Page 1
PHP8 <<Attribute>>
2020-05-16 #phpkansai
【オンライン】関西PHP勉強会
公開日:
by USAMI Kenta @tadsan
にオンラインのビデオ会議で開催された『関西PHP勉強会』でライトニングトーク(5分)として発表しました。
PHP8 <<Attribute>>
2020-05-16 #phpkansai
【オンライン】関西PHP勉強会
お前誰よ
うさみけんた (@tadsan)
/ Zonu.EXE
近況
3月から 氏んでた
最近は
やや元気
PHPカンファレンス関西 にはPHP-Parserの話を しようと応募してました
はじめに
今回紹介する内容に
よって今すぐ何かが変 わることはあまりない
少なくともコードを
PHP7系から8に移行
できないと使えない
これから一年くらい
かけて対応するツールや フレームワークも徐々に
出てくると思う
PHP8時代に心の 準備だけしておこう
さて
RFC
PHPへの 変更提案
全てのPHPへの 変更はここで議決
ここを観察すれば 次のPHPがわかる
ウォッチ
してますか?
@PHPRFCBot
今年12月にリリース予 定のPHP8.0に向けて さまざまな機能が提案
Feature freezeは
7月だが既にPHP8向け
にいろいろ決まってる
さて
RFCは受理された が、実装はまだマー
ジされてない
過去何度も提案されて
きたが今回の仕様で ようやく受理された
そもそも
これは何だ
このRFCはクラス・プロパティ・関数・ メソッド・引数および定数の宣言に対 する構文的メタデータの構造化された 形式として「アトリビュート」を提案 します。アトリビュートによって宣言 に直接埋め込まれた構成ディレクティ
ブを定義できます。
似たようなコンセプトは「アノテーション」 としてJavaに、「アトリビュート」として C#・C++・Rust・Hackに、そして 「デコレータ」としてPython・JavaScript
にあります。
attributeの定訳とし
ては「属性」。直接関係な いが同じ用語としては HTMLでも非常に重要 な概念。<a href="...">
これまでPHPは構造化されていない形 式のメタデータとしてDoc-comment だけを提供しています。ただ、Doc- commentは単なる文字列であり、構 造化情報を保持するための @ ベースの 擬似言語がさまざまなPHPサブコミュ ニティによって提案されてきました。
Doc-commentは
リフレクションAPI経由で
実行時に文字列として
取得できる
実行時に影響するこ ともあるし、しないこ ともある特殊なやつ
/**
* これ
*/
/**
*
@return int
*/
/**
*
@phpstan-return 1|2
*/
/**
*
@deprecated
*/
/**
*
@Inject
*/
/**
*
@Inject(optional=true)
*/
各プロジェクトが 雰囲気で定義してる
各プロジェクト固有タグは @phan-param みたいに
共通のタグにprefixを
つけたりアノテーションを \ で名前空間で区切ってる
文字列を解析してるだけ だからPHPに存在しない 名前付き引数も好き勝手
に使えるぜ!!!11
‒ PHPerKaigi 2020 (Feb 9, 2020)
大雑把に言うと
IDEや静的解析のヒント
実行時メタプログラミング
に分類できる
なんとなくの風潮として
@tag はタグ、
@Anno("arg", attr=true)は
アノテーションと呼び分け
あくまで「なんとなく」で あって、各サブコミュニティ が勝手に実装してるだけ なので厳密な定義はない
区別はかなり曖昧だが PSR-19はタグカタログ であり、アノテーション
カタログではない
どちらにせよ、PHPス クリプトに書く以上の 付加情報を記述できる
あるいは実装から分離して
アノテーションとして
記述することでAOPを実現
実行時メタプログ
ラミングの温床
例:
Go! AOP
そんなわけで
Attributeが入ると
/**
* @ExampleAttribute
*/
class Foo
{
// ...
}
<<ExampleAttribute>>
class Foo
{
// ...
}
// この記法は不採用
@:ExampleAttribute
class Foo
{
// ...
}
Doc-commentから取得 できるのは文字列なので、
実行時に活用するには
それを構文解析する必要
AttributeはDoc-
commentと同じように実 行時に取得でき、構造化さ
れており構文解析不要
好き勝手な記法が使え るタグ/アノテーション と違ってAttributes v2 仕様は単純な関数呼び 出し風構文と静的な式
静的な式 = PHPで有効な
式のうちリテラルと定数 と演算子式で解決できる
(実行時に変わらない)
たぶんPHP-Parserから もリフレクションと似た
APIが用意されて
簡単に取得できるだろう
アトリビュートはク
ラスと同じようにuse
で名前解決できる
アトリビュートはクラ
スにマッピングし、
Reflectionから
インスタンスがとれる
アトリビュートクラス
<<PhpAttribute>>
class MyAttr
{
function __construct($arg){ // 特にやることがなければ
// 実行時には何もしなくていい
}
}
ある意味ではコメントと 同じで、取得されない限り Attributeは実行に影響を
及ぼさない
先程のAttributeクラス は静的解析のためのヒン トであって必須ではない
その意味でPythonの
デコレータとは
全然違う
アトリビュートを加味し てインスタンスを生成す る実行時のファクトリー またはクラスローダーで 近似させることはできる
明確な分類はできない
が、タグよりもアノテー
ション系の方がアトリ
ビュートで表現しやすい
PHPコンパイラ(処理系) のためのアトリビュート があることが示唆されて いる(詳細はRFC範囲外)
PHP
やるじゃん
ほんとに?
🤔
誰のための
アトリビュート?
コンパイラアトリビュー ト(処理系への指示)は
なんとなくわかる
ユーザーランドアト
リビュートは…?
ユースケース
は…?
RFCで実例が 紹介されている
これはわかる
これも… まあまあ
これは… そうなるね
ここまでくると…
もうつらたん
DSLを喜んで覚え直し
たいひとは居るのか?
🙃
移行対象ではなく例とし て考えれば、アノテーショ ンベースDSLの新規実装 コストは多少下がってそう
とはいえライブラリは既
にあるし、コードイン ジェクションもキャッ
シュ機構があるので実行 時コストには影響しない
実はPHP RFC:
Named Argumentsも 復活してPHP8に向けて 議論されそうな雰囲気が あるので影響あるかもね
<<Deprecated>>
アトリビュートの 実際の利用例とし ての新しいRFC
trigger_error(E_DEPRE CATED) 相当のコードを 生成する実行エンジン組 み込みのアトリビュート
言語組み込みのアトリ
ビュートがある意義もわ かるし、ユーザーランド で再現もめんどいので助
かるといえば助かる
関数やメソッド以外 にプロパティや定数 の非推奨化もできる
が、メーリングリス トでは存在意義につ
いて割と揉めてる
ついでに引数へのア トリビュートの付け かたについても議論
普通の実装
function f( $arg1, $arg2
){}
引数の非推奨化
function f( $arg1,
$arg2
<<Deprecated>>
){}
引数のアトリビュート
ってほんとに
必要なんですか…
そもそも名前空間
\Php\Attributes
\Deprecated
じゃなくていいの?
Attributesのfuture
scopeの段階では
名前空間がついてたのに、 しれっとグローバル名前
空間に移動している
Attributeが 解決できない
問題
/** @duplicated */
アノテーション名を
タイプミスすると
(上手に静的解析しない限り) 実行時に無視される
<<Duplicated>> アトリビュート名を
タイプミスすると (静的解析しない限り)
実行時に無視される
あと単純に名前空間との
相性が悪くて、IDEや
静的解析を使ってないと
useし忘れて無意味な
おまじないとして残り…
この問題はアノテー ションベースAOPで 結構深刻だと思うんで すけど皆さんどうやっ
て解決してるんだろ
全部のタグ/アノテー ションがアトリビュー
トに移行されるの?
されない
と思う
いままでのタグ
/** */
@param 1|2 $arg
function f( int $arg1
){}
アトリビュートで置換
(イメージ)
use PHPStan\Param as param;
function f(
int $arg1
<<param("1|2")>>
){}
IDEの入力補完があっ
たとしても書きにくい
🙃
Attributeの
明日はどっちだ
PHP先生の
次回作に
ご期待ください