【PHP8.x】__constructメソッドの使い方
__constructメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
__constructメソッドは、AllowDynamicPropertiesクラスのインスタンスを初期化するメソッドです。PHP 8.2以降、これまで許容されてきたクラスの動的プロパティ(実行時に宣言されていないプロパティに値を代入すること)の使用は非推奨となり、将来的に廃止される予定です。この変更により、動的プロパティを使用すると非推奨警告が発生するようになりました。
AllowDynamicPropertiesは、このような非推奨警告を一時的に抑制するために提供されているアトリビュート(属性)です。このアトリビュートは、動的プロパティを使用する必要がある特定のクラスに対して付与することで、警告なしで動的プロパティの使用を許可します。
__constructメソッドは、このAllowDynamicPropertiesアトリビュートがコード中で使用された際に、PHPエンジンによって内部的に呼び出されます。このメソッドの主な役割は、アトリビュートのインスタンスを生成し、それが有効であることをPHPエンジンに認識させることです。AllowDynamicPropertiesアトリビュートは、追加の引数を取らないため、この__constructメソッド自体が特別なパラメータを受け取ったり、複雑な初期化処理を行ったりすることはありません。しかし、この内部的な初期化プロセスがあることで、アトリビュートが正しく機能し、動的プロパティの使用を許可する役割を果たすことができるようになっています。これにより、開発者は既存のコードベースをPHP 8.2以降に移行する際の互換性を保ちつつ、将来的な変更への対応を進めることが可能です。
構文(syntax)
1new AllowDynamicProperties();
引数(parameters)
引数なし
引数はありません
戻り値(return)
戻り値なし
戻り値はありません
サンプルコード
PHP 8.0 コンストラクタのプロパティ昇格を実装する
1<?php 2 3declare(strict_types=1); 4 5/** 6 * ユーザー情報を保持するクラス 7 * 8 * PHP 8.0で導入された「コンストラクタのプロパティ昇格」機能を使用しています。 9 * この機能により、コンストラクタの引数にアクセス修飾子(public, protected, private)を 10 * 付けるだけで、プロパティの宣言と初期化を同時に行うことができます。 11 * これにより、コードがより簡潔になります。 12 */ 13class User 14{ 15 /** 16 * コンストラクタ 17 * 18 * @param int $id ユーザーID (読み取り専用) 19 * @param string $name ユーザー名 20 * @param string $email メールアドレス (外部からアクセス不可) 21 */ 22 public function __construct( 23 public readonly int $id, 24 public string $name, 25 private string $email 26 ) { 27 // コンストラクタの本文は空でも、プロパティの宣言と代入は自動的に行われます。 28 } 29 30 /** 31 * ユーザー情報を表示するメソッド 32 */ 33 public function displayInfo(): void 34 { 35 echo "ID: " . $this->id . PHP_EOL; 36 echo "Name: " . $this->name . PHP_EOL; 37 // privateプロパティはクラス内からはアクセス可能です。 38 echo "Email: " . $this->email . PHP_EOL; 39 } 40} 41 42// クラスのインスタンスを生成します。 43// コンストラクタに渡された引数は、自動的に同名のプロパティに代入されます。 44$user = new User(1, 'Taro Yamada', 'taro.yamada@example.com'); 45 46// メソッドを呼び出して、プロパティの値が正しく設定されていることを確認します。 47$user->displayInfo(); 48 49// publicプロパティには直接アクセスできます。 50echo "Public Name: " . $user->name . PHP_EOL; 51 52// readonlyプロパティは変更しようとするとエラーになります。 53// $user->id = 2; // Fatal error: Uncaught Error: Cannot modify readonly property User::$id 54 55// privateプロパティは外部からアクセスしようとするとエラーになります。 56// echo $user->email; // Fatal error: Uncaught Error: Cannot access private property User::$email 57
このPHPコードは、ユーザー情報を扱うUserクラスを定義するサンプルです。PHP 8.0で導入された「コンストラクタのプロパティ昇格」という機能を利用しています。
__constructメソッドは、クラスからインスタンス(オブジェクト)が生成される際に自動的に呼び出される特別なメソッドで、コンストラクタと呼ばれます。このサンプルでは、コンストラクタの引数にpublicやprivateといったアクセス修飾子を直接記述しています。これにより、プロパティの宣言と、引数で受け取った値の代入が同時に行われ、コードを大幅に短縮できます。
具体的には、new User(1, 'Taro Yamada', 'taro.yamada@example.com')と記述するだけで、id、name、emailというプロパティが作成され、それぞれの引数の値が自動で設定されます。public readonlyが付いたidは、一度設定すると変更できない読み取り専用のプロパティです。publicなnameは外部から自由にアクセスできますが、privateなemailはクラスの内部からしかアクセスできません。このコンストラクタはインスタンスの初期化を目的とするため、特定の戻り値はありません。
この機能を使うことで、従来必要だったプロパティの宣言と代入処理を省略できるため、より簡潔で読みやすいクラスを定義することが可能になります。
このサンプルコードで使われているのは、PHP 8.0で導入された「コンストラクタのプロパティ昇格」という機能です。この機能は、コンストラクタの引数にpublicなどのアクセス修飾子を付けることで利用でき、プロパティの宣言と初期化を同時に行います。アクセス修飾子を付け忘れるとプロパティにはならず、通常の引数として扱われるため注意が必要です。また、昇格させたプロパティをクラス内で重複して宣言することはできません。readonlyを付けたプロパティは初期化後に値を変更しようとするとエラーになり、不変の値を保証します。privateなプロパティはクラス外部から直接アクセスできないため、意図しない操作を防ぎ、コードの安全性を高めることができます。
PHP: 親コンストラクタと動的プロパティの継承
1<?php 2 3// PHP 8.2以降で利用可能なAllowDynamicProperties属性をインポートします。 4// この属性は、クラスに動的なプロパティの追加を許可するために使用されます。 5use AllowDynamicProperties; 6 7/** 8 * 親クラスの例です。 9 * このクラスは基本的なプロパティを持ち、コンストラクタで初期化されます。 10 */ 11class ParentClass 12{ 13 protected string $parentMessage; 14 15 /** 16 * ParentClassのコンストラクタ。 17 * 親クラスのプロパティを初期化します。 18 */ 19 public function __construct(string $message) 20 { 21 $this->parentMessage = $message; 22 } 23 24 public function getParentMessage(): string 25 { 26 return $this->parentMessage; 27 } 28} 29 30/** 31 * 子クラスの例です。 32 * ParentClassを継承し、AllowDynamicProperties属性が付与されています。 33 * この属性により、このクラスのインスタンスに定義されていないプロパティを動的に追加できるようになります。 34 */ 35#[AllowDynamicProperties] 36class ChildClass extends ParentClass 37{ 38 protected string $childMessage; 39 40 /** 41 * ChildClassのコンストラクタ。 42 * 43 * @param string $parentMessage 親クラスに渡すメッセージ 44 * @param string $childMessage 子クラス独自のメッセージ 45 */ 46 public function __construct(string $parentMessage, string $childMessage) 47 { 48 // 親クラスのコンストラクタを呼び出し、親クラスの初期化を行います。 49 // これは、子クラスが親クラスの初期化処理を引き継ぐためのPHPの一般的なパターンです。 50 parent::__construct($parentMessage); 51 52 // 子クラス独自のプロパティを初期化します。 53 $this->childMessage = $childMessage; 54 55 // AllowDynamicProperties属性が設定されているため、 56 // クラス定義にないプロパティ (動的プロパティ) を安全に追加できます。 57 // PHP 8.2以降でこの属性がない場合、非推奨の警告が発生する可能性があります。 58 $this->dynamicProperty = "これは子クラスに動的に追加されたプロパティです。"; 59 } 60 61 public function getChildMessage(): string 62 { 63 return $this->childMessage; 64 } 65 66 public function getDynamicProperty(): string 67 { 68 return $this->dynamicProperty; 69 } 70} 71 72// クラスの使用例 73$childObject = new ChildClass("親からの挨拶", "子からの返事"); 74 75echo "親クラスのメッセージ: " . $childObject->getParentMessage() . PHP_EOL; 76echo "子クラスのメッセージ: " . $childObject->getChildMessage() . PHP_EOL; 77echo "動的に追加されたプロパティ: " . $childObject->getDynamicProperty() . PHP_EOL; 78 79?>
このPHPコードは、クラスを継承した際に、親クラスの初期化処理を子クラスから呼び出す方法を示しています。
__constructはコンストラクタと呼ばれ、newキーワードでクラスのインスタンスが生成される時に自動的に実行される特別なメソッドです。主に、プロパティの初期化などに使用されます。
サンプルコードのChildClassはParentClassを継承しています。ChildClassのコンストラクタ内では、まずparent::__construct($parentMessage)を呼び出しています。これは、親クラスであるParentClassのコンストラクタを実行するための記述です。引数として受け取った$parentMessageが親クラスに渡され、親クラスが持つプロパティが正しく初期化されます。その後、子クラス独自のプロパティ初期化処理が続きます。
また、ChildClassに付与された#[AllowDynamicProperties]属性により、$this->dynamicPropertyのように、あらかじめクラス内で定義されていないプロパティを後から動的に追加することが許可されます。このコンストラクタは初期化に必要な2つの文字列を引数として受け取りますが、メソッド自体に特定の戻り値はありません。
子クラスでコンストラクタを定義した場合、親クラスのコンストラクタは自動で実行されません。そのため、サンプルコードのようにparent::__construct()を呼び出し、親クラスの初期化処理を明示的に行う必要があります。これを忘れると、親のプロパティが初期化されず、エラーの原因となります。また、#[AllowDynamicProperties]属性は、PHP 8.2以降で未定義のプロパティを動的に追加することを許可するものです。この属性がないと警告が発生しますが、コードの可読性や保守性を高めるため、プロパティは事前にクラス内で宣言することが推奨されます。