[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