Question

Is there any way I can pass parameters (like Query string in URL, or URL parameters) to a PHP file which is being run via CLI? I need this for some PHP cron jobs which need input from parameters. For example:

$ php /home/abc/www/myphp.php?param1=abc
Was it helpful?

Solution

There are two special variables in every command line interface argc and argv.

argv - array of arguments passed to the script.

argc - the number of command line parameters passed to the script (if run on the command line).

Make script cli.php

<?php
print_r($_SERVER['argv']);

and call it with argument:

$ php cli.php argument1=1

You should get the output looking like:

Array
(
    [0] => cli.php
    [1] => argument1=1
)

Source: http://www.php.net/manual/en/reserved.variables.server.php

If you are still so demanding to have a single point entry and to be able to process the url query as $_GET make your script act like a router by adding a switch:

if (PHP_SAPI === 'cli')
{
   // ... BUILD $_GET array from argv[0] 
} 

But then - it violates SRP - Single Responsibility Principle! Having that in mind if you're still so demanding to make it work like you stated in the question you can do it like:

if (PHP_SAPI === 'cli')
{
   /** ... BUILD  from argv[0], by parsing the query string, a new array and 
    *  name it $data or at will 
    */
}
else
{
   // ... BUILD  new $data array from $_GET array
}

After that convert the code to use $data array instead of $_GET

...and have a nice day!

OTHER TIPS

Here's an extracted/rewritten class from my CLI Application library using $_SERVER['argv'] in the same form that linux runs commands (foo.sh --param "value" --marap):

<?php
    class ArgumentScanner {
        private static $instance;
        private $arguments;

        public static function get() {
            if (empty(self::$instance)) {
                self::$instance = new ArgumentScanner();
            }

            return self::$instance;
        }

        public function __construct() {
            $this->arguments = $this->parseArguments($_SERVER['argv']);
        }

        public function __isset($argument) {
            return isset($this->arguments[$argument]);
        }

        public function __get($argument) {
            return (isset($this->arguments[$argument]) ? $this->arguments[$argument] : null);
        }

        /**
         * Is used to parse the contents of $_SERVER['argv']
         * @param array $argumentsRaw The arguments from $_SERVER['argv']
         * @return stdClass An object of properties in key-value pairs
         */
        private function parseArguments($argumentsRaw) {
            $argumentBuffer = '';
            foreach ($argumentsRaw as $argument) {
                if ($argument[0] == '-') {
                    $argumentBuffer = substr($argument, ($argument[1] == '-' ? 2 : 1));
                    $equalSign = strpos($argumentBuffer, '=');
                    if ($equalSign !== false) {
                        $argumentKey = substr($argumentBuffer, 0, $equalSign);
                        $argumentsParsed[$argumentKey] = substr($argumentBuffer, $equalSign + 1);
                        $argumentBuffer = '';
                    } else {
                        $argumentKey = $argumentBuffer;
                        $argumentsParsed[$argumentKey] = '';
                    }
                } else {
                    if ($argumentBuffer != '') {
                        $argumentKey = $argumentBuffer;
                        $argumentsParsed[$argumentKey] = $argument;
                        $argumentBuffer = '';
                    }
                }
            }
            return (object)$argumentsParsed;
        }
    }
?>

Use:

<?php
    $argumentScanner = ArgumentScanner::get();

    if (isset($argumentScanner->reset)) {
        echo '--reset was passed!';
    }

    if (isset($argumentScanner->test)) {
        echo '--test was passed as ' . $argumentScanner->test . '!';
    }

    if (isset($argumentScanner->foo)) {
        echo '--foo was passed as ' . $argumentScanner->foo . '!';
    }

    if (isset($argumentScanner->bar)) {
        echo '--bar was passed as ' . $argumentScanner->bar . '!';
    }
?>

php script.php --foo "bar" --reset -test="hey you!"

Output:

--reset was passed!
--test was passed as hey you!
--foo was passed as bar!

If the underlying code absolutely requires $_GET (and does not rely on other HTTP features) you can write a simple wrapper that abuses the fact that isn't a read-only superglobal:

<?php
// Untested (tweak to your own needs)
foreach($argv as $i){
    list($k, $v) = explode('=', $i, 2);
    $_GET[$k] = $v;
}
require_once('/home/abc/www/myphp.php');

... and then schedule your proxy instead:

php /path/to/wrapper.php param1=abc

Best solution there would be to refactor and abstract away the business logic, retain the original script as a wrapper for it. Then add a CLI script to wrap the same business logic for the CLI. That way, you can use the normal CLI parameter handling: http://www.php.net/manual/en/reserved.variables.argv.php

I needed to do the same thing, pass query parameters to a php script to run as a cron job. The script was from a third party and I didn't want to modify or write a new script. The solution was to place the query string parameters in single quotes and replace the question mark with an ampersand. In my case, I pass three parameters.

php /home/abc/www/myphp.php '&param1=abc&param2=def&param3=123'

I found the solution in this post, tried it and it works fine for me.

if (PHP_SAPI === 'cli')
{
    parse_str(implode('&', array_slice($argv, 1)), $_GET);
} 

This is solution that I use, if running via cli, put vars and values in $_GET, seems that is working for simple tasks , not sure if work with php getopt etc

try wget and output to null

wget http://localhost/myphp.php?param1=abc -o /dev/null
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top