Php как найти функцию

How can I find out in which file and line a given function was defined?

NikiC's user avatar

NikiC

100k36 gold badges190 silver badges225 bronze badges

asked Feb 8, 2010 at 14:21

foreline's user avatar

You could also do this in PHP itself:

$reflFunc = new ReflectionFunction('function_name');
print $reflFunc->getFileName() . ':' . $reflFunc->getStartLine();

answered Feb 8, 2010 at 14:58

Tom Haigh's user avatar

Tom HaighTom Haigh

57.1k21 gold badges114 silver badges142 bronze badges

7

Either use a IDE that allows doing so (I would recomend Eclipse PDT), or you can allways grep it if on Linux, or using wingrep. In Linux it would be something like:

grep -R "function funName" *

from within the root folder of the project.

answered Feb 8, 2010 at 14:25

Johnco's user avatar

JohncoJohnco

3,9774 gold badges31 silver badges43 bronze badges

1

I like Tom’s solution, so I thought I could share a bit more tricks with ReflectionFunction (it should work on every PHP 5):

  • one-liner to print the filename:

    print (new ReflectionFunction("foo"))->getFileName();
    

Please note that it won’t show you the location for internal functions (such as _), but it still can print the API for it as below.

  • to print the definition and parameters of the function:

    print new ReflectionFunction("foo");
    

    Example:

    $ php -r 'print new ReflectionFunction("_");'
    Function [ <internal:gettext> function _ ] {
      - Parameters [1] {
        Parameter #0 [ <required> $msgid ]
      }
    }
    

answered Nov 4, 2014 at 16:36

kenorb's user avatar

kenorbkenorb

153k85 gold badges674 silver badges738 bronze badges

If you use an IDE like Netbeans, you can CTRL+Click the function use and it will take you to where it is defined, assuming the file is within the project folder you defined.

There’s no code or function to do this though.

answered Feb 8, 2010 at 14:24

Stephen Melrose's user avatar

Stephen MelroseStephen Melrose

4,7625 gold badges29 silver badges41 bronze badges

2

Heres a basic function that will scan your entire project files for a specific string and tell you which file it is in and which char position it starts at using only basic php.
Hope this helps someone…

<?php 
$find="somefunction()";

echo findString('./ProjectFolderOrPath/',$find);

function findString($path,$find){
    $return='';
    ob_start();
    if ($handle = opendir($path)) {
        while (false !== ($file = readdir($handle))) {
            if ($file != "." && $file != "..") {
                if(is_dir($path.'/'.$file)){
                    $sub=findString($path.'/'.$file,$find);
                    if(isset($sub)){
                        echo $sub.PHP_EOL;
                    }
                }else{
                    $ext=substr(strtolower($file),-3);
                    if($ext=='php'){
                        $filesource=file_get_contents($path.'/'.$file);
                        $pos = strpos($filesource, $find);
                        if ($pos === false) {
                            continue;
                        } else {
                            echo "The string '$find' was found in the file '$path/$file and exists at position $pos<br />";
                        }
                    }else{
                        continue;
                    }
                }
            }
        }
        closedir($handle);
    }
    $return = ob_get_contents();
    ob_end_clean();
    return $return;
}
?>

answered Apr 2, 2012 at 16:02

Lawrence Cherone's user avatar

Lawrence CheroneLawrence Cherone

45.9k7 gold badges61 silver badges104 bronze badges

0

I assume that by “described” you mean “defined”. For this, you ideally need a decent IDE that can do it.

answered Feb 8, 2010 at 14:22

Anton Gogolev's user avatar

Anton GogolevAnton Gogolev

113k38 gold badges197 silver badges286 bronze badges

1

another way to check where does the function defined, try to redefine the function, PHP error system will simply returns an error told you where the function previously defined

answered Mar 30, 2015 at 10:43

Yohanip's user avatar

You’ll need an IDE that supports “Open Function Declaration” functionality. A good for for php is Eclipse PDT.

To look for the function definition, highlight the function name, hold CTRL + Click on the name.

answered Feb 8, 2010 at 14:26

Yada's user avatar

YadaYada

30.1k24 gold badges103 silver badges144 bronze badges

(PHP 4, PHP 5, PHP 7, PHP 8)

