47739


諸先輩方のお知恵を拝借したく、ここに質問いたします。

[code]

    $keys = "['a']['b']['c']";
    $value = 'can be anything';
    
[/code]

という二つの値がある時に、以下の代入をしたいです。

[code]

    $hoge['a']['b']['c'] = 'can be anything';
    
[/code]

eval(),var_export()を使えば、以下の形で実現できますが、eval()をできれば使わない方法をとれたらと思っています。

[code]

    eval( '$hoge' . $keys . '=' . var_export( $value, true ) . ';' );
    
[/code]

三日間考え続けましたが上記の方法しか考え出せす。。。

御指南の程、何卒よろしくお願いいたします。


CC BY-SA 4.0
2018-08-22T14:23:41.870
47734
2018-08-22T16:45:52.207
2018-08-22T14:28:47.813
29820
29820
question
php array
(PHPで) keyの連なりを表す文字列から多次元連想配列を作成し、(evalを使わずに) 値を代入したい


以下の処理でできますけれど、内部の処理は `eval() + var_export()` と同一です(include
しているだけですので)。また、php.ini で `allow_url_include = On` を設定する必要があります。まぁ、参考までにどうぞ。

[code]

    <?php
    
    $keys = "['a']['b']['c']";
    $value = 'can be anything';
    
    $code = <<<EOS
    <?php
    \$hoge$keys = '$value';
    EOS;
    
    include 'data://text/plain,' . urlencode($code);
    
    print($hoge['a']['b']['c'] . "\n");
    
    ?>
    
[/code]


CC BY-SA 4.0
2018-08-22T16:07:25.780
47736
2018-08-22T16:07:25.780
47734
answer


ちょっとした言語のインタプリタをPHPで書いている形になるので、簡単ではありませんが、エラー処理を端折ったりするとこんな感じで出来そうです。詳細な挙動は`eval`を使った時と少々異なりますが。

[code]

    <?php
    $keys = "['a']['b']['c']";
    $value = 'can be anything';
    
    //まずは全ての実際のキーを配列として取り出す(エスケープとかその辺は無視)
    preg_match_all('/\\[\'([^\']+)\'\\]/', $keys, $matches, PREG_PATTERN_ORDER);
    $keyArray = $matches[1];
    print_r($keyArray);
    /*
    Array
    (
        [0] => a
        [1] => b
        [2] => c
    )
    */
    //$hoge が空とは限らないので、一旦ネストした連想配列を作成して…
    $tmpArr = $value;
    foreach( array_reverse($keyArray) as $key ) {
        $tmpArr = [$key => $tmpArr];
    }
    //$hoge が空だったり、配列以外の値を持っていたりすると困るので前処理
    if( !is_array($hoge) ) $hoge = [];
    //… $hoge にマージする
    $hoge = array_merge_recursive($hoge, $tmpArr);
    print_r($hoge);
    /*
    Array
    (
        [a] => Array
            (
                [b] => Array
                    (
                        [c] => can be anything
                    )
    
            )
    
    )
    */
    
[/code]


CC BY-SA 4.0
2018-08-22T16:45:52.207
47739
2018-08-22T16:45:52.207
13972
47734
answer