2

I'm trying to write some code that will generate a php file with an array, like this.

However, in order to create a correct configuration file I need to be able to leave expressions 'as is' within the array. This is because the file will be used by many users and the expressions evaluate based on environmental variables, etc. the user has set up.

So, say we have this key/value in the array I eventually want to output to the file:

[
    ...
    'connection' => $isFork ? $sourceArray['connection'] : config('database.default'),
    ...
]

When this array is eventually written out to a php file (right now using var_export and file_put_contents) I will see

'connection' => config('database.default')

become

'connection' => 'default_connection',

because the expression is evaluated. What I need is a way to prevent expressions as values in the array from being evaluated but also ensuring

'connection' => $isFork ? $sourceArray['connection']

does evaluate to

'connection' => 'my_connection'

Is there any way to do this?

EDIT: I basically want to do this but in reverse and with expressions.

3
  • use quote if you want prevent from evaluated ? Maybe I'm out of the subject ? 'connection' => $isFork ? $sourceArray['connection'] : 'config('database.default')', Commented Jul 15, 2015 at 14:23
  • ho.. ok you want to output that without evaluate.. why don't use like a string? $string = '\'connection\' => $isFork ? $sourceArray[\'connection\'] : config(\'database.default\')'; Commented Jul 15, 2015 at 14:29
  • @Jean-philippeEmond : The output does not go to the browser, I am trying to generate a config.php file. Wrapping the value in quotes gives me 'connection' => 'config(\'database.default\')' in the generated file when what I want is 'connection' => config('database.default') Commented Jul 15, 2015 at 14:42

3 Answers 3

2

If I understand you correctly, your solution is to have a string representation of your array so the statements are not evaluated. I would serialize that array and put that string into the file. Tell your peeps to unserialize it right after they receive it. Better yet, json_encode your array which is going to give you a json string. You can put that in via put_file_contents and tell your peeps to json_decode the contents. They can use it as such json_decode($content, TRUE) which will give them back the associative array.

Update

So you want to write straight up PHP. I see that you have connection stuff in your array so I am thinking it is safe to think it is some sort of a configuration file that includes connection settings etc.

// filename should have the .ini at the end 
function writeConfig( $filename, $yourArray ) {
    $fh = fopen($filename, "w");
    // making sure its available
    if (!is_resource($fh)) {
        return false;
    }
    // start dumping you array to the file 
    foreach ($yourArray as $key => $value) {
        fwrite($fh, sprintf("%s = %s\n", $key, $value));
    }
    fclose($fh); // close file

    return true;
}

when you want to read it

function readConfigFile( $fileThatMadeAbove ) {
    return parse_ini_file($fileThatYouMadeAbove, false, INI_SCANNER_NORMAL);
}

Since it is config info, it may be better to use the ini in php.

If you want to try plain simple solution

$fp=fopen('filename.php','w');
fwrite($fp, "$yourArray");
fclose($fp);

I honestly do not know if you can do "$yourArray" or not and I do not have a place to test it. You most likely need to do a print_r($yourArray) because it is a string that you write to a file which is why I made my recommendation above.

I am out of ideas. Good luck (:

Sign up to request clarification or add additional context in comments.

6 Comments

This is too many steps for what I'm trying to accomplish. The goal is to allow the user to execute a command from the cli, take an existing config file as input, and output a new config file (still as php code).
Write your key value array to a file file_put_contents(json_encode($array)) and retrieve it via file_get_contents(json_decode($fileName)) I failed to see the too many steps so I am out ... Good luck
so.. read the file with fopen. put each time in an array.. after that, fopen for write new file with the array.
@Jean-philippeEmond and ODelibalta , once the file is generated I am not in control of it. This is an exercise in creating a valid, readable php file with a normal array that be edited and used by the user post-generation however they want. I can't restrict them to having to decode json or unserializing things. It needs to be usable php code.
I tell you about generate your php. You need to generate, so when you try to generate it, just put all information into an array.. (each line) with single quote and write your file using write method.. using and strip your slashes and add \n or PHP_EOL at the end of each line you want a a new line and just. your config argument is already compiled when you insert into the array. So, escape it, write file with remove \ and add PHP_EOL or \n after string insert Check This to see what I tell you
|
1

This isn't possible using var_export. The best way I can see to do this is to create a string of the output and use file_put_contents to output this to a file.

This could be achieved by replicating the array structure, e.g.

$arr_str = "[\n";
         . "\t'simple_annotations' => false,\n"
         . "];";

Or by creating a helper function to use instead of var_export. Something like this:

function var_str($var, $level = 0){
    if(is_array($var)) return arr_str($var, $level+1);
    elseif(is_string($var)) return '\''.$var.'\'';
    elseif(is_numeric($var)) return $var;
    elseif(is_null($var)) return 'null';
    elseif(is_bool($var)) return ($var ? 'true' : 'false');
}

function arr_str($arr, $level){
    $str = "[\n";
    foreach($arr as $k => $e){
        $str .= str_repeat("\t", $level);
        $str .= "'".$k."' => ".var_str($e, $level).",\n";
    }
    return $str.str_repeat("\t", $level-1).']';
}

print var_str($my_array);

4 Comments

How can I generate a string of the raw code representation of the array?
the same way you would create any string (and make sure you escape things that php would try to evaluate): $string = "\$array = array('connection' => 'default_connection');";
The array needs to be built, it's not a simple thing I can hardcode one string for. Do I really need to write a string builder for each section of the array? There's no easier way?
I basically need this, but reversed and with expression stackoverflow.com/questions/11267434/…
0

After searching for a few hours I came to the conclusion the only way to take full control over what I wanted to do was to use a templating engine.

The project this is for uses Laravel so I used Blade but any engine would work (I initially tried this with Twig).

I wrote out each section of my config as if it was a regular php array and then used Blade bracketing to encompass the logic needed to find the right value for each key. If the value was not an expression I evaluated the code, and if it was I wrote the expression into a string.

I ended up with this:

//example.blade.php

[
    'meta' => '{{{ $isFork ? $data['metadata']['driver'] : 'annotations' }}}',
    'connection' => {{{ $isFork ? '\''.$data['connection'].'\'' : 'config("database.default")'  }}},
    'paths' => {{ var_export(ArrayUtil::get($data['metadata']['paths'], $data['metadata']), true) }},
    'repository' => '{{{ ArrayUtil::get($data['repository'], EntityRepository::class) }}}',
    'proxies' => [
        'namespace' => {{{ isset($data['proxy']['namespace']) ? '\'' . $data['proxy']['namespace'] .'\'' : 'false' }}},
        'path'          => '{{{ ArrayUtil::get($data['proxy']['directory'], storage_path('proxies')) }}}',
        'auto_generate' => {{{ ArrayUtil::get($data['proxy']['auto_generate'], env('DOCTRINE_PROXY_AUTOGENERATE', 'false')) }}}
    ],
    'events'     => [
        'listeners'   => [],
        'subscribers' => []
    ],
    'filters' => []
]

and the output:

[
            'meta' => 'yaml',
            'connection' => config('database.default'),
            'paths' => array(
                0 => '/proj/app/Models/mappings',
            ),
            'repository' => 'Doctrine\ORM\EntityRepository',
            'proxies' => [
                'namespace' => false,
                'path' => '/proj/storage/proxies',
                'auto_generate' => false
            ],
            'events' => [
                'listeners' => [],
                'subscribers' => []
            ],
            'filters' => []
]

You can see that where I potentially needed to expand an array I used var_export. Other than it was pretty straight forward.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.