将变量传递给从命令行运行的 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;  
    

?>

如果在?&gt; 标记之前添加var_dump($b);,您将看到数组$b 包含type =&gt; 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文件时如何传递参数?

$_SERVER[]数组解析

如何在命令行下运行PHP脚本(写出两种方式)同时向PHP脚本传递参数?

如何在命令行界面Windows操作系统中运行php脚本

请写出并说明如何在命令行下运行PHP脚本(写出两种方式)同时向PHP脚本传递参数

在 argparse 中从变量而不是命令行获取值