function_existsReturn true if the given function has been defined

Description

function_exists(string $function): bool

Parameters

function

The function name, as a string.

Return Values

Returns true if function exists and is a
function, false otherwise.

Note:

This function will return false for constructs, such as
include_once and echo.

Examples

Example #1 function_exists() example


<?php
if (function_exists('imap_open')) {
echo
"IMAP functions are available.<br />n";
} else {
echo
"IMAP functions are not available.<br />n";
}
?>

Notes

Note:

A function name may exist even if the function itself is unusable due to
configuration or compiling options (with the image functions being an example).

See Also

  • method_exists() – Checks if the class method exists
  • is_callable() – Verify that a value can be called as a function from the current scope.
  • get_defined_functions() – Returns an array of all defined functions
  • class_exists() – Checks if the class has been defined
  • extension_loaded() – Find out whether an extension is loaded

kitchin

10 years ago


You can use this function to conditionally define functions, see: http://php.net/manual/en/functions.user-defined.php

For instance WordPress uses it to make functions "pluggable." If a plugin has already defined a pluggable function, then the WP code knows not to try to redefine it.

But function_exists() will always return true unless you wrap any later function definition in a conditional clause, like if(){...}. This is a subtle matter in PHP parsing. Some examples:

<?php

if (function_exists('foo')) {

  print
"foo defined\n";

} else {

  print
"foo not defined\n";

}

function
foo() {}

if (

function_exists('bar')) {

  print
"bar defined\n";

} else {

  print
"defining bar\n";

  function
bar() {}

}

print
"calling bar\n";

bar(); // ok to call function conditionally defined earlier
print "calling baz\n";

baz(); // ok to call function unconditionally defined later

function baz() {}
qux(); // NOT ok to call function conditionally defined later

if (!function_exists('qux')) {

  function
qux() {}

}

?>

Prints:

  foo defined

  defining bar

  calling bar

  calling baz

  PHP Fatal error: Call to undefined function qux()

Any oddities are probably due to the order in which you include/require files.


michael at squiloople dot com

7 years ago


It should be noted that the function_exists check is not relative to the root namespace. This means that the namespace should be appended to the check:

<?phpnamespace test;

  if (!

function_exists(__NAMESPACE__ . 'example'))
  {

    function

example()
    {

    }

  }

?>


chris at candm dot org dot uk

1 year ago


The confusion expressed in some of the submissions here arise because functions declared outside conditional blocks are defined as the code is loaded and are thus callable and exist wherever in the code they are declared, whereas those declared inside a condition block are not defined until that block is executed. Thus:

    echo foo();
    function foo() { return "I am foo"; }

yields : "I am foo"

however because those inside a conditional are defined as they are encountered during code execution

    echo foo();
    if(true) {
        function foo() { return "I am foo"; }
    }

yields: Fatal error: Uncaught Error: Call to undefined function foo()


ayyappan dot ashok at gmail dot com

7 years ago


PHP supports nested function based on certain criteria.

Please look over the code.

function Media(){ }

function Audio()
{
    echo "Plugged Audo 5.1:<br/>";
    function Volume()
    {
    echo "Volume controls:<br/>";
    function Equalizer()
    {
        echo "Equalize Bands:<br/>";
    }
   }
}
//Call to nested functions
Audio();
Volume();
Equalizer();

if(function_exists('Volume')):
echo "TRUE";
else:
echo "FALSE";
endif;

Case 1:  //Result :Works Well
--------
Audio();
Volume();
Equalizer();

Case 2:  //Results Notice Error. Root function Audio must be called first.
--------
Volume();

Case 3:  //Results Error. Root function Volume must be called.
--------
Audio();
Equalizer();

Note :
The nested function should be called based on their order used.
In our example when Audio is not called and instantly when we try to call Volume puts under error.

Even though there is an possibility to use nested functions in PHP. It looks overhead to do so. Better to avoid in logical ground of script.

Tested on PHP 5.5.32


andi at splitbrain dot org

16 years ago


function_exists will return false for functions disabled with the disable_functions ini directive. However those functions are still declared so trying to define them yourself will fail.

<?php

