【PHP】Class名を変数に入れてインスタンス化or静的に呼び出す


概要

変数にClass名を入れて、別クラスでインスタンス化 or 静的に呼び出したい

  • 共通で使用するクラス
  • 適当なクラス
  • 基底クラス(今回は登場しません)
  • バリデーションクラス(今回は登場しませんが、staticなvalidate()という関数を持っています。) の4つが前提として存在します。

詰まった時のコード

適当なクラス extends 共通クラス{
// 省略
    // リポジトリのクラス名を返す
    protected function getValidationClassName(): string
    {
        return 'TestClassName';
    }
// 省略
}
共通クラス extends 基底クラス{
// 省略
    $validate_class_name = $this->getValidationClassName();
    $error_validate = $validate_class_name::validate();
    var_dump($error_validate);
// 実行結果////////////////
--> $error_validateを表示しようとするとエラーになる
}

どうやら、$validate_class_name::validate($row_data);の部分でエラーが出ているようです。
ベタ書きで、
$error_validate = TestClassName::validate($row_data);

としたところうまくいきましたが、何が原因なのかわかりませんでした。

クラス名を変数に入れると動かないのか?
PHP: クラスの基礎 - Manual
を見る限りだと、そういうわけでもなさそうです。

解決したコード

適当なクラス extends 共通クラス{
// 省略
    protected function getValidationClassName(): string
    {
        return TestClassName::class;
    }
// 省略
}
共通クラス extends 基底クラス{
    // 省略
    $validate_class_name = $this->getValidationClassName();
    $error_validate = $validate_class_name::validate($row_data);
    var_dump($error_validate);
// 実行結果////////////////
--> 正常に$error_validateが表示される
    // 省略
}

原因は、
return TestClassName::class;
の部分でした。

return 'TestClassName'がダメで、
return TestClassName::class;がうまくいく理由は、

名前空間が解決できていないこと が根本の原因でした。

公式に書いてありましたね...

PHP: クラスの基礎 - Manual

class キーワードでもクラス名の解決を行うことが出来ます。 クラスの名前が ClassName になっているクラスの完全修飾名を取得するには、 ClassName::class を使います。 これは、名前空間付きのクラスに使うと特に便利です。

同じような詰まり方する人少ないと思いますが、どなたか参考になれば幸いです。