Reputation: 357
I'd like to create a debug function that dumps information about the execution context along with some other info.
In debug.php I have a function that dumps whatever is passed as a parameter. I'm interested in a way of calling the dump function from, say example.php and have it return the file name, the line number and the function name of the calling context.
1. <?php
2. function my_function(){
3. $var = 'My example';
4. dump( $var );
5. }
6. ?>
example.php
I'd like for the above function to output: "example.php, my_function, 4: My example".
Is there anyway of doing this (short of passing __FILE__
, __FUNCTION__
, and __LINE__
) as parameters?
Upvotes: 3
Views: 1609
Reputation: 1462
I too use debug_backtrace, I try to handle different scenarios, this might seem too time consuming or bad idea, but for me (building my own small mvc has been very helpful). Example of scenarios to handle:
All this scenarios will affect the results brought by debug_backtrace, my debug function (defined below) tries to handle these scenarios.
Each function/method is defined like this
function my_func(){if(__DEBUG){dbg(debug_backtrace(),__CLASS__);}
then when I want to produce the final code I can run a simple script to replace that if statement, for example
a="if(__DEBUG){dbg(debug_backtrace(),__CLASS__);}"
b="//replace_what_ever"
dir="/var/www/mydir/"
find $dir -name \*.inc -exec sed -i "s/$a/$b/g" {} \;
find $dir -name \*.php -exec sed -i "s/$a/$b/g" {} \;
As for the debug function it can go at the very end of the script, let's say at the very and of index.php However if you have defined a class of your own for session handler then the very last command is executed inside the destructor of that class.
So in most cases when something goes wrong your debug function will let you know about. However on a fatal error the line that prints the results created/stored (stored in some array, here $dbg_log) by the debug function will fail to print (the print command is put at the end of index.php for example)!! For this case you need a manual handler (only for fatal errors) to print the array of result, this is how I do it:
register_shutdown_function('handleShutdown');
//Catch fatal errors
function handleShutdown() {
$error = error_get_last();
global $dbg_log;
echo "<pre>";
if(
$error['type'] === E_COMPILE_ERROR or
$error['type'] === E_ERROR or
$error['type'] === E_PARSE or
$error['type'] === E_CORE_ERROR or
$error['type'] === E_CORE_WARNING or
$error['type'] === E_RECOVERABLE_ERROR
)//we need to catch fatal errors under debug
{
//print_r($error); if you like
$dbg_log[] = " Tip: Start backward, the failing function (line) cannot echo a text put at the end of the function!";
$last = count($dbg_log)-1;
for($i=$last;$i>-1;$i--){
echo "$i: {$dbg_log[$i]} \n<br>";
}
}
}
The $dbg_log is used in order to collect all this information, defined in global context (see below).
Now this is what my debug function looks like:
define('__DEBUG', true); // Easily switch from/to debug mode
$dbg_log = array(); // Keep log of function calling sequence for debuging purposes
function dbg($tr, $callee_class){
global $dbg_log;
// If the file of the caller exists
if(isset($tr[0]['file'])){
$caller = $caller=$tr[0]["file"].':'.$tr[0]["line"]; // Then we can get its name and calling line
// If the caller is a function then it was a callee before so $tr[1] should exists
if(isset($tr[1])){
// If the caller is a class method
if(isset($tr[1]["class"])){
$caller = $tr[1]["class"]."whenever->".$caller=$tr[1]["function"].':'.$caller;
}
// Else
else{
$caller = $tr[1]["function"].$caller;
}
}
}
// Else this is an auto call by php compiler
else{
$caller = 'auto';
}
// Log the debug info
$dbg_log[] = 'Started: '.$callee_class.'::'.$tr[0]['function'].' by '.$caller;
}
The $tr (trace) array contains the results of the debug_backtrace as they existed inside the callee faunction. An other thing to mention is that a caller was always a calle before becoming a caller!!
These are some real (meaningless to you, however the whole information provided is obvious) results that the output of $dbg_log array gives (on fatal error or normal exit):
27: Started: Framework\registry::get by App\View\WebWindowOne->__construct:/var/www/MyProject/protected/view/WebWindowOne/WebWindowOne.php:36
26: Started: App\View\WebWindowOne::__construct by Application->AppStart:/var/www/MyProject/protected/Web_Application.php:240
25: Started: Application::AppStart by Application->__construct:/var/www/MyProject/protected/Web_Application.php:150
24: Started: Framework\riskManager::__construct by Application->{closure}:/var/www/MyProject/protected/Web_Application.php:52
There is a lot of info, line number, class etc, with very little effort (just using this function my_func(){if(__DEBUG){dbg(debug_backtrace(),__CLASS__);}
) for each function/method you define.
Upvotes: 0
Reputation: 15903
PHP's debug_backtrace()
:
print_r(debug_backtrace());
The output of backtrace is an array of associative arrays that name these constants you are looking for. For this sample code, the array debug_backtrace()
returns would look like this:
Array
(
[0] => Array
(
[file] => /t.php
[line] => 9
[function] => abc
[args] => Array
(
[0] => a
)
)
)
Upvotes: 2
Reputation: 175038
Yes, you can use debug_backtrace()
.
It returns an array of all the callers and files (traces included files as well) in reverse order (highest ancestor last). So the caller would be the first in the array:
$caller_info = next(debug_backtrace());
Upvotes: 5