通过CLI运行PHP时的URL参数

时间:2014-03-03 11:53:44

标签: php command-line-interface

为什么我可以将参数(如URL中的查询字符串或URL参数)传递给通过CLI运行的PHP文件?我需要这个需要输入参数的PHP cron作业。例如:

$ php /home/abc/www/myphp.php?param1=abc

6 个答案:

答案 0 :(得分:4)

每个命令行界面argcargv都有两个特殊变量。

argv - 传递给脚本的参数数组。

argc - 传递给脚本的命令行参数的数量(如果在命令行上运行)。

制作脚本cli.php

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

并用参数调用它:

$ php cli.php argument1=1

你应该得到如下输出:

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

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

如果你仍然要求有一个单点条目,并且能够处理url查询,因为$ _GET通过添加一个开关使你的脚本像路由器一样:

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

但是 - 它违反了SRP - 单一责任原则!考虑到这一点,如果你仍然如此要求让它像你在问题中所说的那样工作,你可以这样做:

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
}

之后将代码转换为使用$ data数组而不是$ _GET

...祝你有愉快的一天!

答案 1 :(得分:1)

这是我的CLI应用程序库中使用$_SERVER['argv']提取/重写的类,其形式与linux运行命令(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;
        }
    }
?>

使用

<?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!"

<强>输出

  

- 重置已通过!
   - 测试通过嘿你!   --foo被传递为吧!

答案 2 :(得分:1)

如果底层代码绝对需要$_GET(并且不依赖于其他HTTP功能),您可以编写一个简单的包装器,它滥用不是只读超全局的事实:

<?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');

...然后安排代理:

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

答案 3 :(得分:0)

尝试wget并输出为null

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

答案 4 :(得分:0)

最好的解决方案是重构和抽象出业务逻辑,保留原始脚本作为它的包装器。然后添加CLI脚本以包装CLI的相同业务逻辑。 这样,您可以使用常规CLI参数处理:http://www.php.net/manual/en/reserved.variables.argv.php

答案 5 :(得分:0)

我需要做同样的事情,将查询参数传递给 php 脚本以作为 cron 作业运行。该脚本来自第三方,我不想修改或编写新脚本。解决方案是将查询字符串参数放在单引号中,并用与号替换问号。就我而言,我传递了三个参数。

yq read abc.yaml abc@in.xyz.com

我在此 post 中找到了解决方案,尝试了一下,对我来说效果很好。