能否将数组作为命令行参数传递给PHP脚本?

29

我维护着一个PHP库,它负责获取和存储传入的数据(POST、GET、命令行参数等)。我刚刚修复了一个错误,这个错误导致它无法从POST和GET中获取数组变量,我想知道这是否也适用于处理命令行的部分。

你能将一个数组作为命令行参数传递给PHP吗?

9个回答

20

直接来说不行,命令行传递的所有参数都是字符串类型,但你可以使用查询字符串作为一个参数来传递所有带有名称的变量:

直接来说不行,命令行传递的所有参数都是字符串类型,但你可以使用查询字符串作为一个参数来传递所有带有名称的变量:

php myscript.php a[]=1&a[]=2.2&a[b]=c

<?php
parse_str($argv[1]);
var_dump($a);
?>

/*
array(3) {
  [0]=> string(1) "1"
  [1]=> string(3) "2.2"
  ["b"]=>string(1) "c"
}
*/

13

严格来说,不行。但是你可以将一个序列化的数组(使用PHP的serialize()unserialize()或使用json)作为一个参数传递,只要脚本反序列化它。

类似以下代码:

php MyScript.php "{'colors':{'red','blue','yellow'},'fruits':{'apple','pear','banana'}}"

我认为这不是理想的方式,然而,我建议您考虑其他解决问题的方法。


2
它是 unserialize() 而不是 deserialize() - dev-null-dweller
1
unserialize() 不安全,因此不应该被推荐使用。 - Mikhail Batcer

10

就像之前说过的,你可以使用 serialize 来将数组和其他数据传递给命令行。

shell_exec('php myScript.php '.escapeshellarg(serialize($myArray)));

在myScript.php中:

$myArray = unserialize($argv[1]);

7

如果你正在通过代码执行带参数的命令行脚本,则最好对其进行基础编码 -

base64_encode(json_encode($arr));

在发送时进行编码,在其他脚本中接收并解码。
json_decode(base64_decode($argv[1]));

这也将解决没有引号包围键和值的json接收问题。因为没有引号,它被认为是错误的json,你将无法解码它。


4
以下代码块将传递数组作为一组逗号分隔的值来完成此操作:
<?php
  $i_array = explode(',',$argv[1]);
  var_dump($i_array);
?>

输出:

php ./array_play.php 1,2,3

array(3) {
  [0]=>
  string(1) "1"
  [1]=>
  string(1) "2"
  [2]=>
  string(1) "3"
}

1

按照以下步骤,您可以进行如下调用:

phpcl yourscript.php _GET='{ "key1": "val1", "key2": "val2" }'

为了使其正常工作,您需要在调用脚本之前执行代码。我在Linux上使用bash shell,在我的.bashrc文件中设置命令行界面,以使php ini标志auto_prepend_file加载我的命令行引导文件(此文件应该在您的php_include_path中找到):

alias phpcl='php -d auto_prepend_file="system/bootstrap/command_line.php"'

这意味着从命令行调用每个文件都会在运行调用的脚本之前执行此文件。auto_prepend_file是引导系统的好方法,我在我的标准php.ini中使用它来在系统级别设置最终的异常和错误处理程序。设置此命令行auto_prepend_file会覆盖我的正常设置,我选择仅处理命令行参数,以便我可以设置$_GET或$_POST。以下是我预先添加的文件:
<?php
// Parse the variables given to a command line script as Query Strings of JSON.
// Variables can be passed as separate arguments or as part of a query string:
//    _GET='{ "key1": "val1", "key2": "val2" }' foo='"bar"'
// OR
//    _GET='{ "key1": "val1", "key2": "val2" }'\&foo='"bar"' 
if ($argc > 1)
{
   $parsedArgs = array(); 

   for ($i = 1; $i < $argc; $i++)
   {
      parse_str($argv[$i], $parsedArgs[$i]);
   }

   foreach ($parsedArgs as $arg)
   {
      foreach ($arg as $key => $val)
      {
         // Set the global variable of name $key to the json decoded value.
         $$key = json_decode($val, true);
      }
   }

   unset($parsedArgs);
}
?>

它循环遍历所有传递的参数,并使用变量变量(注意$$)设置全局变量。手册页面确实说变量变量不能与超级全局变量一起使用,但我发现它似乎可以与$_GET一起使用(我猜POST也可以)。我选择将值作为JSON传递。json_decode的返回值在错误时将为NULL,如果需要,您应该对解码进行错误检查。


1
"Sort of."
如果您传递类似以下内容的东西:
$php script.php --opt1={'element1':'value1','element2':'value2'}

你会在opt1参数中得到这个:

Array(
 [0] => 'element1:value1'
 [1] => 'element2:value2'
)

所以你可以使用以下代码片段进行转换:


foreach($opt1 as $element){
    $element = explode(':', $element);
    $real_opt1[$element[0]] = $element[1];
}

这将把它转换成这样:
Array(
 [element1] => 'value1'
 [element2] => 'value2'
)

2
如果一个值恰好包含冒号(:),那么这种方法就无法很好地处理。 - Andrew Ensley

1

你需要想出一种将数组编码为字符串的方法。然后,你可以将此字符串作为命令行参数传递给 PHP CLI,并稍后解码该字符串。


0

所以如果一个CLI是这样的

php path\to\script.php param1=no+array param2[]=is+array param2[]=of+two

那么读取这个的函数可以是:

function getArguments($args){
    unset($args[0]); //remove the path to script variable
    $string = implode('&',$args);
    parse_str($string, $params);
    return $params;
}

这将会给你

Array
(
    [param1] => no array
    [param2] => Array
             (
                 [0] => is array
                 [1] => of two
             )
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接