php: işlevin nereden çağrıldığını belirleyin


94

PHP'deki bir işlevin nereden çağrıldığını öğrenmenin bir yolu var mı? misal:

function epic()
{
  fail();
}

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

Yanıtlar:


131

Kullanabilirsiniz debug_backtrace().

Misal:

<?php

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

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

    print_r( $backtrace );
}

epic( 'Hello', 'World' );

Çıktı:

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
İlk defa debug_backtrace()ne kadar mükemmel bir fonksiyon buldum . Bunu kullanacağım!
David Yell

26

Kullanım 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
Bu kesinlikle istediğini yapıyor. Ancak dikkatli olun debug_backtrace(), pahalı bir arama. Çağrı zincirlerini belirlemek için kullanma alışkanlığı edinmeyin. Bu işlevleri "korumak" istiyorsanız, OOP ve korumalı yöntemleri kontrol edin.
ircmaxell

18

Bulduğum en hızlı ve en basit çözüm

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 dizüstü bilgisayarda hızı test ediyorum: 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;

Sonuçlar:

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

Benim için DEBUG_BACKTRACE_IGNORE_ARGS çok faydalı oldu, onsuz çok fazla bilgi vardı.
Arie

15

Öyleyse, gerçekten nasıl olduğunu hala bilmiyorsanız, işte çözüm:

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

1
Yani if ​​($ backtrace [1] ['function'] == 'epic') {// bir şeyler yapın; başka şeyler yapın; } ?? wow
Buttle Butkus

2
Evet, ama yapma! Kalıcı uygulama kodunda değil zaten. Parametreleri kullanın. debug_backtrace () oldukça ağır bir işleme benziyor.
Kluny


3

Aşağıdaki kodu deneyin.

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

Belirli bir işlevin çağrıldığı tüm dosyaların izini geri almak için iyi ve doğrudan bir çözüm.
istisna

3

Yığının en üstünde aramanın tam kaynağını izlemek istiyorsanız, aşağıdaki kodu kullanabilirsiniz:

$call_origin = end(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS));

Bu, zincirleme işlevleri yok sayar ve yalnızca en alakalı çağrı bilgilerini alır (ilgili, neyi başarmaya çalıştığınıza bağlı olarak gevşek bir şekilde kullanılır).


Teşekkür ederim. bu benim için çok zaman kazandırdı :)
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");

Umarım birine yardımcı olur. Gerçek işlev httpdocs dışında ise, sunucu buna izin vermeyecek şekilde kurulacağından bulunamaz. Sadece bir klasör derinliğinde test edildi, ancak yinelemeli metodoloji teoride çalışmalıdır.

Bu, 0.1 sürümüne benziyor, ancak üzerinde geliştirmeye devam etmeyi düşünmüyorum, bu yüzden birisi güncellerse onu yeniden yayınlamaktan çekinmeyin.


Çok fazla çalışma: bunu .bashrc'ye ekleyin ve function ff() { grep "function $1" $(find ./ -name "*.php") } ardından ff failveya arayın ff epic. bkz: github.com/MaerF0x0/VimSetup/blob/master/bashrc#L122
Mike Graf
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.