【PHP8.x】flagsプロパティの使い方

flagsプロパティの使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

flagsプロパティは、PHP 8で導入されたAttribute(属性)クラスに属し、その属性が適用できるプログラム要素の種類を示す情報を保持するプロパティです。

このプロパティには、定義された属性が、PHPのどのようなコード要素に付与(適用)できるかという情報が格納されます。具体的には、Attribute::TARGET_CLASS(クラス)、Attribute::TARGET_METHOD(メソッド)、Attribute::TARGET_PROPERTY(プロパティ)、Attribute::TARGET_FUNCTION(関数)、Attribute::TARGET_CONSTANT(定数)、Attribute::TARGET_PARAMETER(パラメータ)、Attribute::TARGET_ALL(すべて)といったPHPが提供する定数が、組み合わされた形式で設定されます。

例えば、ある属性がクラスとメソッドの両方に適用可能である場合、このflagsプロパティにはAttribute::TARGET_CLASSAttribute::TARGET_METHODが組み合わされた値が保持されます。これにより、一つの属性定義で複数の適用対象を同時に指定することが可能になります。

開発者がカスタム属性を定義する際、このflagsプロパティに適切なターゲット情報を設定することで、その属性が意図しない場所で使用されるのを防ぎ、コードの整合性と安全性を高めることができます。flagsプロパティは、属性の適用範囲を厳密に制御し、コードの意図を明確にする上で非常に重要な役割を担っています。

構文(syntax)

1#[Attribute(flags: Attribute::TARGET_CLASS)]
2class MyCustomAttribute
3{
4    //
5}

引数(parameters)

戻り値(return)

int

Attributeクラスのflagsプロパティは、属性に設定されたフラグを表す整数値を返します。

サンプルコード

PHP AttributeでEnumフラグを扱う

1<?php
2
3/**
4 * Enum を Attribute フラグとして使用する例
5 */
6
7enum Permission: int
8{
9    case Read = 1;
10    case Write = 2;
11    case Execute = 4;
12}
13
14#[Attribute(flags: true)]
15class AccessControl
16{
17    public function __construct(public Permission $permission) {}
18}
19
20#[AccessControl(Permission::Read)]
21class Document
22{
23    // ...
24}
25
26$reflection = new ReflectionClass(Document::class);
27$attributes = $reflection->getAttributes(AccessControl::class);
28
29foreach ($attributes as $attribute) {
30    $instance = $attribute->newInstance();
31    echo "Permission: " . $instance->permission->name . PHP_EOL; // Permission: Read
32    echo "Value: " . $instance->permission->value . PHP_EOL; // Value: 1
33}

このサンプルコードは、PHP 8 で導入された Attribute 機能と Enum を組み合わせて、フラグとして属性を定義する方法を示しています。

まず、Permission という Enum を定義しています。この Enum は int 型をベースとし、Read, Write, Execute という3つのケースを持ち、それぞれ 1, 2, 4 という整数値を割り当てています。これらの値は、ビット演算で組み合わせることを想定したフラグとして利用できます。

次に、AccessControl という Attribute クラスを定義しています。#[Attribute(flags: true)] という記述により、このクラスが Attribute として使用されることを宣言しています。flags: true は、この Attribute が Enum のフラグを受け取ることを示します。コンストラクタでは、Permission Enum を引数として受け取り、プロパティ $permission に格納します。

Document クラスは、#[AccessControl(Permission::Read)] という Attribute を持っています。これにより、Document クラスに AccessControl Attribute が付与され、その引数として Permission::Read が渡されます。

コードの後半部分では、Reflection API を使用して Document クラスの Attribute 情報を取得しています。ReflectionClassDocument クラスをリフレクションし、getAttributes(AccessControl::class)AccessControl Attribute を取得します。

最後に、取得した Attribute インスタンスから $permission プロパティの値を取り出し、その名前 (name) と値 (value) を出力しています。この例では、Permission: ReadValue: 1 が出力されます。

このように、Attribute と Enum を組み合わせることで、クラスやメソッドに付与するメタデータをより柔軟かつ型安全に定義することができます。flags: true を使用することで、Enum のフラグを Attribute の引数として扱うことが可能になり、より表現力豊かなコードを実現できます。

#[Attribute(flags: true)]は、Attributeクラスを定義する際に、enumをフラグとして扱えるようにするためのものです。flags: trueを指定することで、Attributeの引数に複数のenum値をビット演算で組み合わせた値を渡せるようになります。このサンプルコードでは、Permission enumの値をそのままAttributeに渡していますが、複数のPermissionを組み合わせる場合は、Permission::Read | Permission::Writeのようにビット演算子を使用します。また、enumの各ケースには一意な整数値を割り当てる必要があります。値が重複すると、意図しない動作になる可能性があるため注意が必要です。Reflection APIを利用してAttributeの情報を取得する際、newInstance()でAttributeクラスのインスタンスを生成してから、プロパティにアクセスする必要があります。