Php узнать вызывающую функцию

php: определить, откуда была вызвана функция

Это определенно делает то, что вы хотите. Но будьте осторожны, debug_backtrace() — дорогой вызов. Не привыкать использовать его для определения цепочек вызовов. Если вы хотите «защитить» эти функции, проверьте ООП и защищенные методы.

Итак, если вы все еще ДЕЙСТВИТЕЛЬНО не знаете, как это сделать, то вот решение:

$backtrace = debug_backtrace(); echo 'Mu name is '.$backtrace[1]['function'].', and I have called him! Muahahah!'; 

Да, но не надо! Во всяком случае, не в постоянном коде приложения. Используйте параметры. debug_backtrace () выглядит как довольно тяжелая операция.

Самое быстрое и простое решение, которое я нашел

public function func() < //function whose call file you want to find $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1); >$trace: Array ( [0] => Array ( [file] => C:\wamp\www\index.php [line] => 56 [function] => func [class] => (func Class namespace) [type] => -> ) ) 

Я тестирую скорость на ноутбуке Lenovo: процессор Intel Pentiom N3530 2,16 ГГц, оперативная память 8 ГБ

global $times; $start = microtime(true); $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1); $times[] = microtime(true) - $start; 
count($times): 97 min: 2.6941299438477E-5 max: 10.68115234375E-5 avg: 3.3095939872191E-5 median: 3.0517578125E-5 sum: 321.03061676025E-5 the same results with notation without E-5 count($times): 97 min: 0.000026941299438477 max: 0.0001068115234375 avg: 0.000033095939872191 median: 0.000030517578125 sum: 0.0032103061676025 
foreach(debug_backtrace() as $t) < echo $t['file'] . ' line ' . $t['line'] . ' calls ' . $t['function'] . "()
"; >

Хорошее и прямое решение, чтобы получить обратную трассировку всех файлов, из которых вызывается определенная функция.

function findFunction($function, $inputDirectory="") < //version 0.1 $docRoot = getenv("DOCUMENT_ROOT"); $folderArray = null; $dirArray = null; // open directory $directory = opendir($docRoot.$inputDirectory); // get each entry while($entryName = readdir($directory)) < if(is_dir($entryName) && $entryName != "." && $entryName != "..")< $folderArray[] = str_replace($inputDirectory, "", $entryName); >$ext = explode(".", $entryName); if(!empty($ext[1])) < $dirArray[] = $docRoot.$inputDirectory."/".$entryName; >> // close directory closedir($directory); $found = false; if(is_array($dirArray))< foreach($dirArray as $current)< $myFile = file_get_contents($current); $myFile = str_replace("", "", $myFile); if(preg_match("/function ".$function."/", $myFile)) < $found = true; $foundLocation = $current; break; >> > if($found) < echo $foundLocation; exit; >else if(is_array($folderArray)) < foreach($folderArray as $folder)< if(!isset($return))< $return = findFunction($function, $inputDirectory."/".$folder); >else if($return == false) < $return = findFunction($function, $inputDirectory."/".$folder); >> > else < return false; >> findFunction("testFunction", "rootDirectory"); 

Надеюсь, это поможет кому-то. Если фактическая функция находится за пределами httpdocs, она не может быть найдена, потому что сервер будет настроен так, чтобы не разрешать ее. Тестировал только одну папку, но рекурсивная методология должна работать теоретически.

Это похоже на версию 0.1, но я не намерен продолжать его разработку, поэтому, если кто-то обновляет его, он может перепроверить его.

Слишком много работы: добавьте это в .bashrc function ff() < grep "function $1" $(find ./ -name "*.php") >затем вызовите ff fail или ff epic . см .: github.com/MaerF0x0/VimSetup/blob/master/bashrc#L122