if(!function_exists('readfile')){

  function
readfile($file){

   
$handle=@fopen($cache,"r");

    echo @
fread($handle,filesize($file));

    @
fclose($handle);

  }

}

?>



The above will issue a "Cannot redeclare readfile()" fatal error if readfile was disabled with disable_functions.


fili at fili dot nl

17 years ago


To prevent direct calls to included files i use the following technique.

In the main file create an empty function with a random name. Like so:

<?php
function hjudejdjiwe() { return true; }
?>

Then check for the existence of this function within your include:

<?php
if (!function_exists('hjudejdjiwe')) { die('!'); }
?>

Simple but effective.


BruceB

7 years ago


This is not going to go down as you might expect it should (even if you play smart and require/include_once):

<?php
if(function_exists('my_function'))
{
   throw new
Exception("'my_function' is already defined!");
}

function

my_function()
{
  
// Do the work here
}
?>

This, however does work:

<?php
if( ! function_exists('my_function'))
{
   function
my_function()
   {
     
// Do the work here
  
}
}
else
{
   throw new
Exception("'my_function' is already defined!");
}
?>

Does it have anything to do with PHP parse/execute phases or global/local scope or those curly brackets or something else, I have no idea, but the latter ugly son works, while the former bombs out claiming that 'my_function' is already defined.

Thought this might save someone a few minutes of debugging time...


webmaster at mamo-net dot de

15 years ago


If you use suhosin.executor.func.blacklist instead of disabled_functions in your php.ini, function_exists will return true for a disabled function. I used this to have the same beahviour with suhosin.executor.func.blacklist and disabled_functions:

<?php
function suhosin_function_exists($func) {
    if (
extension_loaded('suhosin')) {
       
$suhosin = @ini_get("suhosin.executor.func.blacklist");
        if (empty(
$suhosin) == false) {
           
$suhosin = explode(',', $suhosin);
           
$suhosin = array_map('trim', $suhosin);
           
$suhosin = array_map('strtolower', $suhosin);
            return (
function_exists($func) == true && array_search($func, $suhosin) === false);
        }
    }
    return
function_exists($func);
}
?>


breadman

19 years ago


Functions within a function are better off as anonymous returns from create_function(), unless you want to be able to call it elsewhere.

However, I have used this in skinning:  I use alert_box() to display certain errors, like a faulty SQL query.  This simply calls display_alert(), which is defined in my skin scripts.  However, alert_box() is sometimes called before I know which skin to load, so it has its own functionality which it uses if function_exists('display_alert') returns false.


Dan

16 years ago


I would like to comment on the following post:

A note of caution: function_exists() appears to be case-insensitive (at least as of PHP 4.3.8).  e.g.:

<?php
  
function MyCasedFunction() {
       return
true;
   }
// Will return true, even though casing is "wrong"
  
if (function_exists("mYcAsEdFuNcTiOn"))
       echo
"I see it!";
?>

I believe that function calls itself are case insensitve, so this function is returning a valid truth. PHP doesn't care about cases.


ckrack at i-z dot de

19 years ago


i was wondering whether is_callable or function exists is faster when checking class methods.

is_callable(array('foo', 'bar'));
function_exists('foo::bar');

my results when doing each operation 10000 times with a simple test class were the following:

is_callable: 0.28671383857727 seconds
function_exists: 0.14569997787476 seconds

(following tests have proved this to be true).

thus you can see, function_exists is twice as fast as is_callable.


bob at thethirdshift dot net

18 years ago


I, too, was wondering whether is_callable or function exists is faster when checking class methods.  So, I setup the following test:

<?php
function doTimes($start, $end)
  {
   
$start_time = explode (" ", $start);
   
$start_time = $start_time[1] + $start_time[0];
   
$end_time = explode (" ", $end);
   
$end_time = $end_time[1] + $end_time[0];
   
$time = $end_time - $start_time;
    return
$time;
  }

class

test
 
{
      function
test()
      {
          return
true;
      }
  }
$callableIsTrue = false;
$startIsCallable = microtime();
for(
$i = 0; $i < 10000; $i++)
  {
      if(
is_callable(array('test', 'test'))) { $callableIsTrue = true; }
  }
