回答:
is_callable
関数を使用する必要があります。変数に関数として呼び出すことができる何かが含まれているかどうかをチェックします(関数の名前、オブジェクトインスタンスと関数名を含む配列、または匿名の関数/クロージャー)
call_user_func(array('ClassName', 'method'), $args)
私のお気に入りのバージョンはインラインバージョンです。
${"variableName"} = 12;
$className->{"propertyName"};
$className->{"methodName"}();
StaticClass::${"propertyName"};
StaticClass::{"methodName"}();
大括弧の中に変数や式を置くこともできます!
{"functionName"}();
は正しくないため、構文エラーがスローされます。
はい、可能です:
function foo($msg) {
echo $msg."<br />";
}
$var1 = "foo";
$var1("testing 1,2,3");
出典:http : //www.onlamp.com/pub/a/php/2001/05/17/php_foundations.html?page=2
すでに述べたように、これを実現するにはいくつかの方法call_user_func()
があります$function_name()
。おそらく最も安全な方法であるか、必要であればのルートをたどることもできます。これらのメソッドの両方を使用して引数を渡すことが可能です
$function_name = 'foobar';
$function_name(arg1, arg2);
call_user_func_array($function_name, array(arg1, arg2));
呼び出す関数がオブジェクトに属している場合でも、これらのいずれかを使用できます
$object->$function_name(arg1, arg2);
call_user_func_array(array($object, $function_name), array(arg1, arg2));
ただし、$function_name()
メソッドを使用する場合は、名前が何らかの方法で動的である場合、関数の存在をテストすることをお勧めします
if(method_exists($object, $function_name))
{
$object->$function_name(arg1, arg2);
}
クラス内のメソッドに変数を使用しようとしたためにGoogleによって他の誰かがここに連れてきた場合、以下は実際に機能するコードサンプルです。上記のどれも私の状況ではうまくいきませんでした。主な違いは、&
の宣言$c = & new...
と&$c
渡されることcall_user_func
です。
私の特定のケースは、色と2つのメンバーメソッドlighten()
を使用darken()
して、csscolor.phpクラスからのコードを実装する場合です。なんらかの理由で、ロジックで選択するのではなく、同じコードでlightenまたはdarkenを呼び出せるようにしたかったのです。これは、if-elseだけを使用したり、このメソッドを呼び出すコードを変更したりしないという私の頑固さの結果かもしれません。
$lightdark="lighten"; // or optionally can be darken
$color="fcc"; // a hex color
$percent=0.15;
include_once("csscolor.php");
$c = & new CSS_Color($color);
$rtn=call_user_func( array(&$c,$lightdark),$color,$percent);
で何かを試しても$c->{...}
うまくいかなかったことに注意してください。上のphp.netのページの下部にある読者提供のコンテンツを閲覧したところcall_user_func
、上記をまとめることができました。また、$params
配列が機能しなかったので注意してください:
// This doesn't work:
$params=Array($color,$percent);
$rtn=call_user_func( array(&$c,$lightdark),$params);
この上記の試みは、2番目の引数(パーセント)を期待するメソッドに関する警告を与えます。
数年遅れますが、これが今の私にとって最良の方法です。
$x = (new ReflectionFunction("foo"))->getClosure();
$x();
完全を期すために、eval()を使用することもできます。
$functionName = "foo()";
eval($functionName);
しかし、それcall_user_func()
は適切な方法です。
eval
この質問に対する解決策ではありません。
注:要約バージョンについては、回答の最後にあるTL; DRを参照してください。
更新:ここで説明した古いメソッドの1つが削除されました。他の方法の説明については、他の回答を参照してください。ここでは説明しません。ちなみに、この回答が役に立たない場合は、アップグレードを元に戻す必要があります。PHP 5.6のサポートは2019年1月に終了しました(現在、PHP 7.0および7.1もサポートされていません)。詳細については、サポートされているバージョンを参照してください。
他の人が述べたように、PHP5(およびPHP7のような新しいバージョン)では、変数を関数名として使用しcall_user_func()
たり、call_user_func_array()
(そして、個人的にはこれらの関数が嫌いです)などを使用したりできます。
PHP7以降、新しい方法が導入されています。
注:<something>
括弧内のすべては、何かを形成する1つ以上の式を<function_name>
意味します。例えば、関数名を形成する式を意味します。
かっこ内の1つ以上の式を関数名として一度に使用できます。形式は次のとおりです。
(<function_name>)(arguments);
例えば:
function something(): string
{
return "something";
}
$bar = "some_thing";
(str_replace("_", "", $bar))(); // something
// Possible, too; but generally, not recommended, because makes your code more complicated
(str_replace("_", "", $bar))()();
注:括弧を削除してstr_replace()
もエラーにはなりませんが、括弧を使用するとコードが読みやすくなります。ただし、.
演算子を使用しているときなど、これを実行できない場合があります。一貫性を保つために、常に括弧を付けることをお勧めします。
動的関数呼び出しと同様に、かっこではなく中かっこで囲まれたメソッド呼び出しでも同じように実行できます(追加のフォームの場合は、TL; DRセクションに移動します)。
$object->{<method_name>}(arguments);
$object::{<method_name>}(arguments);
例でそれを見てください:
class Foo
{
public function another(): string
{
return "something";
}
}
$bar = "another thing";
(new Something())->{explode(" ", $bar)[0]}(); // something
PHP7で追加されたよりエレガントな方法は次のとおりです。
[<object>, <method_name>](arguments);
[<class_name>, <method_name>](arguments); // Static calls only
例として:
class Foo
{
public function nonStaticCall()
{
echo "Non-static call";
}
public static function staticCall()
{
echo "Static call";
}
}
$x = new X();
[$x, "non" . "StaticCall"](); // Non-static call
[$x, "static" . "Call"](); // Static call
注:前の方法よりもこのメソッドを使用する利点は、呼び出しの種類(つまり、静的かどうか)を気にしないことです。
少し複雑にすると、匿名クラスと上記の機能の組み合わせを使用できます。
$bar = "SomeThing";
echo (new class {
public function something()
{
return 512;
}
})->{strtolower($bar)}(); // 512
一般に、PHP7では、次の形式を使用することがすべて可能です。
// Everything inside `<something>` brackets means one or more expressions
// to form something
// Dynamic function call
(<function_name>)(arguments)
// Dynamic method call on an object
$object->{<method_name>}(arguments)
$object::{<method_name>}(arguments)
// Dynamic method call on a dynamically-generated object
(<object>)->{<method_name>}(arguments)
(<object>)::{<method_name>}(arguments)
// Dynamic method call, statically
ClassName::{<method_name>}(arguments)
(<class_name>)::{<method_name>}(arguments)
// Dynamic method call, array-like (no different between static and non-static calls
[<object>, <method_name>](arguments)
// Dynamic method call, array-like, statically
[<class_name>, <method_name>](arguments)
主にこのPHPトークに基づいています。
(expressions)->$bar()
名前空間を使用するときに動的関数名に関するポイントを追加するだけです。
名前空間を使用している場合、関数がグローバル名前空間にある場合を除いて、以下は機能しません。
namespace greetings;
function hello()
{
// do something
}
$myvar = "hello";
$myvar(); // interpreted as "\hello();"
call_user_func()
代わりに使用する必要があります:
// if hello() is in the current namespace
call_user_func(__NAMESPACE__.'\\'.$myvar);
// if hello() is in another namespace
call_user_func('mynamespace\\'.$myvar);
オブジェクトのメソッドを呼び出す場合は、@ Chris Kの答えを補完するために、クロージャーを使用して単一の変数を使用して呼び出すことができます。
function get_method($object, $method){
return function() use($object, $method){
$args = func_get_args();
return call_user_func_array(array($object, $method), $args);
};
}
class test{
function echo_this($text){
echo $text;
}
}
$test = new test();
$echo = get_method($test, 'echo_this');
$echo('Hello'); //Output is "Hello"
これらの変数と関数があるとしましょう:
$functionName1 = "sayHello";
$functionName2 = "sayHelloTo";
$functionName3 = "saySomethingTo";
$friend = "John";
$datas = array(
"something"=>"how are you?",
"to"=>"Sarah"
);
function sayHello()
{
echo "Hello!";
}
function sayHelloTo($to)
{
echo "Dear $to, hello!";
}
function saySomethingTo($something, $to)
{
echo "Dear $to, $something";
}
引数なしで関数を呼び出すには
// Calling sayHello()
call_user_func($functionName1);
こんにちは!
1つの引数で関数を呼び出すには
// Calling sayHelloTo("John")
call_user_func($functionName2, $friend);
親愛なるジョン、こんにちは!
1つ以上の引数を使用して関数を呼び出すには
これは、関数を動的に呼び出しており、各関数の引数の数が異なる場合に役立ちます。これは私が探していた(そして解決した)私のケースです。call_user_func_array
鍵です
// You can add your arguments
// 1. statically by hard-code,
$arguments[0] = "how are you?"; // my $something
$arguments[1] = "Sarah"; // my $to
// 2. OR dynamically using foreach
$arguments = NULL;
foreach($datas as $data)
{
$arguments[] = $data;
}
// Calling saySomethingTo("how are you?", "Sarah")
call_user_func_array($functionName3, $arguments);
親愛なるサラ、元気?
イェイバイ!
call_user_func関数を使用します。
次のコードは、PHPで動的関数を作成するのに役立ちます。現在、関数名は変数「$ current_page」によって動的に変更できます。
$current_page = 'home_page';
$function = @${$current_page . '_page_versions'};
$function = function() {
echo 'current page';
};
$function();
変数に格納された名前を使用して関数を安全に呼び出す最も簡単な方法は、
//I want to call method deploy that is stored in functionname
$functionname = 'deploy';
$retVal = {$functionname}('parameters');
以下のように動的にLaravelに移行テーブルを作成しました、
foreach(App\Test::$columns as $name => $column){
$table->{$column[0]}($name);
}
私が思いついた1つの型破りなアプローチは、それ自体を書き込む超超自律型AIを介してコード全体を生成しない限り、「動的に」呼び出したい関数がすでにコードで定義されている可能性が高いということです。ベース。だから、弦をチェックして悪名高いifelse
ダンスをして召喚するだけではどうでしょう...
例えば。
if($functionName == 'foo'){
foo();
} else if($functionName == 'bar'){
bar();
}
はしごのswitch-case
淡白な味が気に入らなくても使えますifelse
。
「関数を動的に呼び出す」ことが絶対に必要になる場合があることを理解しています(それ自体を変更する再帰ロジックのように)。しかし、日常のささいなユースケースのほとんどは、回避できます。
文字列が使用可能な関数の定義のいずれにも一致しない場合、フォールバック関数を実行する機会を与えながら、アプリケーションから多くの不確実性を取り除きます。私見では。
if (method_exists($functionName)) $functionName(); else //exception or handle