답변:
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
있습니다.
내 구체적인 사례는 색상과 두 가지 멤버 메소드 lighten()
와 관련 darken()
이 있고 csscolor.php 클래스에서 누군가의 코드를 구현할 때 입니다. 어떤 이유로 든 나는 논리로 선택하지 않고 밝게 또는 어둡게 호출 할 수있는 동일한 코드를 원했습니다. 이것은 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);
위의 시도는 두 번째 인수 (퍼센트)를 예상하는 메소드에 대한 경고를 제공합니다.
몇 년 늦었지만 현재는 이것이 가장 좋은 방법입니다.
$x = (new ReflectionFunction("foo"))->getClosure();
$x();
완전성을 위해 eval ()을 사용할 수도 있습니다 .
$functionName = "foo()";
eval($functionName);
그러나 call_user_func()
올바른 방법입니다.
eval
이 질문에 대한 해결책이 아닙니다.
참고 : 요약 된 버전은 답변 끝 부분의 TL; DR을 참조하십시오.
업데이트 : 여기에 설명 된 이전 방법 중 하나가 제거되었습니다. 다른 방법에 대한 설명은 다른 답변을 참조하십시오. 여기에서는 다루지 않습니다. 그건 그렇고,이 답변이 도움이되지 않으면 물건 업그레이드를 반환해야합니다. PHP 5.6 지원은 2019 년 1 월에 종료되었습니다 (현재 PHP 7.0 및 7.1도 지원되지 않음). 자세한 내용은 지원되는 버전 을 참조하십시오.
다른 사람들이 언급했듯이 PHP5 (및 PHP7과 같은 최신 버전)에서는 변수를 함수 이름으로 사용 call_user_func()
하고call_user_func_array()
(개인적으로는 그 함수를 싫어합니다) 등을 사용할 수 있습니다.
PHP7부터는 다음과 같은 새로운 방법이 도입되었습니다.
참고 : 내부의 모든 것<something>
대괄호 안에있는 무언가를 형성하는 하나 이상의 표현을 의미합니다.<function_name>
의미합니다. 함수 이름을 형성하는 표현식을 의미합니다.
괄호 안에 하나 이상의 표현식을 함수 이름으로 한 번에 다음과 같은 형식으로 사용할 수 있습니다.
(<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)
(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);
친애하는 존, 안녕!
하나 이상의 인수로 함수를 호출하려면 함수 를
동적으로 호출하고 각 함수에 다른 개수의 인수가있는 경우 유용합니다. 이것은 내가 찾은 (그리고 해결 된) 나의 경우입니다. 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);
}
내 생각에 온 하나의 비 전통적인 접근 방식 은 스스로 작성하는 초 자율 AI를 통해 전체 코드를 생성하지 않는 한 "동적으로"호출하려는 함수가 이미 코드에 정의되어있을 가능성이 높다는 것입니다. 베이스. 문자열을 확인하고 악명 높은 행동을하는 이유는 무엇입니까?ifelse
춤을 추어 소환하여 ... 내 요점을 찾으십시오.
예.
if($functionName == 'foo'){
foo();
} else if($functionName == 'bar'){
bar();
}
사다리의 switch-case
맛이 좋지 않은 경우 에도 사용할 수 있습니다 ifelse
.
나는 " 동적으로 함수 호출 "이 절대적으로 필요한 경우가 있다는 것을 이해 합니다 (자체를 수정하는 재귀 논리처럼 ). 그러나 대부분의 일상적인 사소한 사용 사례는 피할 수 있습니다.
문자열이 사용 가능한 함수 정의와 일치하지 않으면 폴백 함수를 실행할 수있는 기회를 제공하면서 애플리케이션에서 많은 불확실성을 제거합니다. 이모.
if (method_exists($functionName)) $functionName(); else //exception or handle