$endIsCallable = microtime();$existsIsTrue = false;
$startExists = microtime();
for(
$i = 0; $i < 10000; $i++)
  {
      if(
function_exists('test::test')) { $existsIsTrue = true; }
  }
$endExists = microtime();$timeIsCallable = doTimes($startIsCallable, $endIsCallable);
$timeExists     = doTimes($startExists, $endExists);

echo

"<b>is_callable = ".($callableIsTrue ? "TRUE" : "FALSE")."</b>, n";
echo
"<b>function_exists = ".($existsIsTrue ? "TRUE" : "FALSE")."</b><br>n";

echo

"<br>Did 10000 is_callables in ".$timeIsCallable." seconds";
echo
"<br>Did 10000 function_exists in ".$timeExists." seconds";
?>

This gives the output :

is_callable = TRUE, function_exists = FALSE

Did 10000 is_callables in 0.0640790462494 seconds
Did 10000 function_exists in 0.0304429531097 seconds

So the fact that function_exists is twice as fast is slightly over shadowed by the fact that it doesn't work on class methods, at least not as far as I can tell.


admin at gk-root dot com

11 years ago


// If you want to chack if the function is enabled or disable in php.ini you can use this function:

<?php
function func_enabled($func) {
   
$disabled = explode(',', ini_get('disable_functions'));
    foreach (
$disabled as $disableFunction) {
       
$is_disabled[] = trim($disableFunction);
    }
    if (
in_array($func,$is_disabled)) {
       
$it_is_disabled["m"] = $func.'() has been disabled for security reasons in php.ini';
       
$it_is_disabled["s"] = 0;
    } else {
       
$it_is_disabled["m"] = $func.'() is allow to use';
       
$it_is_disabled["s"] = 1;
    }
    return
$it_is_disabled;
}
?>

// An example of how to use:

<?php
$if_is_disabled
= func_enabled('exec'); // return Arrey
echo $if_is_disabled["m"]; // return text value
echo '<br/>';
echo
$if_is_disabled["s"]; // return 1 or 0
?>


neelam_ab2003 at yahoo dot co dot in

17 years ago


<?php
/*PHP doesn't Support nested functions. I have tried following in PHP_VERSION - 5.1.2*/function A(){}

function

B(){
    function
C(){
        function
D(){}
    }
}
IsFunctionExist('A');
IsFunctionExist('B');
IsFunctionExist('C');
IsFunctionExist('D');

function

IsFunctionExist($funcName){
    echo
function_exists($funcName)?" $funcName exist <br>":" $funcName doesn't exist <br>";
}
?>

/*O U T P U T
A exist
B exist
C doesn't exist
D doesn't exist
*/

dshearin at excite dot com

19 years ago


This can be used to conditionally define a user function. In this sense, it can act as a sort of inline include_once().

For example, suppose you have a function A that calls function B. B is only used inside function A and is never called from anywhere else in the script. It's logical (and perfectly legal in PHP) to define B inside of A's definition, like so:

<?php

function A($inputArray)

{

   if (!
function_exists('B'))

   {

      function
B($item)

      {

          
// Do something with $item

         // and return result

         
return $result;

      }

   }

   foreach (
$inputArray as $nextItem) $outputArray[] = B($nextItem);

   return
$outputArray;   

}

?>



Without the function_exists test, you would get a fatal error the second time you called A, as PHP would think you were trying to redefine B (not legal in PHP). The placement of the test is also important. Since the if block is executed sequentially, like any other block of code, it must come before any call to the function defined within.


chaumo

17 years ago


to avoid direct calls this can be better than function_exists
in the parent file:
<?php
define
("IN_MODULE",true);
?>
and in the target file:
<?php
if(!defined("IN_MODULE")) die("Can't access the file directly");
?>

White-Gandalf

15 years ago


I stumbled over the same problem as "eddiec" (users not able or not willing to use "_once"-suffixes).

A possible alternative explanation for the behavior:

If a file is included, it is possibly parsed every include-time.(?)
While parsing, every function in global scope is tried to register. THIS gets wrong, when multiple times included, and it produces an error.

If functions are defined within block scopes, their registration seems to be delayed until execution of such a block. Thus, not the function "function_exists" functions wrong, but simply the philosophy of the interpreter produces such results.

