php: tentukan dari mana fungsi dipanggil


93

apakah ada cara untuk mengetahui, dari mana fungsi dalam PHP dipanggil? contoh:

function epic()
{
  fail();
}

function fail()
{
  //at this point, how do i know, that epic() has called this function?
}

Jawaban:


129

Anda bisa menggunakan debug_backtrace().

Contoh:

<?php

function epic( $a, $b )
{
    fail( $a . ' ' . $b );
}

function fail( $string )
{
    $backtrace = debug_backtrace();

    print_r( $backtrace );
}

epic( 'Hello', 'World' );

Keluaran:

Array
(
    [0] => Array
        (
            [file] => /Users/romac/Desktop/test.php
            [line] => 5
            [function] => fail
            [args] => Array
                (
                    [0] => Hello World
                )

        )

    [1] => Array
        (
            [file] => /Users/romac/Desktop/test.php
            [line] => 15
            [function] => epic
            [args] => Array
                (
                    [0] => Hello
                    [1] => World
                )

        )

)

5
Pertama kali saya menemukan debug_backtrace()fungsi yang luar biasa. Saya akan menggunakan yang ini!
David Yell

26

Penggunaan debug_backtrace():

function fail()
{
    $backtrace = debug_backtrace();

    // Here, $backtrace[0] points to fail(), so we'll look in $backtrace[1] instead
    if (isset($backtrace[1]['function']) && $backtrace[1]['function'] == 'epic')
    {
        // Called by epic()...
    }
}

9
Itu pasti melakukan apa yang Anda inginkan. Namun waspadalah debug_backtrace()adalah panggilan yang mahal. Jangan biasakan menggunakannya untuk menentukan rantai panggilan. Jika Anda ingin "melindungi" fungsi tersebut, lihat OOP dan metode yang dilindungi.
ircmaxell

18

Solusi tercepat dan termudah yang saya temukan

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] => ->
        )

)

Saya menguji kecepatan pada laptop Lenovo: Intel Pentiom CPU N3530 2.16GHz, RAM 8GB

global $times;
$start = microtime(true);
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
$times[] = microtime(true) - $start;

Hasil:

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

Bagi saya DEBUG_BACKTRACE_IGNORE_ARGS sangat berguna, tanpanya akan ada terlalu banyak info.
Arie

15

Jadi jika Anda masih BENAR-BENAR tidak tahu caranya, berikut solusinya:

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

1
Jadi Anda bisa menggunakan if ($ backtrace [1] ['function'] == 'epic') {// melakukan beberapa hal; lain lakukan beberapa hal lain; } ?? wow
Buttle Butkus

2
Ya, tapi jangan! Tidak dalam kode aplikasi permanen. Gunakan parameter. debug_backtrace () terlihat seperti operasi yang cukup berat.
Kluny


3

Coba kode di bawah ini.

foreach(debug_backtrace() as $t) {              
   echo $t['file'] . ' line ' . $t['line'] . ' calls ' . $t['function'] . "()<br/>";
}

Solusi yang baik dan langsung untuk mendapatkan kembali jejak semua file dari mana fungsi tertentu dipanggil.
Pengecualian

3

Jika Anda ingin melacak asal panggilan yang tepat di bagian atas tumpukan, Anda dapat menggunakan kode berikut:

$call_origin = end(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS));

Ini akan mengabaikan fungsi yang dirantai dan hanya mendapatkan info panggilan yang paling relevan (relevan digunakan secara longgar karena bergantung pada apa yang ingin Anda capai).


Terima kasih. yang menghemat banyak waktu bagi saya :)
Mohamed hesham

-1
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("<?php", "", $myFile);
            $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");

Semoga bisa membantu seseorang. Jika fungsi sebenarnya berada di luar httpdocs maka itu tidak dapat ditemukan karena server akan diatur untuk tidak mengizinkannya. Hanya mengujinya dalam satu folder juga tetapi metodologi rekursif harus bekerja dalam teori.

Ini seperti versi 0.1 tetapi saya tidak bermaksud melanjutkan pengembangan di atasnya jadi jika seseorang memperbaruinya, silakan memposting ulang.


Terlalu banyak pekerjaan: tambahkan ini ke .bashrc function ff() { grep "function $1" $(find ./ -name "*.php") } lalu panggil ff failatau ff epic. lihat: github.com/MaerF0x0/VimSetup/blob/master/bashrc#L122
Mike Graf
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.