Search code examples
phpbashevalassociative-arraygetopt

Pass BASH associative arrays to PHP script


Is it possible to pass BASH associative arrays as argv to PHP scripts?

I have a bash script, that collects some variables to a bash associative array like this. After that, I need to send it to PHP script:

typeset -A DATA
DATA[foo]=$(some_bash_function "param1" "param2")
DATA[bar]=$(some_other_bash_function)

php script.php --data ${DATA[@]}

From PHP script, i need to access the array in following manner:

<?php

    $vars = getopt("",array(
        "data:"
    ));

    $data = $vars['data'];

    foreach ($data as $k=>$v) {
          echo "$k is $v";
    }

?>

What I've tried

Weird syntax around the --data parameter follows advice from a great post about bash arrays from Norbert Kéri how to force passed parameter as an array:

You have no way of signaling to the function that you are passing an array. You get N positional parameters, with no information about the datatypes of each.

However this sollution still does not work for associative arrays - only values are passed to the function. Norbert Kéri made a follow up article about that, however its eval based solution does not work for me, as I need to pass the actual array as a parameter.

Is the thing I'm trying to achieve impossible or is there some way? Thank you!

Update: What I am trying to accomplish

I have a few PHP configuration files of following structure:

<?php
return array(
    'option1' => 'foo',
    'option2' => 'bar'
)

My bash script collects data from user input (through bash read function) and stores them into bash associative array. This array should be later passed as an argument to PHP script.

php script.php --file "config/config.php" --data $BASH_ASSOC_ARRAY

So instead of complicated seds functions etc. I can do simple:

<?php

    $bash_input = getopt('',array('file:,data:'));
    $data = $bash_input['data'];

    $config = require($config_file);
    $config['option1'] = $data['option1'];
    $config['option2'] = $data['option2'];

    // or

    foreach ($data as $k=>$v) {
         $config[$k] = $v;
    }

    // print to config file
    file_put_contents($file, "<?php \n \n return ".var_export($config,true).";");
?>

This is used for configuring Laravel config files


Solution

  • Different Approach to @will's

    Your bash script:

    typeset -A DATA
    foo=$(some_bash_function "param1" "param2")
    bar=$(some_other_bash_function)
    
    php script.php "{'data': '$foo', 'data2': '$bar'}"
    

    PHP Script

    <?php
    
        $vars = json_decode($argv[1]);
    
        $data = $vars['data'];
    
        foreach ($data as $k=>$v) {
              echo "$k is $v";
        }
    
    ?>
    

    EDIT (better approach) Credit to @will

    typeset -A DATA
    DATA[foo]=$(some_bash_function "param1" "param2")
    DATA[bar]=$(some_other_bash_function)
    
    php script.php echo -n "{"; for key in ${!DATA[@]}; do echo - "'$key'":"'${DATA[$key]}'", | sed 's/ /,/g' ; done; echo -n "}"