Thus, the same effect can be achieved by simply putting block braces around the contents of an include_once file:

if (function_exists('function_in_question')) return;
{
    function function_in_question(...)
    {
        ...
    }
    ...other stuff
}

...which is equivalent to...

if (!function_exists('function_in_question'))
{
    function function_in_question(...)
    {
        ...
    }
    ...other stuff
}


b dot g dot dariush at gmail dot com

9 years ago


function_exists() does not cache its query internally.

by executing the following code

        $funcs = array_shift(get_defined_functions());
        $l = new coreutilesloadTime;
        $times = 0;
        $l->start();
        for($index = 0; $index<count($funcs); $index++)
        {
            foreach($funcs as $func)
            {
                $times++;
                if(function_exists($func)) ;
            }
        }
        $s = $l->stop();
        echo "<span style='color:green'>$times</span> took : $s";
        # the output would be
         $> 2365444 took : 0.70324

By executing the

        $funcs = array_shift(get_defined_functions());
        $l = new coreutilesloadTime;
        $times = 0;
        $l->start();
        static $func_check = array();
        for($index = 0; $index<count($funcs); $index++)
        {
            foreach($funcs as $func)
            {
                $times++;
                if(!isset($func_check[$func]))
                {
                    if(function_exists($func)) ;
                    $func_check[$func] = 1;
                }
                else $func_check[$func];
            }
        }
        $s = $l->stop();
        echo "<span style='color:green'>$times</span> took : $s";
        # the output would be
        $> 2365444 took : 0.53446

There is a 0.16878 seconds improvement, when you use static array to cache methods existence.


brooklynphil at hotmail dot com

16 years ago


to bob at thethirdshift dot net
regarding is_callable vs function_exists.

using your code
is_callable = TRUE, function_exists = FALSE

Did 10000 is_callables in 0.0443360805511 seconds
Did 10000 function_exists in 0.0111110210419 seconds

then we replace
is_callable(array('test','test'));
with
$callarray = array('test','test'); // place this outside for-loop
is_callable($callarray);

is_callable = TRUE, function_exists = FALSE

Did 10000 is_callables in 0.0314660072327 seconds
Did 10000 function_exists in 0.0120670795441 seconds

then we replace
is_callable(array('test','test'));
with
is_callable('test','test');

is_callable = TRUE, function_exists = FALSE

Did 10000 is_callables in 0.00991606712341 seconds
Did 10000 function_exists in 0.0113790035248 seconds

I hope you can see that loop-testing functions is not so simple. :)


zach at bygeekz dot com

14 years ago


to php at fluidthoughts dot com

you aren't comparing against false, that if compares against true, so it's going to return that, as false != true
true being 1, True, (bool)True, etc.
false being 0, False, Null, etc
<?php

$foo

=null;
if (
$foo) { echo 'yay'; } //does not echo yay, because null is not True$foo=false;
if (
$foo) { echo 'yay'; } //does not echo yay, because false is not True$foo=null;
if (!
$foo) { echo 'yay'; } //echoes yay!$foo=false;
if (!
$foo) { echo 'yay'; } //echoes yay!?>

This..
<?php
   
if (!function_exists('')) {
                echo
"empty string function doesnt exist as compared as negativen";
        }

        if (!

function_exists(NULL)) {
                echo
"NULL function doesnt exist as compared as negativen";
        }
?>
Works.

Alternatively, to enter upon existance..

Use your code. Since they dont exist, it wont enter..


php at fluidthoughts dot com

15 years ago


function_exists returns false on NULL and empty string:

<?php
       
if (function_exists('')) {
                echo
"empty string function existsn";
        }

        if (

function_exists(NULL)) {
                echo
"NULL function existsn";
        }
?>

Neither of the echo statements happen when I run this.


eddiec at stararcher dot com

16 years ago


Note that function_exists will return TRUE in the following situation, presumably because the function "testfunc" was defined when the script was PARSED/ITERPRETED, before the function_exists call was made at RUNTIME:

<?php

if (function_exists('testfunc')) return;

function
testfunc() { }

?>



So, this construction is not useful for preventing testfunc from being multiply defined if the script is muliply included or required.

