Get code line and file that's executing the current function in PHP?

Php

Php Problem Overview


Imagine I have the following situation:

File1.php

<?php
 include("Function.php");
 log("test");
?>

Function.php

<?php
 function log($msg)
 {
  echo "";
 }
?>

I want to change the log function so that it would produce the following:

> test (file: File1.php, line number: 3)

So, any way to get the file name and the line number of the code that executed the current function in PHP?

EDIT for backlog usage comments: When I use backlog in my object oriented way of programming I have the following situation.

Index.php

<?php
 include("Logger.static.php");
 include("TestClass.class.php");
 new TestClass();
?>

TestClass.class.php

<?php
 class TestClass
 {
   function __construct()
   {
     Logger::log("this is a test log message");
   }
 }
?>

Logger.static.php

<?php
 class Logger
 {
   static public function log($msg)
   {
     $bt = debug_backtrace();
     $caller = array_shift($bt);
     echo $caller['file'];
     echo $caller['line'];
   }
 }
?>

This example will return as file "Index.php" and as line number 4, this is where the class is initiated. However, it is supposed to return the file TestClass.class.php and line number 6. Any idea how to fix this?

Php Solutions


Solution 1 - Php

You can use debug_backtrace().

http://us3.php.net/manual/en/function.debug-backtrace.php

So, in your log function, you would be able to retrieve the filename and line number from which the log function was called.

I'm using this approach in my logging classes and it has significantly reduced the amount of code required to get meaningful log data. Another benefit would be readability. Magic constants tend to get quite ugly when mixed with strings.

Here's a quick example:

function log($msg)
{
  $bt = debug_backtrace();
  $caller = array_shift($bt);

  // echo $caller['file'];
  // echo $caller['line'];

  // do your logging stuff here.    
}

Solution 2 - Php

debug_backtrace() can be used to trace back through the call stack. It can be slow though, so be careful with it if you're doing a lot of logging.

If you're using PHP 5.3, you could take advantage of late static binding and have a base class method of log(), and your child classes could call it but still maintain static references to __FILE__ and __LINE__.

A final option would be just pass __FILE__ and __LINE__ in as parameters when you call your log() function.

Solution 3 - Php

This is an old question but seeing as how my solution is not here, I'll provide it for posterity

     try{
		throw new Exception();
	}catch ( Exception $e ){
		$trace = $e->getTrace();
	}
	
	$length = 0;
	
	foreach ($trace as $t){
		if( $t['file'] != __FILE__ ){
			break;
		}
		++$length;
	}
	return array_slice( $trace, ($length - count( $trace ) ));

You can throw/catch to get a clean stack trace, then you need to look for the first line that contains this file ( typically that is where it is called from ) you can also use the index of the trace if you know it, or the function.

The exception stack trace is pretty much the same as doing debug_backtrace(true).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTomView Question on Stackoverflow
Solution 1 - PhpLior CohenView Answer on Stackoverflow
Solution 2 - PhpzombatView Answer on Stackoverflow
Solution 3 - PhpArtisticPhoenixView Answer on Stackoverflow