Skip to content

PHP8 <<Attribute>>

公開日:

オンラインビデオ会議で開催された『関西PHP勉強会』でライトニングトーク(5分)として発表しました。

Download PDF

スライドテキスト

Page 1

PHP8 <<Attribute>>

2020-05-16 #phpkansai【オンライン】関西PHP勉強会

Page 2

お前誰よ

  • うさみけんた (@tadsan) / Zonu.EXE
  • GitHub/Packagistでは id: zonuexe
  • ピクシブ株式会社 pixiv運営本部
  • Emacs Lisper, PHPer, Rubyist
  • Emacs PHP Modeのメンテナ引き継ぎました
  • 好きなリスプはEmacs Lispです
  • Qiitaに記事を書いたり変なコメントしてるよ

Page 3

Page 4

Page 5

近況

Page 6

月から氏んでた

Page 7

最近はやや元気

Page 8

PHPカンファレンス関西にはPHP-Parserの話をしようと応募してました

Page 9

はじめに

Page 10

今回紹介する内容によって今すぐ何かが変わることはあまりない

Page 11

少なくともコードをPHP7系から8に移行できないと使えない

Page 12

これから一年くらいかけて対応するツールやフレームワークも徐々に出てくると思う

Page 13

PHP8時代に心の準備だけしておこう

Page 14

さて

Page 15

RFC

Page 16

PHPへの変更提案

Page 17

全てのPHPへの変更はここで議決

Page 18

ここを観察すれば次のPHPがわかる

Page 19

ウォッチしてますか?

Page 20

Page 21

@PHPRFCBot

Page 22

今年12月にリリース予定のPHP8.0に向けてさまざまな機能が提案

Page 23

Feature freezeは7月だが既にPHP8向けにいろいろ決まってる

Page 24

さて

Page 25

Page 26

RFCは受理されたが、実装はまだマージされてない

Page 27

過去何度も提案されてきたが今回の仕様でようやく受理された

Page 28

そもそもこれは何だ

Page 29

Page 30

このRFCはクラス・プロパティ・関数・メソッド・引数および定数の宣言に対する構文的メタデータの構造化された形式として「アトリビュート」を提案します。アトリビュートによって宣言に直接埋め込まれた構成ディレクティブを定義できます。

Page 31

Page 32

似たようなコンセプトは「アノテーション」としてJavaに、「アトリビュート」としてC#・C++・Rust・Hackに、そして「デコレータ」としてPython・JavaScriptにあります。

Page 33

attributeの定訳としては「属性」。直接関係ないが同じ用語としてはHTMLでも非常に重要な概念。<a href="...">

Page 34

これまでPHPは構造化されていない形式のメタデータとしてDoc-commentだけを提供しています。ただ、Doc-commentは単なる文字列であり、構造化情報を保持するための @ ベースの擬似言語がさまざまなPHPサブコミュニティによって提案されてきました。

Page 35

Doc-commentはリフレクションAPI経由で実行時に文字列として取得できる

Page 36

実行時に影響することもあるし、しないこともある特殊なやつ

Page 37

/**

* これ

*/

Page 38

/**

*

@return int

*/

Page 39

/**

*

@phpstan-return 1|2

*/

Page 40

/**

*

@deprecated

*/

Page 41

/**

*

@Inject

*/

Page 42

/**

*

@Inject(optional=true)

*/

Page 43

各プロジェクトが雰囲気で定義してる

Page 44

各プロジェクト固有タグは@phan-param みたいに共通のタグにprefixをつけたりアノテーションを\ で名前空間で区切ってる

Page 45

文字列を解析してるだけだからPHPに存在しない名前付き引数も好き勝手に使えるぜ!!!11

Page 46

‒ PHPerKaigi 2020 (Feb 9, 2020)

Page 47

大雑把に言うとIDEや静的解析のヒント実行時メタプログラミングに分類できる

Page 48

なんとなくの風潮として

@tag

タグ

@Anno("arg", attr=true)は

アノテーション

と呼び分け

Page 49

あくまで「なんとなく」であって、各サブコミュニティが勝手に実装してるだけなので厳密な定義はない

Page 50

区別はかなり曖昧だがPSR-19はタグカタログであり、アノテーションカタログではない

Page 51

どちらにせよ、PHPスクリプトに書く以上の付加情報を記述できる

Page 52

あるいは実装から分離してアノテーションとして記述することでAOPを実現

Page 53

実行時メタプログラミングの温床

Page 54

例:Go! AOP

Page 55

そんなわけでAttributeが入ると

Page 56

/**

* @

ExampleAttribute

*/

class Foo

{

// ...

}

Page 57

<<

ExampleAttribute

>>

class Foo

{

// ...

}

Page 58

// この記法は不採用

@:

