PHP で動的にクラス名を指定する場合、現在いる名前空間が修飾されないため、
クラス名のみで名前空間内のクラスを指定して new するとクラスを見つけられず致命的なエラーになります。
エラーになる例
クラスファイルのパス構成
例えば PSR-0 規約に準拠して以下のような構成で Car クラスと CarCreator クラスを配置していたとします。
- /var/www/sample/Vendor/SampleVendor/Entity
- Car.php
- CarCreator.php
Car.php
SampleVendor\Entity の名前空間に Car クラスを定義します。
<?php
namespace SampleVendor\Entity
class Car {}
CarCreator.php
この状態で Car クラスと同じ名前空間の CarCreator クラスから Car クラスのインスタンスを生成してみます。(autoload.php は既に読み込まれている状態とします。)
<?php
namespace SampleVendor\Entity
class CarCreator {
public function create() {
// 🙆🏻♀️ OKパターン:
// 暗黙的に現在の名前空間が修飾され、問題なくインスタンスの生成ができる
$car = new Car();
// 🙅♀️ NGパターン:
// 名前空間が修飾されずクラスが見つからないためエラー
// Fatal error: Class 'Car' not found in /var/www/...
$className = 'Car';
$car = new $className();
}
}
このエラーを解決するにはどうすればいいでしょうか?
解決方法
完全修飾形式(名前空間まで含めた完全な指定)でクラスを指定するか、Car クラスを別途 use 句で指定することで解決できます。
以下は完全修飾形式でクラスを指定する場合の例です。
<?php
namespace SampleVendor\Entity
class CarCreator {
public function create() {
$className = __NAMESPACE__ . '\\' . 'Car';
$car = new $className();
}
}
マジック定数の __NAMESPACE__ で現在の名前空間名の文字列を取得できるので、これを先頭に付けてクラスを指定します。