为什么我可以将参数(如URL中的查询字符串或URL参数)传递给通过CLI运行的PHP文件?我需要这个需要输入参数的PHP cron作业。例如:
$ php /home/abc/www/myphp.php?param1=abc
答案 0 :(得分:4)
每个命令行界面argc
和argv
都有两个特殊变量。
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 中找到了解决方案,尝试了一下,对我来说效果很好。