6

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
1
  • Take a look at this and especially this one. Commented Mar 3, 2014 at 12:01

7 Answers 7

7

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!

Sign up to request clarification or add additional context in comments.

4 Comments

This is not very useful for running a script intended to take query string parameters on the CLI...
@aderuwe, IMHO, it is very useful. You can take argv[0] explode it and build $_GET array by hand, also if you're running a scipt thru cli and expect it to behave like it's running from the request it violates SRP - Single Responsibility Principle.
Well, you didn't actually explain the building $_GET part. Agree with the second part of your comment.
@aderuwe i did it on purpose. ;) but anyway thanks, i'll edit my post.
2

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

2 Comments

I think you mean 'foreach' - other than that, upvoted.
Clever solution. I used a for to skip the first 'argv' which is the 'wrapper.php' itself: "for ($n = 1; $n < $argc; $n++) list($k, $v) = explode('=', $argv[$n], 2);"
1

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!

Comments

0

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

Comments

0

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.

Comments

0
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

Comments

-1

try wget and output to null

wget http://localhost/myphp.php?param1=abc -o /dev/null

1 Comment

Very creative, but this activates at least 2 php processes and other processes on the server (apache, nginx, caddy, tomcat, etc.), so this is an irrational solution.

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.