さあ大変です。PHP 8.2において動的プロパティが廃止(Deprecated)となりました。PHP 9.0ではErrorExceptionが投げられるようです。動的プロパティをたくさん使っているLaravelのプログラムは大丈夫なのでしょうか?

動的プロパティが廃止とはどういうこと?

空のクラスを作成します。

namespace App\Models;

class Person
{
    //
}

PHP 8.1では、好き勝手に動的プロパティを作成できます。

> use App\Models\Person;
> $person = new Person;
= App\Models\Person {#5068}

> $person->first_name = 'Joe';
= "Joe"

> $person->first_name;
= "Joe"

しかし、同様なコードの実行をPHP 8.2下で行うと、

> use App\Models\Person;
> $person = new Person;
= App\Models\Person {#5068}

> $person->first_name = 'Joe';

   DEPRECATED  Creation of dynamic property App\Models\Person::$first_name is deprecated.

= "Joe"

と、しっかり廃止のエラーが表示されます。Deprecated(廃止)なのでDisabled(無効)になったわけではなくエラーとはならずに警告のみです。
つまり、実行はされているので値はGETできます。

> $person->first_name;
= "Joe"

もちろん、動的プロパティでなくプロパティがクラスで予め宣言されているなら問題ありません。

namespace App\Models;

// 以下はModelを継承していないことに注意
class Person
{
    public string $first_name;
}

と定義したなら、以下のようにfirst_nameをセットしても、警告なしです。

> use App\Models\Person;
> $person = new Person;
= App\Models\Person {#5068
    +first_name: ? string,
  }

> $person->first_name = 'Joe';
= "Joe"

PHP 8.2以降で動的プロパティに対応するには、どうしたらよいのでしょう?

マジックメソッドを使う

前回説明したマジックメソッドを使用するなら問題ありません。

namespace App\Models;

// 以下はModelを継承していないことに注意
class Person
{
    protected array $attributes = [];

    // プロパティの値を取得
    public function __get(string $key ) : ?mixed
    {
        if (isset($this->attributes[$key])) {
            return $this->attributes[$key];
        }

        return null;
    }

    // プロパティを設定
    public function __set(string $key, mixed $value)
    {
        $this->attributes[$key] = $value;
    }
}

ということは、LaravelのEloquentやCollectionを使用したコードを書き換える必要はなしです。良かったです。安堵!

stdClassを使う

stdClassを使っても動的プロパティの作成が警告なしに可能となります。

> $person = new StdClass;
= {#5072}

> $person->first_name = 'Joe';
= "Joe"

さらに、stdClassを継承してクラスを作成してもOKです。

namespace App\Models;

use stdClass;

class Person extends stdClass;
{
    //
}

Attributeを使う

PHP8.0 から導入されたAttributeを使用しても動的プロパティの作成が可能です。

つまり、

namespace App\Models;

// 以下は、動的プロパティ許可としています
#[\AllowDynamicProperties]
class Person
{
    //
}

参照

混乱してはいけないLaravelの動的プロパティ – Eloquent編
混乱してはいけないLaravelの動的プロパティ – Collection編
混乱してはいけないLaravelの動的プロパティ – 裏側編

メルマガ購読の申し込みはこちらから。

By khino