Ещё вопросы

  • 0 запрос содержит MAX () и MIN () со своими собственными условиями
  • 0 SQLSTATE [HY000]: общая ошибка: 1364 Поле ‘name’ не имеет значения по умолчанию laravel 5.5
  • 1 конвертировать timedelta чч: мм в секунды
  • 1 [Vue warn]: свойство или метод «v» не определен в экземпляре, но на него ссылаются во время рендеринга
  • 0 Получить идентификатор объекта (этого) Jquery в js-файле?
  • 1 System.ArgumentException: недопустимые символы в пути
  • 0 jquery fadein () вызывается после завершения всех транзакций функции jquery?
  • 1 Преобразование даты и времени в формат отметки времени java «2019-02-21T14: 10: 18.161 + 0000»
  • 1 Eclipse PDE: имитирует IResourceChangeEvents для создания IJavaProject между PDE и рабочим пространством разработчика?
  • 1 C # при остановке цикла FOR он считает остальные числа как 0
  • 0 Получение электронной почты из Facebook GraphObject
  • 0 Как загрузить AJAX файл без ошибок?
  • 1 Node.js fs.writeFile: err возвращает ноль
  • 0 Javascript скрипты замедляются до нуля
  • 1 Как Entity framewrok определит первичный ключ в подходе базы данных первым
  • 1 Развертывание таблиц базы данных в порядке взаимосвязи с ограничениями
  • 1 Вызов Image.FromFile выдает исключение Out of memory
  • 1 Sympy — сравнение эквивалентных выражений со знаком равенства (=)
  • 0 Способы передачи информации из PHP в JQUERY?
  • 0 Интерфейс Laravel
  • 1 Ошибка: (29, 34) Несоответствие типов: предполагаемый тип — String? но редактируемый! ожидалось
  • 0 Как хранить несколько рабочих писем, личных и т. Д. Для одного контакта в MySQL
  • 0 Угловые диаграммы не могут заставить этикетки работать так, как мне нужно
  • 0 JQuery проблема с выпадающим меню
  • 0 JQuery получить индекс объекта, где поле равно значению
  • 0 Загружая контент в div с помощью jQuery.load (), как я могу заставить новые изображения исчезать при загрузке?
  • 0 MySQL разъем в Python не работает
  • 0 использование глобальной структуры против вызывающих методов (указатель на эту структуру)
  • 0 Нужен ли тип шифрования для подключения к внешней базе данных в Xamarin?
  • 0 GLSL — Пытаетесь добавить несколько источников света?
  • 0 От клиента было обнаружено потенциально опасное значение Request.Path (:)
  • 0 Javascript рекурсия не охватывает все элементы
  • 0 Ошибка при использовании активных записей для get_where и левого соединения
  • 0 Скрыть элемент при заполнении поля формы
  • 1 Если Элемент не существует
  • 1 RuntimeBeanNameReference против RuntimeBeanReference
  • 1 Почему текст Snackbar исчезает, если текст слишком длинный?
  • 0 Ошибка при использовании оператора модуля в qt на двойном
  • 0 как переписать URL в Yii?
  • 0 angular $ resource получает дополнительную информацию
  • 1 Высокая производительность в многозадачности внутри Tomcat
  • 1 Передать целое число в Arduino
  • 1 Monitor.Wait время ожидания никогда не истекает
  • 1 Реактивный экран-заставка и реагирующая навигация
  • 0 Ошибки с изменением размеров листа свойств
  • 0 JQuery — слияние / несколько $ (это) My в той же функции
  • 0 Angularjs: модель не доступна
  • 0 ng-repeat и пользовательская директива
  • 0 Изменение выбора не действует с помощью функции выхода мыши
  • 0 HTML-форма Codeigniter — нельзя нажимать на поля ввода
Читайте также:  Заголовок страницы

Источник

Как получить имя вызывающей функции / метода в 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 () из функции, вам не нужно указывать ее так:

Читайте также:  Работа через api python

Вот сценарий в полном объеме с причудливым тестовым примером:

 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).

Читайте также:  String problems in java

В то время как 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); 

Источник

Как узнать имя метода, который вызвал метод?

Из примера думаю суть ясна, как узнать имя класса нашел, мне бы теперь узнать имя дочернего метода который вызвал метод родителя, можно конечно это имя передать параметром, но так не интересно же.

Оценить 8 комментариев

qonand

И где здесь ООП? Класс от которого наследуются ничего не должен знать о классах которые его наследуют, это вообще не ООП подход

sanek_os9

Максим Федоров: он у меня умный потому знает кто дергает его методы, почему бы нет? Наверное я книжки плохо читал

Александр Шаповал: Такой подход — 99.99% знак говнокода. Или даже 100%. Не должны методы знать такую информацию. В нормальной архитектуре это ни к чему.

sanek_os9

Евгений: в своём случае, в методе display я подключаю файл шаблона, что бы в дочернем методе не передавать имя файла который нужно подключить я беру это имя из его названия и подключаю. В итоге получаю что какой метод вызывает display такой файл и подключаю, как по мне вполне юзабельно.

Александр Шаповал: Гораздо понятнее, проще, быстрее и красивее определить у класса атрибут типа template_name .

sanek_os9

Евгений: ну это тогда придется его определять у каждого метода (если в нем предусмотрен вывод), и хорошо когда этот атрибут соответствует имени метода, что бы когда смотришь шаблон было видно какой файл в каком классе используется, поэтому встает вопрос зачем указывать то, что заранее известно. Что касается понимания, тут все просто, достаточно один раз понять что файл шаблона подключается исходя из имени метода и класса.
Раньше я писал

class posts extends Controller < public function actionIndex() < $this->display('posts/index'); > >
class posts extends Controller < public function actionIndex() < $this->display(); > >

Один раз в методе display написал «не красиво» зато потом все красиво и структура файлов у шаблона тоже красива, потому что иначе он не будет работать.

Александр Шаповал: Поверьте моему опыту. Ради экономии 7-10 символов, вы усложнили код для понимания и изменения. И это потом выльется в часы отладки у вас или следующего разработчика.

sanek_os9

Евгений: спасибо за совет. Тут суть не только в сокращении кода а и содержании в порядке файлов шаблона, ведь легко можно там развести бардак. Пока оставлю как есть, а в дальнейшем если что, понесу всю ответственность:)

Источник

Оцените статью