ExampleAttribute

class Foo

{

// ...

}

Page 59

Doc-commentから取得できるのは文字列なので、実行時に活用するにはそれを構文解析する必要

Page 60

AttributeはDoc-commentと同じように実行時に取得でき、構造化されており構文解析不要

Page 61

好き勝手な記法が使えるタグ/アノテーションと違ってAttributes v2仕様は単純な関数呼び出し風構文と静的な式

Page 62

静的な式 = PHPで有効な式のうちリテラルと定数と演算子式で解決できる(実行時に変わらない)

Page 63

たぶんPHP-Parserからもリフレクションと似たAPIが用意されて簡単に取得できるだろう

Page 64

アトリビュートはクラスと同じようにuseで名前解決できる

Page 65

アトリビュートはクラスにマッピングし、Reflectionからインスタンスがとれる

Page 66

アトリビュートクラス

<<PhpAttribute>>

class MyAttr

{

function __construct($arg){

// 特にやることがなければ

// 実行時には何もしなくていい

}

}

Page 67

ある意味ではコメントと同じで、取得されない限りAttributeは実行に影響を及ぼさない

Page 68

先程のAttributeクラスは静的解析のためのヒントであって必須ではない

Page 69

その意味でPythonのデコレータとは全然違う

Page 70

アトリビュートを加味してインスタンスを生成する実行時のファクトリーまたはクラスローダーで近似させることはできる

Page 71

明確な分類はできないが、タグよりもアノテーション系の方がアトリビュートで表現しやすい

Page 72

PHPコンパイラ(処理系)のためのアトリビュートがあることが示唆されている(詳細はRFC範囲外)

Page 73

PHPやるじゃん

Page 74

ほんとに?

🤔

Page 75

誰のためのアトリビュート?

Page 76

コンパイラアトリビュート(処理系への指示)はなんとなくわかる

Page 77

ユーザーランドアトリビュートは…?

Page 78

ユースケースは…?

Page 79

RFCで実例が紹介されている

Page 80

これはわかる

Page 81

これも… まあまあ

Page 82

これは… そうなるね

Page 83

ここまでくると…

Page 84

もうつらたん

Page 85

DSLを喜んで覚え直したいひとは居るのか?

🙃

Page 86

移行対象ではなく例として考えれば、アノテーションベースDSLの新規実装コストは多少下がってそう

Page 87

とはいえライブラリは既にあるし、コードインジェクションもキャッシュ機構があるので実行時コストには影響しない

Page 88

実はPHP RFC:Named Argumentsも復活してPHP8に向けて議論されそうな雰囲気があるので影響あるかもね

Page 89

<<Deprecated>>

Page 90

Page 91

アトリビュートの実際の利用例としての新しいRFC

Page 92

trigger_error

(E_DEPRE

CATED)

相当のコードを生成する実行エンジン組み込みのアトリビュート

Page 93

言語組み込みのアトリビュートがある意義もわかるし、ユーザーランドで再現もめんどいので助かるといえば助かる

Page 94

関数やメソッド以外にプロパティや定数の非推奨化もできる

Page 95

が、メーリングリストでは存在意義について割と揉めてる

Page 96

ついでに引数へのアトリビュートの付けかたについても議論

Page 97

普通の実装

function f(

$arg1,

$arg2

){}

Page 98

引数の非推奨化

function f(

<<Deprecated>>

$arg1,

$arg2

){}

Page 99

引数のアトリビュートってほんとに必要なんですか…

Page 100

そもそも名前空間

\Php\Attributes

\Deprecated

じゃなくていいの?

Page 101

Attributesのfuture scopeの段階では名前空間がついてたのに、しれっとグローバル名前空間に移動している

Page 102

Attributeが解決できない問題

Page 103

/** @duplicated */

アノテーション名をタイプミスすると(上手に静的解析しない限り)実行時に無視される

Page 104

<<Duplicated>>

アトリビュート名をタイプミスすると(静的解析しない限り)実行時に無視される

Page 105

あと単純に名前空間との相性が悪くて、IDEや静的解析を使ってないとuseし忘れて無意味なおまじないとして残り…

Page 106

この問題はアノテーションベースAOPで結構深刻だと思うんですけど皆さんどうやって解決してるんだろ

Page 107

全部のタグ/アノテーションがアトリビュートに移行されるの?

Page 108

されないと思う

Page 109

いままでのタグ

@param 1|2 $arg

/**

*/

function f(

int $arg1

){}

Page 110

(イメージ)アトリビュートで置換

use PHPStan\Param as param;

function f(

<<param("1|2")>>

int $arg1

){}

Page 111

IDEの入力補完があったとしても書きにくい

🙃

Page 112

Attributeの明日はどっちだ

Page 113

PHP先生の次回作にご期待ください