Quantcast
Channel: PHP8タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 539

PHP 8 で導入される Attributes 事始め

$
0
0

Attributes とは

紆余曲折1ありましたが、 PHP 8 で Attributesという機能が提供されることが決まりました。

この Attributesとは、

  • Java で言う Annotations
  • C#, C++, Rust, Hack で言う Attributes
  • Python, JavaScript で言う Decorators

を指します。つまりどんなコードかというと、下記です。

return// ↓コレ#[Get('/')]fn()=>['Hello'=>'World'];

記法はPHP7以下では行コメントとみなされるので、シンタックスハイライトで強調はされませんがエラーにもなりません。地味にうれしい。

似たようなものは既に見たことがあると思います。

BlogController.php
useSymfony\Component\Routing\Annotation\Route;classBlogController{// ↓コレ/**
   * @Route("/blog", name="blog_list")
   */publicfunctionlist(){return[];}}

これは現在 「アノテーション」と呼ばれ、 doctrine/annotationsを実装として使われることが非常に多いです(依存パッケージが約1,500個)。既に展開されているアノテーションと混同しないようにするため、アトリビュートと名付けられたようです。

簡単に言えば、 「クラスや関数、メソッドやオブジェクトなどにメタ情報を付加する機能」です。

これで何を実現出来るかというと、 「フレームワークやライブラリが、アプリケーションコードに付加されたメタ情報を読み取ることで、アプリケーションコードのロジックを調整する」ことが出来るようになります。

サンプルでは Symfony のルーティングで「/blog パスは BlogController::list メソッドを利用するよ」というメタ情報が付加されています。

また、別のサンプルとして doctrine/ormでの利用方法を見てみましょう。

Product.php
<?phpuseDoctrine\ORM\AnnotationasORM;/**
 * @ORM\Entity @ORM\Table(name="products")
 **/classProduct{/** @ORM\Id @ORM\Column(type="integer") @ORM\GeneratedValue **/private$id;/** @ORM\Column(type="string") **/private$name;// .. (other code)}

このクラスがエンティティであること、DBのカラムとプロパティを紐づけることなどがメタ情報(コメントアノテーション)として書かれています。

Attributes が実装されて何がうれしい?

既にコメントアノテーションが多くの PHP プロジェクトで利用されていて、機能的にはほとんど同じに見えます。では、何故今さら言語機能として Attributes が採用されたのでしょうか。

パフォーマンスの向上

アノテーションの Doc コメントは文字列で取得することしか出来ず、パースするのに時間がかかります。そのため doctrine/annotations では一度取得したアノテーションをキャッシュすることが可能になっています。

Attributes の形式だと Reflectionから取得出来るようになるので、パースの時間を省略することが出来ます。

取得容易性の向上

ReflectionClass::getAttributes()などのメソッドで、 Reflectionから簡単に Attributes を取り出せるようになったので、 Doc コメントアノテーションに比べ取得が格段に簡単になります。

明確な型インスタンス

Attribute::newInstance()メソッドを使って Attributeクラスのインスタンスを生成することが出来るため、明確な型を使って利用ロジックを実装することが出来ます。そのため、静的解析やIDE補完などが容易に行えるようになります。

PHP Core や Extensions での利用

PHP拡張の実装時に Attributes を使うことによって、拡張機能により実装された Attributes をアプリケーションコードに落とし込むことが出来るようになります。

// 例えばusePhp\Attributes\Deprecated;#[Deprecated("Use bar() instead")]functionfoo(){}foo();// PHP Deprecated: Function foo is deprecated in test.php on line 5

このように、以前は Doc コメントで拘束性のなかった機能を、実際にランタイムでエラー出力出来るような形式に変えることが出来ます。

// 現状 Attributes なしで記述した場合classRequestSubscriberimplementsEventSubscriberInterface{publicstaticfunctiongetSubscribedEvents():array{// 分かりづらい static 実装ですreturn[RequestEvent::class=>'onKernelRequest'];}publicfunctiononKernelRequest(RequestEvent$event){}}// Attributes を使うと#[Attribute]classListener{public$event;publicfunction__construct(string$event){$this->event=$event;}}classRequestSubscriber{// このメソッドが RequestEvent を listen していることが明白です#[Listener(RequestEvent::class)]publicfunctiononKernelRequest(RequestEvent$event){}}

このように、 Attributes を活用することにより、実装に型安全な拡張性を持たせることが出来るようになります。

誰が Attributes を実装するの?

主なユースケースとして提案されているのが、

  • PHP Core 実装として
  • PHP extension 実装として
  • 各種ライブラリ実装として
  • 各種フレームワーク実装として

です。つまりアプリケーションコード側は Attributes を実装する機会はあまりないかなと思います(もちろん利用するケースは増えていくと思います)。

なのでアプリケーションコードを実装する人は、 Attributes の細かい実装などに詳しくなる必要はありません。

ライブラリを実装している人などは、 PHP 8 時代に向けて Attributes をどう使えば便利になるかなーと研究すると良いと思います。


  1. PHP7.1 で導入しようとしたけど採択されなかったり、 @@Attr, <<Attr>>など様々な記法が入れ代わり立ち代わり採択されて、alpha/beta 段階ではそれぞれのバージョンで異なる実装がなされていました。 


Viewing all articles
Browse latest Browse all 539

Latest Images

Trending Articles