PHPの変数からクラスをインスタンス化しますか?


146

私はこの質問が曖昧に聞こえるのを知っているので、例を使ってより明確にします:

$var = 'bar';
$bar = new {$var}Class('var for __construct()'); //$bar = new barClass('var for __construct()');

これが私がやりたいことです。どうしますか もちろん、次のようにeval()を使用することもできます。

$var = 'bar';
eval('$bar = new '.$var.'Class(\'var for __construct()\');');

しかし、私はむしろeval()から離れたいと思います。eval()なしでこれを行う方法はありますか?

回答:


213

最初にクラス名を変数に入れます:

$classname=$var.'Class';

$bar=new $classname("xyz");

多くの場合、これはファクトリーパターンに包まれたようなものです。

詳細については、名前空間と動的言語機能を参照してください。


2
これが私のやり方です。クラス内から、親と自己を使用できることに注意してください。
ロス

1
同様に、$ var = 'Name';を実行することもできます。$ obj-> {'get'。$ var}();
マリオ

1
良い点ですが、これはコンストラクターではなくメソッド呼び出しでのみ機能します
Paul Dixon

12
あなたは、名前空間で作業する場合、文字列に現在のネームスペースを入れて:$var = __NAMESPACE__ . '\\' . $var . 'Class';
bastey

@bastey-しかし、なぜですか?クラス名の前に名前空間がないとこれが機能しない理由を理解するのにあまりにも多くの時間を費やしました...
jkulak

72

名前空間を使用する場合

私自身の調査結果では、あなたが(私が知る限り)クラスの完全な名前空間パスを宣言する必要があることを言及するのは良いことだと思います。

MyClass.php

namespace com\company\lib;
class MyClass {
}

index.php

namespace com\company\lib;

//Works fine
$i = new MyClass();

$cname = 'MyClass';

//Errors
//$i = new $cname;

//Works fine
$cname = "com\\company\\lib\\".$cname;
$i = new $cname;

6
名前空間で作成する必要がある場合の唯一の有効なソリューションは、あなたのものです。共有してくれてありがとう!
TiagoGouvêa15年

しかし、これは奇妙です、なぜ宣言された名前空間を使用しないのですか?
Yisrael Dov

@YisraelDovはい、それは間違いなく反直感的です。しかし、何らかの理由で、このコンテキストでは奇妙な動作をします。ありがとうphp
csga5000

@YisraelDovその場合、別の名前空間からクラスをインスタンス化することは大きな頭痛の種になるためだと思います。また、変数を渡すことができることも考慮してください。クラス名がテキストとしてphpファイルに書き込まれる場合、それを書き込む人は誰でも、それがどの名前空間に書き込まれるかを正確に把握しています。しかし、変数が関数間で渡される場合、フォローアップするのは悪夢になります。また、get_class()を使用すると、FQクラス名が返されるため、変数にすぐに格納してどこでも使用できます。それがファイルの名前空間に依存している場合、それはあまりうまく機能しません。
sbnc.eu

61

動的コンストラクターパラメーターも渡す方法

動的コンストラクターパラメーターをクラスに渡す場合は、次のコードを使用できます。

$reflectionClass = new ReflectionClass($className);

$module = $reflectionClass->newInstanceArgs($arrayOfConstructorParameters);

動的クラスとパラメーターの詳細情報

PHP> = 5.6

PHP 5.6以降では、引数のアンパッキングを使用してこれをさらに簡略化できます。

// The "..." is part of the language and indicates an argument array to unpack.
$module = new $className(...$arrayOfConstructorParameters);

それを指摘してくれたDisgruntledGoatに感謝します。


7
PHP 5.6から、あなたは開梱引数を使用することができるはずです:new $className(...$params)
DisgruntledGoat

29
class Test {
    public function yo() {
        return 'yoes';
    }
}

$var = 'Test';

$obj = new $var();
echo $obj->yo(); //yoes

いいえ、良い例ではありません。すべてが同じphpファイルにある場合にのみ機能します。
fralbo 2017年

2
2ndGABはこのコメントを削除する必要があります。自動読み込みはこの質問とは関係ありません。
ジムマグワイア2017

-1

call_user_func()またはcall_user_func_arrayphpメソッドをお勧めします。こちらで確認できます(call_user_func_arraycall_user_func)。

class Foo {
static public function test() {
    print "Hello world!\n";
}
}

 call_user_func('Foo::test');//FOO is the class, test is the method both separated by ::
 //or
 call_user_func(array('Foo', 'test'));//alternatively you can pass the class and method as an array

メソッドに渡す引数がある場合は、call_user_func_array()関数を使用します。

例。

class foo {
function bar($arg, $arg2) {
    echo __METHOD__, " got $arg and $arg2\n";
}
}

// Call the $foo->bar() method with 2 arguments
call_user_func_array(array("foo", "bar"), array("three", "four"));
//or
//FOO is the class, bar is the method both separated by ::
call_user_func_array("foo::bar"), array("three", "four"));

3
この回答は質問には適用されません。OPは、変数文字列からクラスをインスタンス化する方法(クラス__constructメソッドを動的にトリガーする)を尋ね、CLASS OBJECTを新しい変数に戻す-あなたのアドバイスは、class-> method([])のVALUEを返します。クラスオブジェクトではなく、再呼び出しのため、この場合は適用されません。戻り値php.net/manual/en/function.call-user-func-array.phpを
ChrisN
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.