(jp) =
PHP 8.1 で追加された機能は些細なことのように思えるかもしれませんが、多くの人々に日常的に大きな影響を与えると思われる機能です。 では、この「イニシャライザ RFC の新機能」とは何ですか? 例を見てみましょう。 私たちは皆、次のようなコードを書きました:
class MyStateMachine
public function __construct(
private ?State $state = null,
)
$this->state ??= new InitialState();

このステート マシンの例では、次の 2 つの方法でクラスを構築します。 と と それなし 初期状態。 構築すれば それなし デフォルトの状態を設定します。 もちろん、PHP はパラメーター リストで初期値を直接設定することをサポートしていますが、プリミティブ型に対してのみサポートしています。 たとえば、ステート マシンが内部でオブジェクトの代わりに文字列を使用する場合、そのコンストラクタを次のように記述できます。
class MyStateMachine
public function __construct(
private string $state = 'initial',
)
したがって、PHP 8.1 では、同じ「デフォルト値」構文をオブジェクトにも使用できます。 言い換えれば:あなたは使用することができます new デフォルトの引数 (「初期化子」の一例) の場合:
class MyStateMachine
public function __construct(
private State $state = new InitialState(),
)
ただし、「初期化子」はパラメーターのデフォルト値以上のものです。RFC からの簡単な説明を次に示します。
この RFC は、パラメーターのデフォルト値、属性引数、静的変数初期化子、およびグローバル定数初期化子内で新しい式を使用できるようにすることを提案しています。
あなたはそれを正しく読んでいます: 属性もこのリストにあります! 属性を使用してプロパティの入力を検証する単純な検証ライブラリを想像してみてください。 おそらく、次のような配列要素を検証できるはずです。
class CreateEmailsRequest extends FormRequestData
#[ValidArray(
email: [new Required, new ValidEmail],
name: [new Required, new ValidString],
)]
public array $people;
PHP 8.1 より前では、この種のコードを書くことはできませんでした。 new 属性では、それらが評価される方法のために、しかし今では可能です!
言及する価値のあるいくつかの重要な詳細を見てみましょう。
# 必要なときだけ構築
このような「新しい価値」は、本当に必要なときにしか構築されません。 つまり、最初の例では、PHP は新しいオブジェクトのみを作成します。 InitialState 引数が指定されていない場合:
class MyStateMachine
public function __construct(
private State $state = new InitialState(),
)
new MyStateMachine(new DraftState());
new MyStateMachine();
たとえば、属性の場合、オブジェクトは次の場合にのみ作成されます。 newInstance リフレクション属性で呼び出されます。
# クラスのプロパティにはありません
また、使用できないことも知っておく必要があります。 new クラス プロパティのデフォルト値として。 この機能をサポートすると、オブジェクトのシリアル化とシリアル化解除などの際に、多くの予期しない副作用が発生します。
class MyStateMachine
private State $state = new InitialState();
幸いなことに、デフォルト値を許可するプロパティをプロモートしました。これは、PHP がプロパティ プロモーション構文をトランスパイルし、実際のプロパティではなくコンストラクタ引数にデフォルト値を保持するためです。
トランスパイルされたバージョンは次のようになります。
class MyStateMachine
private State $state;
public function __construct(
State $state = new InitialState(),
)
$this->state = $state;
# 入力制限あり
すでに推測されているかもしれませんが、初期化子で新しいオブジェクトを構築するときに、限られた入力セットしか渡すことができません。 たとえば、変数、スプレッド演算子、匿名クラスなどは使用できません。それでも、これは非常に歓迎すべき追加です!
PHP は更新のたびにどんどん良くなっています。 これらの変更は、言語に新しい機能を追加するものではないため、厳密には必要ではないと主張する人もいます。 だけどあの人達 行う 私たちの日々の開発者の生活を少しだけ楽にしてくれます。私は最近、PHP について本当に気に入っています!
//platform.twitter.com/widgets.js