【问题标题】:Pass a variable to a PHP script running from the command line将变量传递给从命令行运行的 PHP 脚本
【发布时间】:2011-10-13 04:37:50
【问题描述】:

我有一个需要从命令行运行的 PHP 文件(通过crontab)。我需要将type=daily 传递给文件,但我不知道如何。我试过了:

php myfile.php?type=daily

但是返回了这个错误:

无法打开输入文件:myfile.php?type=daily

我能做什么?

【问题讨论】:

    标签: php command-line command-line-arguments


    【解决方案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

      【讨论】:

      • 虽然这可能会回答问题,但请考虑添加有关此解决方案如何解决问题的详细信息。请参考stackoverflow.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"
        }
        

        这个总是会执行,因为它会传递一个或两个参数。

        【讨论】:

        【解决方案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"

              【讨论】:

                猜你喜欢
                • 2013-12-07
                • 1970-01-01
                • 2018-01-11
                • 2019-08-24
                • 1970-01-01
                • 1970-01-01
                • 2013-05-01
                • 1970-01-01
                相关资源
                最近更新 更多