
はじめに
最近Laravelのコードを見ると、引数にアトリビュートが付いていることがあります。
例えば Illuminate\Auth\SessionGuard::rehashPasswordIfRequired
のコードは以下の通りです。
protected function rehashPasswordIfRequired(AuthenticatableContract $user, #[\SensitiveParameter] array $credentials)
{
 if ($this->rehashOnLogin) {
 $this->provider->rehashPasswordIfRequired($user, $credentials);
 }
}
引数の $credentials
に #[\SensitiveParameter]
というアトリビュート付いていることが分かります。
このようなPHP標準アトリビュートが他にもないかということで、調査してみました。
PHP 8.4現在の標準アトリビュート例
#[\SensitiveParameter]
#[\SensitiveParameter]
を付けたパラメーターは、パラメーター値をエラートレースやログに表示しないようになります。
function test(string $name, #[\SensitiveParameter] string $secret) {
 throw new Exception("Error occurred");
}

try {
 test('Alice', 'super-secret');
} catch (Throwable $e) {
 echo $e;
}
Exception: Error occurred in script.php:3
Stack trace:
#0 script.php(7): test('Alice', Object(SensitiveParameterValue))
機密情報が含まれるパラメーターに対してこの設定を付けることで、「機密データがログに漏れないこと」を担保できます。
例えばクレジットカード番号をDBに保存しないのは当然ですが、ログの方に記録されていたというような事故を減らせます。
#[\ Override ]
#[\Override]
を付けたメソッドは、親クラスやインターフェースに 同名のメソッドが存在しなければ 、PHPがFatal Errorを出します。
class ParentClass {
 public function greet() {}
}

class ChildClass extends ParentClass {
 #[\Override]
 public function grete() {} // ← 名前を間違えた
}
Fatal error: Method ChildClass::grete() has #[\Override] attribute, but no matching parent method found
Java 5の頃を思い出す、なじみ深い機能です。PHP 8.3(2023年)になってついに登場です。
#[\ Deprecated ]
PHP 8.4から、 #[Deprecated]
アトリビュートを使って、機能の実行時にDeprecatedを出すことが出来ます。
#[\Deprecated(message: "Use doSomethingNew() instead", since: "8.4")]
function doSomethingOld() {
 // legacy code
}
以前は静的解析ツール用にPHPDocでマークするのが基本でしたが、ついに実行時に警告を出すことが出るようになりました。
/**
 * @deprecated Use doSomethingNew() instead.
 */
function doSomethingOld() {
 // legacy code
}
#[\ReturnTypeWillChange]
PHP 8.1から、インターフェースと戻り値の型があっていなかった場合にDeprectedが出るようになりました。それを抑制することが出来ます。
class MyClass implements \ArrayAccess {
 #[\ReturnTypeWillChange]
 public function offsetGet($offset) {
 // 実装
 }
}
一開発者からすると「使わずに型定義をすれば良いだけなのでは?」と思うかもしれませんが、これを使うと、PHP 8.0以下でも動く上にPHP 8.1でDeprecatedが出ないコードを書く事が出来ます。
#[ReturnTypeWillChange] // PHP 8.1 用
public function offsetGet($offset) /* PHP 8.0 以前の型なし互換 */
#[\ AllowDynamicProperties ]
PHP 8.2から、動的プロパティを追加するとDeprecatedが出るようになりました。それを抑制することが出来ます。
#[\AllowDynamicProperties]
class MyClass {}

$obj = new MyClass();
$obj->foo = 'bar'; // OK
今時の子は嫌だと思うかも知れませんが、PHPの特徴でもある柔軟性が必要であると考える人も一定数います。
この先は動的プロパティは非推奨になっていますが、明示的に許可すれば使えるということになります。
昔のPHP(特に5系)は、めちゃくちゃに書いても動く・誰でも書けるという印象が強かったのですが、そうでは無い方向性になりそうですね。
これはスコープや封じ込めなどを導入し始めている、CSSと同じ方向性を感じます。
さいごに
ライブラリで定義されたアトリビュートの活躍の場が増えていますが、PHP標準として定義済みのアトリビュートもいくつかあります。
今のところ数は少ないですが、覚えておいて損はないかと思います。