Is it possible to pass an array as a command line

2019-02-08 04:40发布

问题:

I'm maintaining a PHP library that is responsible for fetching and storing incoming data (POST, GET, command line arguments, etc). I've just fixed a bug that would not allow it to fetch array variables from POST and GET and I'm wondering whether this is also applicable to the part that deals with the command line.

Can you pass an array as a command line argument to PHP?

回答1:

Directly not, all arguments passed in command line are strings, but you can use query string as one argument to pass all variables with their names:

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"
}
*/


回答2:

Strictly speaking, no. However you could pass a serialized (either using PHP's serialize() and unserialize() or using json) array as an argument, so long as the script deserializes it.

something like

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

I dont think this is ideal however, I'd suggest you think of a different way of tackling whatever problem you're trying to address.



回答3:

As it was said you can use serialize to pass arrays and other data to command line.

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

And in myScript.php:

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


回答4:

The following code block will do it passing the array as a set of comma separated values:

<?php
  $i_array = explode(',',$argv[1]);
  var_dump($i_array);
?>

OUTPUT:

php ./array_play.php 1,2,3

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


回答5:

In case, if you are executing command line script with arguments through code then the best thing is to base encode it -

base64_encode(json_encode($arr));

while sending and decode it while receiving in other script.

json_decode(base64_decode($argv[1]));

That will also solve the issue of json receiving without quotes around the keys and values. Because without quotes, it is considered to be as bad json and you will not be able to decode that.



回答6:

You need to figure out some way of encoding your array as a string. Then you can pass this string to PHP CLI as a command line argument and later decode that string.



回答7:

After following the set of instructions below you can make a call like this:

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

To get this working you need code to execute before the script being called. I use a bash shell on linux and in my .bashrc file I set the command line interface to make the php ini flag auto_prepend_file load my command line bootstrap file (this file should be found somewhere in your php_include_path):

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

This means that each call from the command line will execute this file before running the script that you call. auto_prepend_file is a great way to bootstrap your system, I use it in my standard php.ini to set my final exception and error handlers at a system level. Setting this command line auto_prepend_file overrides my normal setting and I choose to just handle command line arguments so that I can set $_GET or $_POST. Here is the file I prepend:

<?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);
}
?>

It loops through all arguments passed and sets global variables using variable variables (note the $$). The manual page does say that variable variables doesn't work with superglobals, but it seems to work for me with $_GET (I'm guessing it works with POST too). I choose to pass the values in as JSON. The return value of json_decode will be NULL on error, you should do error checking on the decode if you need it.



回答8:

So if a CLI is as such

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

Then the function thats reads this can be

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

This would give you

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


回答9:

Sort of.

If you pass something like this:

$php script.php --opt1={'element1':'value1','element2':'value2'}

You get this in the opt1 argument:

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

so you can convert that using this snippet:

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

which turns it into this:

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