PHP: Basic question about __FILE__

Let's say I have a function called outputFile($source, $outputFileName, $message), and that it lives in a file called utils.php.

When I invoke this function, I always pass __FILE__ for the first parameter (i.e., $source). Let's say I'm calling that function while in index.php. So when I call the function like this: outputFile(__FILE__, "someFileName", "Hello World"), it would output to my log file something like this:

[Source=index.jsp]Hello World!

Open in new window


I'm kind of getting tired of having to type __FILE__ all the time when I call my outputFile function. Is there a way for my function to internally pick up which file it is being invoked from? In other words, if I were in index.php, is there a way my outputFile() function can know it was invoked from index.php and use that as the $source? I know if I hardcoded __FILE__ in outputFile(), it's going to output "utils.php" (where it lives) rather than where it was invoked.

Thanks.
elepilAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Dave BaldwinFixer of ProblemsCommented:
If you're getting tired of typing anything, you're in the wrong profession.  Programmers are actually secretary / typists with additional skills as programmers.

As for your function to 'know' where it's being invoked from?  I've never heard of such a thing.  But then I never use '__FILE__' anyway.  After looking it up, I see why.  On shared hosting where most of my customers are, an absolute path is useless because shared hosting frequently blocks access thru an absolute path.  All you can use is paths relative to your web root.

http://php.net/manual/en/language.constants.predefined.php
Julian HansenCommented:
Take a look at debug_backtrace() http://php.net/manual/en/function.debug-backtrace.php

It returns an array of the points along the execution path.

However, this is traditionally a debug tool - so not something you really want to be doing in production code.

Other than that __FILE__ by definition has to refer to the file containing the code being executed.

Sometimes there are no short cuts - if you want your output to show what file your output came from then you have to tell it.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
elepilAuthor Commented:
The day I cease getting tired of repetition is the day I stop making function libraries to make my life and future projects easier. Programming is one of the few professions where laziness is a virtue. All I'm trying to do here is streamline tasks, trying to do things in less steps than more. If I can create a function with two arguments than three, I'd choose that.

With PHP being so rich and numerous in functions, I was hoping people more knowledgeable in PHP than I might know of a function that allows an invoked function to somehow detect where it was invoked from. If that sounds like a bizarre expectation, remember the magic functions of PHP that allow one to create classes with no getters or setters and somehow end up populated in full.

I don't need an absolute path, just some indication where the function was invoked that I could output to my log file, just so I'd know which file the function was invoked from.
Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

elepilAuthor Commented:
JulianH, now that's what I'm talking about!

Since debug_backtrace() returns an array, I think I might be able to programmatically construct a "bread crumb" and output it into my log file; this way, I can do away with __FILE__ altogether. Thanks, JulianH!
Julian HansenCommented:
You are welcome
elepilAuthor Commented:
By the way. Dave, regarding what you said:

Programmers are actually secretary / typists with additional skills as programmers.

If all you do are forms and database calls, then you'd be a glorified secretary with great copy/paste skills, and you probably wouldn't deserve good pay.

I have yet to find a programmer job like that though. In all the work I've done, there always some challenge. Just in the application I'm currently working on, I had to make a series of JavaScript constructor functions that act as self-contained components (e.g. an elaborate highly-customizable tooltip, validator functions that work with my tooltip() function for highly flexible field validation, reusable constructor functions for slide shows, reusable functions for <div> overlays on any section of the page, etc.), things I don't think secretaries would even imagine doing. These are the stuff I've done since I started my transitioned to the PHP platform. Prior to that when I was doing java with Adobe Flex, I was making reusable custom components for clients, as well as dealing with Adobe Flex's tree and datagrid components while employing drag and drop. If you can find a secretary who can do all that at a near-secretary's pay scale, please send him/her my way, I will hire the individual.
elepilAuthor Commented:
Good riddance to __FILE__. fo() will always tell you what file and line number it's in. Anywhere in your application, no matter which function level your program execution is in, you can output any string to an output file for debugging.

/**
 * 'fo' stands for file output. Writes specified text output to a specified filename, providing a top to
 * bottom execution stacktrace path.
 * @param String $output    The text content to be outputted to the file.
 * @param String $filename  The output filename. Defaults to '/_foLog' if not
 *                          provided.
 * 
 * Example: fo("Hello World"); // outputs "Hello World" to "/_foLog"
 *          fo("Boo", "/myFile"); // outputs "Boo" to "/myFile"
 */
function fo($output, $filename='/_foLog') {
    $desc = "";
    $arr = debug_backtrace();

    $desc .= "PROGRAM EXECUTION ORDER:\n";
    for ($i=count($arr)-1; $i>=0; $i--) {
        /* If 'file' is undefined, an error is output to php_error_log. 
         * Assigning a value of '<unknown>' to prevent the error. */
        if (!isset($arr[$i]['file'])) {
            $arr[$i]['file'] = '<unknown>';
        }
        /* If 'line' is undefined, it will bomb out. Assigning '0' to prevent 
         * an error */
        if (!isset($arr[$i]['line'])) {
            $arr[$i]['line'] = '0';
        }
        if ($i == count($arr)-1) {
            $desc .= count($arr)-$i . ':' . $arr[$i]['file'] . ' at line ' . $arr[$i]['line'] . "\n";
        } else {
            $desc .= count($arr)-$i . ':' . $arr[$i]['file'] . ' at line ' . $arr[$i]['line'] . 
                 ' inside ' . $arr[$i+1]['function'] . "()\n"; 
        }
    }

    $time = strftime("%Y-%m-%d %H:%M:%S", time());
    $handle = fopen($_SERVER["DOCUMENT_ROOT"] . "/" . $filename, "a");
    fwrite($handle, '[' . $time . ']' . "\n");
    fwrite($handle, $desc);
    fwrite($handle, 'OUTPUT: ' . "\n");
    fwrite($handle, $output . "\n\n");
    fclose($handle);
}

Open in new window

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.