Как получить имя вызывающей функции / метода в PHP?
Мне известно о функции debug_backtrace , но я ищу некоторые готовые к использованию функции, такие как GetCallingMethodName() ? Было бы прекрасно, если бы он дал класс метода (если это действительно метод).
Функция debug_backtrace() – это единственный способ узнать это, если вы ленивы, это еще одна причина, по которой вы должны закодировать GetCallingMethodName() . Борьба с лени! : D
echo debug_backtrace()[1]['function'];
Вы также можете использовать информацию, предоставленную с помощью исключения php, это элегантное решение:
function GetCallingMethodName () < $ e = новое исключение (); $ trace = $ e->getTrace (); // position 0 будет линией, вызывающей эту функцию, поэтому мы ее игнорируем $ last_call = $ trace [1]; print_r ($ last_call); > функция firstCall ($ a, $ b) < theCall ($ a, $ b); >функция theCall ($ a, $ b) < GetCallingMethodName (); >firstCall ('lucia', 'php');
массив ( [файл] => /home/lufigueroa/Desktop/test.php [line] => 12 [function] => theCall [args] => Массив ( [0] => lucia [1] => php ) )
Начиная с php 5.4 вы можете использовать
$dbt=debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,2); $caller = isset($dbt[1]['function']) ? $dbt[1]['function'] : null;
Это не испортит память, поскольку игнорирует аргументы и возвращает только последние 2 записи стека backtrace и не будет генерировать уведомления в качестве других ответов здесь.
Мой любимый способ, в одной строке!
Вы можете использовать его следующим образом:
echo 'The calling function: ' . debug_backtrace()[1]['function'];
Обратите внимание, что это только совместимо с версиями PHP, выпущенными в течение прошлого года. Но это хорошая идея, чтобы поддерживать PHP в любом случае по соображениям безопасности.
Для меня debug_backtrace ударил мой лимит памяти, и я хотел использовать это в производстве для регистрации и отправки сообщений по электронной почте, поскольку они происходят.
Вместо этого я нашел это решение, которое работает блестяще!
// Make a new exception at the point you want to trace, and trace it! $e = new Exception; var_dump($e->getTraceAsString()); // Outputs the following #2 /usr/share/php/PHPUnit/Framework/TestCase.php(626): SeriesHelperTest->setUp() #3 /usr/share/php/PHPUnit/Framework/TestResult.php(666): PHPUnit_Framework_TestCase->runBare() #4 /usr/share/php/PHPUnit/Framework/TestCase.php(576): PHPUnit_Framework_TestResult->run(Object(SeriesHelperTest)) #5 /usr/share/php/PHPUnit/Framework/TestSuite.php(757): PHPUnit_Framework_TestCase->run(Object(PHPUnit_Framework_TestResult)) #6 /usr/share/php/PHPUnit/Framework/TestSuite.php(733): PHPUnit_Framework_TestSuite->runTest(Object(SeriesHelperTest), Object(PHPUnit_Framework_TestResult)) #7 /usr/share/php/PHPUnit/TextUI/TestRunner.php(305): PHPUnit_Framework_TestSuite->run(Object(PHPUnit_Framework_TestResult), false, Array, Array, false) #8 /usr/share/php/PHPUnit/TextUI/Command.php(188): PHPUnit_TextUI_TestRunner->doRun(Object(PHPUnit_Framework_TestSuite), Array) #9 /usr/share/php/PHPUnit/TextUI/Command.php(129): PHPUnit_TextUI_Command->run(Array, true) #10 /usr/bin/phpunit(53): PHPUnit_TextUI_Command::main() #11 "
Я просто написал версию этого «get_caller», надеюсь, это поможет. Моя очень ленивая. Вы можете просто запустить get_caller () из функции, вам не нужно указывать ее так:
Вот сценарий в полном объеме с причудливым тестовым примером:
else < // Otherwise create a fresh one. $stack = debug_backtrace(); echo "\nPrintout of Function Stack: \n\n"; print_r($stack); echo "\n"; >if ($function == NULL) < // We need $function to be a function name to retrieve its caller. If it is omitted, then // we need to first find what function called get_caller(), and substitute that as the // default $function. Remember that invoking get_caller() recursively will add another // instance of it to the function stack, so tell get_caller() to use the current stack. $function = get_caller(__FUNCTION__, $stack); >if ( is_string($function) && $function != "" ) < // If we are given a function name as a string, go through the function stack and find // it's caller. for ($i = 0; $i < count($stack); $i++) < $curr_function = $stack[$i]; // Make sure that a caller exists, a function being called within the main script // won't have a caller. if ( $curr_function["function"] == $function && ($i + 1) < count($stack) ) < return $stack[$i + 1]["function"]; >> > // At this stage, no caller has been found, bummer. return ""; > // TEST CASE function woman() < $caller = get_caller(); // No need for get_caller(__FUNCTION__) here if ($caller != "") < echo $caller , "() called " , __FUNCTION__ , "(). No surprises there.\n"; >else < echo "no-one called ", __FUNCTION__, "()\n"; >> function man() < // Call the woman. woman(); >// Don't keep him waiting man(); // Try this to see what happens when there is no caller (function called from main script) //woman(); ?>
man () вызывает женщину (), которая вызывает get_caller (). get_caller () не знает, кто его назвал, потому что женщина () была осторожна и не рассказывала об этом, поэтому она рекурсивно выясняет. Затем возвращается тот, кто вызвал женщину (). И распечатка в режиме исходного кода в браузере показывает стек функций:
Printout of Function Stack: Array ( [0] => Array ( [file] => /Users/Aram/Development/Web/php/examples/get_caller.php [line] => 46 [function] => get_caller [args] => Array ( ) ) [1] => Array ( [file] => /Users/Aram/Development/Web/php/examples/get_caller.php [line] => 56 [function] => woman [args] => Array ( ) ) [2] => Array ( [file] => /Users/Aram/Development/Web/php/examples/get_caller.php [line] => 60 [function] => man [args] => Array ( ) ) ) man() called woman(). No surprises there.
Мне нужно было что-то, чтобы просто перечислить вызывающие классы / методы (работая над проектом Magento).
В то время как debug_backtrace предоставляет debug_backtrace полезной информации, объем информации, которую он искал для установки Magento, был подавляющим (более 82 000 строк!) Поскольку меня беспокоила только вызывающая функция и класс, я работал над этим небольшим решением:
$callers=debug_backtrace(); foreach($callers as $call) < echo "
" . $call['class'] . '->' . $call['function']; >
Самый простой способ получить имя родительской функции:
$caller = next(debug_backtrace())['function'];
Лучший ответ на этот вопрос, который я видел, – это:
list(, $caller) = debug_backtrace(false);
Как вызвать функцию PHP из строки, хранящейся в переменной
Мне нужно иметь возможность вызывать функцию, но имя функции хранится в переменной, возможно ли это? например:
function foo () < //code here >function bar () < //code here >$functionName = "foo"; // i need to call the function based on what is $functionName
14 ответов
Если вам нужно вызвать функцию объекта, имя которого находится в переменной, сделайте это: call_user_func (array ($ obj, $ func), $ params)
Как я могу аннулировать ошибку определения функции, если функция не была определена? Достаточно ли ($ functionName)?
@ sємsєм: Вы должны использовать функцию is_callable . Он проверит, содержит ли переменная что-то, что может быть вызвано как функция (будь то имя функции, массив, содержащий экземпляр объекта и имя функции, или анонимная функция / замыкание)
@Pacerier: укажите имя класса в качестве первого элемента массива: call_user_func(array(‘ClassName’, ‘method’), $args)
Моя любимая версия — встроенная версия:
$ = 12; $className->; $className->(); StaticClass::$; StaticClass::();
Вы можете поместить переменные или выражения в скобки тоже!
@marcioAlmada: публиковать комментарии, а не редактировать ответы других таким образом; это добавляет путаницу — не ясно, кто что сказал [для любопытных: см. ревизии для объяснений]
Спасибо, ребята, за ответы, это действительно выдает ошибку, даже в php 5.4, так что синтаксис работает только с объектными методами. Отредактировал пост.
function foo($msg) < echo $msg."
"; > $var1 = "foo"; $var1("testing 1,2,3");
Как уже упоминалось, есть несколько способов достичь этого, возможно, самым безопасным способом является 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. По какой-то причине я хотел, чтобы один и тот же код мог вызвать 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);
Эта вышеприведенная попытка даст предупреждение о методе, ожидающем второй аргумент (в процентах).
Обращение к функциям через переменные
PHP поддерживает концепцию переменных функций. Это означает, что если к имени переменной присоединены круглые скобки, PHP ищет функцию с тем же именем, что и результат вычисления переменной, и пытается ее выполнить. Эту возможность можно использовать для реализации обратных вызовов, таблиц функций и множества других вещей.
Переменные функции не будут работать с такими языковыми конструкциями как echo , print , unset() , isset() , empty() , include , require и другими подобными им операторами. Вам необходимо реализовывать свою функцию-обертку (wrapper) для того, чтобы приведенные выше конструкции могли работать с переменными функциями.
Пример #1 Работа с функциями посредством переменных
function bar ( $arg = » )
echo «In bar(); argument was ‘ $arg ‘.
\n» ;
>
// Функция-обертка для echo
function echoit ( $string )
echo $string ;
>
$func = ‘foo’ ;
$func (); // Вызывает функцию foo()
$func = ‘bar’ ;
$func ( ‘test’ ); // Вызывает функцию bar()
$func = ‘echoit’ ;
$func ( ‘test’ ); // Вызывает функцию echoit()
?>
Вы также можете вызвать методы объекта, используя возможности PHP для работы с переменными функциями.
Пример #2 Обращение к методам класса посредством переменных
class Foo
function Variable ()
$name = ‘Bar’ ;
$this -> $name (); // Вызываем метод Bar()
>
?php
function Bar ()
echo «This is Bar» ;
>
>
$foo = new Foo ();
$funcname = «Variable» ;
$foo -> $funcname (); // Обращаемся к $foo->Variable()
При вызове статических методов, вызов функции «сильнее» чем оператор доступа к статическому свойству:
Пример #3 Пример вызова переменного метода со статическим свойством
class Foo
static $variable = ‘static property’ ;
static function Variable ()
echo ‘Method Variable called’ ;
>
>
?php
echo Foo :: $variable ; // Это выведет ‘static property’. Переменная $variable будет разрешена в нужной области видимости.
$variable = «Variable» ;
Foo :: $variable (); // Это вызовет $foo->Variable(), прочитав $variable из этой области видимости.
С версии PHP 5.4.0, можно вызывать callable функцию помещенную в переменную.
Пример #4 Сallable-фукнции
class Foo
static function bar()
echo «bar\n»;
>
function baz()
echo «baz\n»;
>
>
$func = array(«Foo», «bar»);
$func(); // prints «bar»
$f = array(new Foo, «baz»);
$func(); // prints «baz»
$f = «Foo::bar»;
$func(); // выведет «bar» в PHP 7.0.0 и выше; в предыдущих версиях это приведет к фатальной ошибке
Список изменений
Версия | Описание |
---|---|
7.0.0 | ‘ClassName::methodName’ доступна как функция-переменная. |
5.4.0 | Массивы, являющиеся корректными callable-методами, доступны как функции-переменные. |
Ошибка PHP: имя функции должно быть строкой
Я попытался: $_COOKIE(«CaptchaResponseValue») . Файл cookie успешно установлен и доступен. Почему при использовании $_COOKIE ?
8 ответов
Использование скобок на языке программирования или языке сценариев обычно означает, что это функция. Однако $_COOKIE в php не является функцией, это Array. Чтобы получить доступ к данным в массивах, вы используете квадратные скобки (‘[‘ и ‘]’), которые символизируют индекс для получения данных. Поэтому, делая $_COOKIE[‘test’] , вы в основном говорите: «Дайте мне данные из теста» index «. Теперь, в вашем случае, у вас есть две возможности: (1) либо вы хотите увидеть, является ли это ложью — просмотрев куки файл, либо (2) посмотреть, нет ли там даже. Для этого вы используете функцию isset, которая в основном проверяет, установлена ли переменная или нет. Пример
И если вы хотите проверить, является ли значение ложным, и оно установлено, вы можете сделать следующее:
if ( isset($_COOKIE['test']) && $_COOKIE['test'] == "false" )
Одна вещь, которую вы можете иметь в виду, состоит в том, что если первый тест завершится неудачно, он даже не будет проверять следующий оператор, если он И ( && ). И чтобы объяснить, почему вы действительно получаете ошибку «Функция должна быть строкой», посмотрите эту страницу. Что касается базового создания функций в PHP, то вы должны помнить, что функция в PHP может содержать только определенные типы символов, где $ не является одним из них. Поскольку в PHP $ представлена переменная. Функция может выглядеть так: _myFunction _myFunction123 myFunction и во многих других шаблонах, но смешение с такими символами, как $и%, не будет работать.