tags:

views:

600

answers:

2

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?

+4  A: 

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.

zombat
`__FILE__` and `__LINE__` may be way more efficient, although it adds code clutter. By the way, maybe proper debugging could replace file/line logging when the need arises.
Altherac
+3  A: 

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.    
}
Lior Cohen
Thanks, I see you changed filename to file.
Tom
Yes. Made a mistake there and quickly fixed it when I've noticed it. 2:30AM. Time to go to bed :)
Lior Cohen
Actually, there is a problem. I'm coding in an object oriented way and it's returning the line and the script that is calling the object in which the function is called. Instead, it should give me the name of the included class and the line within that class file. Any idea?
Tom
You need to be more specific here. Can you show me what you're getting and what you're expecting instead?
Lior Cohen
Hello Lior Cohen, could you please check my edited original post? I explained everything in detail there. Thanks!
Tom
I've just copied and pasted your code, created the 3 files and ran them. The results I got were exactly what you were expecting to get: TestClass.class.php, line 6.Please make sure you have exactly the same code as my example above. Go over the 4 lines and make sure they are exactly the same as above.
Lior Cohen
I'm amazed. It does work. I'm sure I tested it yesterday and it seemed to give me wrong results. Well, sorry about that. Not sure what went wrong but it works now.
Tom