将变量传递给从命令行运行的 PHP 脚本
Posted
技术标签:
【中文标题】将变量传递给从命令行运行的 PHP 脚本【英文标题】:Pass a variable to a PHP script running from the command line 【发布时间】:2011-10-13 04:37:50 【问题描述】:我有一个需要从命令行运行的 php 文件(通过crontab)。我需要将type=daily
传递给文件,但我不知道如何。我试过了:
php myfile.php?type=daily
但是返回了这个错误:
无法打开输入文件:myfile.php?type=daily
我能做什么?
【问题讨论】:
【参考方案1】:?type=daily
参数(以 $_GET
数组结尾)仅对 Web 访问的页面有效。
您需要像php myfile.php daily
一样调用它并从$argv
数组中检索该参数(这将是$argv[1]
,因为$argv[0]
将是myfile.php
)。
如果页面也用作网页,您可以考虑两种选择。使用 shell 脚本和 Wget 访问它,然后从 cron 调用它:
#!/bin/sh
wget http://location.to/myfile.php?type=daily
或者检查PHP文件是否从命令行调用:
if (defined('STDIN'))
$type = $argv[1];
else
$type = $_GET['type'];
(注意:您可能需要/想要检查 $argv
是否实际上包含足够的变量等)
【讨论】:
推荐使用getopt() defined('STDIN') 是做什么的?【参考方案2】:只需将其作为普通参数传递并在 PHP 中使用 $argv
数组访问它。
php myfile.php daily
在 myfile.php 中
$type = $argv[1];
【讨论】:
使用 : if (isset($argv[1])) echo . $argv[1]; else 死('不!'); 【参考方案3】:这些行会将 CLI 调用(如 php myfile.php "type=daily&foo=bar"
)的参数转换为众所周知的 $_GET
-array:
if (!empty($argv[1]))
parse_str($argv[1], $_GET);
虽然覆盖全局 $_GET
-array 相当麻烦,但它会快速转换所有脚本以接受 CLI 参数。
详情请见parse_str。
如果您想要更传统的 CLI 样式,例如 php myfile.php type=daily foo=bar
,一个小函数可以将其转换为与 $_GET
-array 兼容的关联数组:
// Convert $argv into associative array
function parse_argv(array $argv): array
$request = [];
foreach ($argv as $i => $a)
if (!$i)
continue;
if (preg_match('/^-*(.+?)=(.+)$/', $a, $matches))
$request[$matches[1]] = $matches[2];
else
$request[$a] = true;
return $request;
if (!empty($argv[1]))
$_GET = parse_argv($argv);
【讨论】:
完美答案!谢谢! 是的,我认为这正是 OP 真正想要的(在命令行上下文中运行(几乎)相同的(Web)PHP 脚本)。【参考方案4】:使用 getopt() 函数,我们还可以从命令行读取参数。只需使用 php
运行命令传递一个值:
php abc.php --name=xyz
文件abc.php
$val = getopt(null, ["name:"]);
print_r($val); // Output: ['name' => 'xyz'];
【讨论】:
【参考方案5】:像其他应用程序一样按索引发送参数:
php myfile.php type=daily
然后你可以像这样得到它们:
<?php
if (count($argv) == 0)
exit;
foreach ($argv as $arg)
echo $arg;
?>
【讨论】:
这不是很方便,它并没有分离出键和值,它只是传递值“type=daily”【参考方案6】:将此代码保存在文件myfile.php
中并以php myfile.php type=daily
运行
<?php
$a = $argv;
$b = array();
if (count($a) === 1) exit;
foreach ($a as $key => $arg)
if ($key > 0)
list($x,$y) = explode('=', $arg);
$b["$x"] = $y;
?>
如果在?>
标记之前添加var_dump($b);
,您将看到数组$b
包含type => daily
。
【讨论】:
虽然这可能会回答问题,但请考虑添加有关此解决方案如何解决问题的详细信息。请参考***.com/help/how-to-answer。 将此代码保存在文件 myfile.php 中,如果添加 var_dump($b); 则以 'php myfile.php type=daily' 运行在 ?> 标记之前,您会看到数组 $b 包含 type => daily。【参考方案7】:您可以使用以下代码同时使用命令行和 Web 浏览器。将此代码放在您的 PHP 代码之上。它为每个命令行参数创建一个 $_GET 变量。
在您的代码中,您只需要检查 $_GET
变量,无需担心脚本是从 Web 浏览器或命令行调用的。
if(isset($argv))
foreach ($argv as $arg)
$e=explode("=",$arg);
if(count($e)==2)
$_GET[$e[0]]=$e[1];
else
$_GET[$e[0]]=0;
【讨论】:
【参考方案8】:你可以use what sep16 on php.net recommends:
<?php
parse_str(implode('&', array_slice($argv, 1)), $_GET);
?>
它的行为与您对 cgi-php 的期望完全一样。
$ php -f myfile.php type=daily a=1 b[]=2 b[]=3
将$_GET['type']
设置为'daily'
,将$_GET['a']
设置为'1'
,将$_GET['b']
设置为array('2', '3')
。
【讨论】:
谁或什么是“sep16”? @PeterMortensen 我链接到的帖子的作者。【参考方案9】:<?php
if (count($argv) == 0)
exit;
foreach ($argv as $arg)
echo $arg;
?>
不应使用此代码。首先,CLI 的调用方式如下:
/usr/bin/php phpscript.php
它将有一个 argv 值,即脚本的名称:
array(2)
[0]=>
string(13) "phpscript.php"
这个总是会执行,因为它会传递一个或两个参数。
【讨论】:
这似乎是对Subdigger's answer的回应。【参考方案10】:我强烈推荐使用getopt。
如果您需要帮助打印出您的选项,请查看 GetOptionKit。
【讨论】:
你能详细说明你的答案吗?例如,使用示例代码说明如何实际操作?【参考方案11】:只需将其作为参数传递如下:
php test.php one two three
和里面的文件test.php:
<?php
if(isset($argv))
foreach ($argv as $arg)
echo $arg;
echo "\r\n";
?>
【讨论】:
【参考方案12】:有四种主要选择。两者都有自己的怪癖,但在我看来,方法 4 有很多优点。
./script
是一个shell script,以#!/usr/bin/php
开头
方法一:$argv
./script hello wo8844rld
// $argv[0] = "script", $argv[1] = "hello", $argv[2] = "wo8844rld"
⚠️使用$argv,参数顺序很关键。
方法二:getopt()
./script -p7 -e3
// getopt("p::")["p"] = "7", getopt("e::")["e"] = "3"
很难与$argv
结合使用,因为:
⚠️ 选项的解析会在找到第一个非选项时结束, 后面的任何东西都会被丢弃。
⚠️ 字母表中只有 26 个参数。
方法三:Bash Global variable
P9="xptdr" ./script
// getenv("P9") = "xptdr"
// $_SERVER["P9"] = "xptdr"
这些变量可以被在同一个 shell 中运行的其他程序使用。
它们在 shell 关闭时被炸毁,但在 PHP 程序终止时不会。我们可以在文件 ~/.bashrc 中将它们永久设置!
方法四:STDIN管道和stream_get_contents()
一些管道示例:
输入一个字符串:
./script <<< "hello wo8844rld"
// stream_get_contents(STDIN) = "hello wo8844rld"
使用 bash echo 输入字符串:
echo "hello wo8844rld" | ./script
// explode(" ",stream_get_contents(STDIN)) ...
提供文件内容:
./script < ~/folder/Special_params.txt
// explode("\n",stream_get_contents(STDIN)) ...
输入一组值:
./script <<< '["array entry","lol"]'
// var_dump( json_decode(trim(stream_get_contents(STDIN))) );
从文件中提供 JSON 内容:
echo params.json | ./script
// json_decode(stream_get_contents(STDIN)) ...
通过阅读 STDIN,它可能是 work similarly to fread() or fgets()。
Bash-Scripting Guide
【讨论】:
【参考方案13】:if (isset($argv) && is_array($argv))
$param = array();
for ($x=1; $x<sizeof($argv);$x++)
$pattern = '#\/(.+)=(.+)#i';
if (preg_match($pattern, $argv[$x]))
$key = preg_replace($pattern, '$1', $argv[$x]);
$val = preg_replace($pattern, '$2', $argv[$x]);
$_REQUEST[$key] = $val;
$$key = $val;
我把参数放在$_REQUEST中:
$_REQUEST[$key] = $val;
而且也可以直接使用:
$$key = $val
像这样使用它:
myFile.php /key=val
【讨论】:
$$key = $val;
的目的是什么?
直接使用变量而不在数组中提取蜜蜂($_REQUEST)也可以完成这项工作【参考方案14】:
我在 github 上找到了这个 vanilla/garden-cli。我认为它可以满足 PHP CLI 的所有需求。
【讨论】:
【参考方案15】:为了绕过传递给文件的复杂性,听起来你可以使用 sed 将行直接插入到 php 文件中。
sed -i "i (反斜杠)type=daily myfile.php
or as I use it with variables:
sed -i "i (反斜线)$type = "(反斜线)"$daily(反斜线)"(反斜线); $path"/myfile.php"
【讨论】:
以上是关于将变量传递给从命令行运行的 PHP 脚本的主要内容,如果未能解决你的问题,请参考以下文章
如何在命令行下运行PHP脚本(写出两种方式)同时向PHP脚本传递参数?