However, the following construction DOES work to prevent multiple defines of testfunc:

<?php

if (!function_exists('testfunc')) {

  function
testfunc() { }

}

?>



CONTRAST this with similar uses of defined() which is completely runtime evaluated.  These both work:

<?php

if (defined('testfunc_defined')) return;

define('testfunc_defined', 1);

function
testfunc() { }

?>



AND...

<?php

if (!defined('testfunc_defined')) {

define('testfunc_defined', 1);

function
testfunc() { }

}


dieter at edarta dot be

16 years ago


to brooklynphil at hotmail dot com:

Your post is misleading, namely the 3rd and last speedtest you describe is an unfair comparison:

<?php
is_callable
('test','test');
?>

The value of the 2nd parameter $syntax_only is 'test' and this evaluates to boolean true. In other words, this is exactly the same as calling the function like this:

<?php
is_callable
('test',true);
?>

Of course this will be faster because is_callable only does a very basic syntaxcheck. From the documentation: 'It will only reject simple variables that are not strings, or an array that does not have a valid structure to be used as a callback.'

If you omit this erroneous 3rd test, then according to your examples function_exists is 2 to 4 times faster.

I hope you can see that loop-testing functions is not so simple. :)

rtfm


Условия:
1) удалённый хост с доступом по ssh;
2) много файлов, выкачивать их не вариант.
get_defined_functions() говорит что функция определена, интерпретатор не ругается на её вызов.
Как найти где определяется функция?

Пробовал следующее:

grep --include="*.php" -r -l "function foo_bar(" ./

Я подумал что в регексе открывающая скобка будет служебным символом, но всё всё ок. Создал файл с определением функции и только он нашёлся после того как команда отработала.


  • Вопрос задан

    более трёх лет назад

  • 3284 просмотра

<?php
function test() {
}

$ref = new ReflectionFunction('test');
echo $ref->getFileName().':'.$ref->getStartLine().PHP_EOL;

Пригласить эксперта

Я подумал что в регексе открывающая скобка будет служебным символом

Так вы и не просили поиск по регулярке. Флаги -P или -G

grep -riP 'functions+foo_bars*('  --include="*.php" ./


  • Показать ещё
    Загружается…

21 мая 2023, в 01:51

500 руб./за проект

20 мая 2023, в 23:39

10000 руб./за проект

20 мая 2023, в 22:30

500 руб./за проект

Минуточку внимания

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

Хорошо, когда проект писался самостоятельно и примерно можно запомнить какая архитектура проекта. А что делать, когда сайт достается “в наследство” и не просто сайт, а целый огромный портал и очень срочно необходимо переписать вывод на экран в какой-то функции?

Как же найти файл где хранится php функция, которую нам нужно изменить?

Если есть ssh – можно запустить поиск по проекту, а если есть только фтп – то придется или писать “поисковый скрипт на пхп” или копировать сайт на компьютер и на нем уже делать поиск нужной функции.

А можно воспользоваться штатными средствами самого php, а точнее классом ReflectionFunction.
Поместим этот код сразу за вызовом искомой функции (или, например, в самом низу сайта)

$file_function = new ReflectionFunction('function_name');
print $file_function ->getFileName() . ':' . $file_function ->getStartLine();

и на экране отобразится полный путь к файлу и номер строки:

/sata6/home/www/artkiev_com/meta/data/core/system/claster_8/run.php:114

You will not have many options there. The other option (which was posted in the other question) to force the caller to provde it’s information with the function call (using PHP magic constants):

callFunction(1, 2, 3, __FUNCTION__)
callFunction(1, 2, 3, __CLASS__,  __METHOD__)
callFunction(1, 2, 3, $this,  __METHOD__)

  or

$class = new ReflectionClass( __CLASS__ ); 
$method = $class->getMethod( __METHOD__ );
callFunction(1, 2, 3, $method) // $method would be a ReflectionMethod obj

would be a possible alternative. But it’s

  • obfuscating your code
  • can be “manipulated” which might cause the code of callFunction to fail and it would be quite difficult to track those errors down.

If I were in your place, I would try to avoid it in a function that is used throughout your code. use debug_backtrace (even if it might be ‘slow’). Readable code wins over fast code.

Добавить комментарий