[prev in list] [next in list] [prev in thread] [next in thread]
List: php-general
Subject: Re: [PHP] Which file called the function?
From: "Nathan Nobbe" <quickshiftin () gmail ! com>
Date: 2007-12-31 21:38:41
Message-ID: 7dd2dc0b0712311338o32cddd52ydfa61b6cf8605e89 () mail ! gmail ! com
[Download RAW message or body]
On Dec 20, 2007 7:06 PM, Robert Cummings <robert@interjinn.com> wrote:
> On Thu, 2007-12-20 at 19:54 +0000, George Pitcher wrote:
> > > On Thu, December 20, 2007 8:37 am, Christoph Boget wrote:
> > > > Let's say I have the following 3 files
> > > >
> > > > global.php
> > > > <?
> > > > function myFunc() { echo __FILE__; }
> > > > ?>
> > > >
> > > > one.php
> > > > <?
> > > > include( 'global.php' );
> > > > echo 'You are in file: ';
> > > > myFunc();
> > > > ?>
> > > >
> > > > two.php
> > > > <?
> > > > include( 'global.php' );
> > > > echo 'You are in file: ';
> > > > myFunc();
> > > > ?>
> > > >
> > > > In each case, what is echoed out for __FILE__ is global.php. Apart
> > > > from
> > > > analyzing the debug_backtrace array, is there any way that myFunc()
> > > > would
> > > > display "one.php" and "two.php" respectively?
> > >
> > > $_SERVER['PHP_SELF'] and other bits in $_SERVER have the "main" PHP
> > > filename in them.
> > >
> > > __FILE__ will always be exactly the file that it's in.
> > >
> > > In between, I think you are stuck with the debug_backtrace.
> > >
> > > NOTE:
> > > If it's for error logging or error reporting, note that trigger_error
> > > automatically passes in the file/line to the error handler.
> >
> > I'm far from being an expert, and often see more efficient ways of doing
> > things (more efficient tham my own methods). Howevr, I've just been
> dealing
> > with a similar problem.
> >
> > I have a functions file with over 400 functions (and that may be too
> many -
> > but it works). I've been adding some error reporting in to my PEAR::DB
> > queries, but wanted to know which page triggered the function. I went
> > theough my php pages and gane each one a $pg variable at the start
> > containing the bare name of the file, eg 'home' rather than 'home.php'.
> I
> > then went to each function containing either a DB query (ore one which
> calls
> > another DB-related function. I did a global search and replace for the
> > function name 'func(' replaced by 'func($pg,'. I use Dreamweaver so this
> was
> > fairly straightforward.
> >
> > It worked for me, but now someone is about to show me a quicker, cleaner
> > way, aren't they?
>
> Yes, I am.
>
> <?php
> function checkpoint()
> {
> $trace = debug_backtrace();
>
> $caller = isset( $trace[0] ) ? $trace[0] : array();
> $owner = isset( $trace[1] ) ? $trace[1] : array();
>
> $file
> = isset( $caller['file'] )
> ? $caller['file']
> : null;
>
> $class
> = isset( $owner['class'] )
> ? $owner['class']
> : null;
>
> $function
> = isset( $owner['function'] )
> ? $owner['function']
> : null;
>
> $line
> = isset( $caller['line'] )
> ? $caller['line']
> : null;
>
> $type
> = isset( $owner['type'] )
> ? $owner['type']
> : null;
>
> list( $timeSub, $time ) = explode( ' ', microtime() );
> $timeSub = ereg_replace( '^[^.]\.', '', $timeSub );
> $timeSub = substr( str_pad( $timeSub, 6, '0' ), 0, 6 );
>
> echo 'Checkpoint '
> .'['.date( 'Y-m-d H:i:s', $time ).'.'.$timeSub.']: '
> .($file === null
> ? ''
> : $file.' ')
> .($line === null
> ? ''
> : sprintf( '{%05d} ', $line ))
> .($class === null
> ? ''
> : $class.$type)
> .($function === null
> ? ''
> : $function.'()')
> .$this->nl;
> }
>
> ?>
>
incidentally, i was looking through Pear::Log today;
i stumbled upon this and thought id share:
/**
* Using debug_backtrace(), returns the file, line, and enclosing
function
* name of the source code context from which log() was invoked.
*
* @param int $depth The initial number of frames we should step
* back into the trace.
*
* @return array Array containing three strings: the filename, the
line,
* and the function name from which log() was called.
*
* @access private
* @since Log 1.9.4
*/
function _getBacktraceVars($depth)
{
/* Start by generating a backtrace from the current call (here). */
$backtrace = debug_backtrace();
/*
* If we were ultimately invoked by the composite handler, we need
to
* increase our depth one additional level to compensate.
*/
if (strcasecmp(@$backtrace[$depth+1]['class'], 'Log_composite') ==
0) {
$depth++;
}
/*
* We're interested in the frame which invoked the log() function,
so
* we need to walk back some number of frames into the backtrace.
The
* $depth parameter tells us where to start looking. We go one
step
* further back to find the name of the encapsulating function from
* which log() was called.
*/
$file = @$backtrace[$depth]['file'];
$line = @$backtrace[$depth]['line'];
$func = @$backtrace[$depth + 1]['function'];
/*
* However, if log() was called from one of our "shortcut"
functions,
* we're going to need to go back an additional step.
*/
if (in_array($func, array('emerg', 'alert', 'crit', 'err',
'warning',
'notice', 'info', 'debug'))) {
$file = @$backtrace[$depth + 1]['file'];
$line = @$backtrace[$depth + 1]['line'];
$func = @$backtrace[$depth + 2]['function'];
}
/*
* If we couldn't extract a function name (perhaps because we were
* executed from the "main" context), provide a default value.
*/
if (is_null($func)) {
$func = '(none)';
}
/* Return a 3-tuple containing (file, line, function). */
return array($file, $line, $func);
}
-nathan
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic