2

I have a PHP class file that is used as an include both through a web server and by a cron process. I am looking for a way to add some code to the head of the script so that I can detect if the script is being launched directly from the command line instead of being included in another script. This way I can make testing a bit easier by calling the script directly and having a function instantiate the object and execute some code on it without needing to create a wrapper script for it.

I tried using if (php_sapi_name() == 'cli') { but that tests true even if the script is being included in another script that was called from the command line.

4
  • This is a duplicate. See stackoverflow.com/questions/2397004/… for an answer. There are a few valid ones. Commented Apr 20, 2011 at 15:33
  • 3
    Nope, not a duplicate, the other question is different. Commented Apr 20, 2011 at 15:42
  • Isn't that more about detecting (and preventing) direct access through Apache, rather than what I want to do, detecting and performing additional operations when the file is directly accessed at the command line? Commented Apr 20, 2011 at 15:47
  • exactly. Your question is definitely not a duplicate of that one. Commented Apr 20, 2011 at 15:49

5 Answers 5

5

Checking that $argv[0] is set lets you know if things were invoked from the command line; it does not tell you if the file was invoked directly or if it was included from another file. To determine that, test if realpath($argv[0]) == realpath(__FILE__).

Putting it all together:

if (isset($argv[0]) && realpath($argv[0]) == realpath(__FILE__))
    // This file was called directly from command line
Sign up to request clarification or add additional context in comments.

1 Comment

This is the real answer. $argv[0] will be set on both the file that's being called through the cli and scripts that will be included by that script. But on all scripts $argv[0] will be set with the same filename, the one that's being directly called. __FILE__ != $argv[0] on included/required scripts.
3

You can check for the presence of $argv. If $argv[0] is set (the script name), your script is run from the command line.

4 Comments

Won't this still test true if the script is included by another script that was called from the command line? Although I could check the value of $argv[0] if it is set... Hm...
@Wige It´s a global variable so if your script is called from another script that is run from the command line, it will still exist.
This looks like the closest solution so far. What seems to work at the moment is if (isset($argv[0]) && strpos($argv[0], 'file.class.php') > 0) { This method seems to be the best to always detect if the file is being called directly from the command line.
@Wige Yes, you´ll have to add a second if the script that includes it can also be run from the command line.
1

You could test if $_SERVER['DOCUMENT_ROOT'] is empty. It will be empty in the command line execution since it's a variable predefined by apache.

What's interesting is $_SERVER['DOCUMENT_ROOT'] is defined but empty. I would have guessed it wouldn't be defined at all when using the cli.

You could also test if $argv is defined or its size (at least 1 when using CLI). I didn't test when including the file but if defined, sizeof($argv)would definitely be 0.

Other possible tests are $_SERVER['argc'] (0 when executed by a server, 1 when executed from CLI) and a strange $_SERVER['_'] defined to the path to the PHP binary, which is not defined at all when served.

To conclude, I would rely on $_SERVER['argc'] (or $argc) which is a direct count of the number of arguments passed to the command line: will always be 0 when the script is served. Relying on $argv is more complicated: you have to test if $argv[0] is set or if sizeof($argv) is > 0.

Comments

0

I have successfully used if (defined('STDIN')) as such a check. STDIN will be defined if the script is run from a shell, but not if it's in a server environment.

As you can see here and at the link Ryan provided in his comment, there are lots of possibilities.

Comments

0
if($_SERVER['SCRIPT_FILENAME']==__FILE__){
   // Directly
}else{
   // Included
}

1 Comment

When answering, it's recommended to share some context instead of just posting a snippet. Check this article to learn how to write an answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.