2016-11-26 8 views
0

私のサイトには人間が読めないURLがあり、私が持っている製品、カテゴリ、ブランドごとにURLを解析する必要があります。このタスクは、多次元配列を走査して変更を加える(ノードを追加する)必要があるコードに私を導きました。ポインタで多次元配列をウォークして変更する

私は、次の配列持っている:私はそれを歩くと、特定の条件でいくつかの変更を行いたい

$a = array(
    'product' => array(
     'oven' => array(
      'url' => 'http', 
      'category' => array(
       'single' => array(
        'url' => 'http2' 
       ) 
      ) 
     ) 
    ) 
); 

をので、私はポインタを維持する必要があります。今

私のコードは次のとおりです。

$data = array('product' => 'oven', 'category' => 'single'); 
$pointer = &$a; 
foreach ($data as $field => $value) { 
    func($field, $value, $pointer); 
    print_r($a); 
    print_r($pointer); 
} 



function func($field, $value, &$pointer) { 
    if (isset($pointer[$field][$value])) { 
     echo 'exists'; 
     // moving into 
     $pointer = &$pointer[$field][$value]; 
    } else { 
     echo 'does not exist'; 
     $pointer[$field][$value] = array('url' => 'someUrl'); 
     // moving into 
     $pointer = &$pointer[$field][$value]; 
    } 
} 

出力はライン「内に移動すると、」動作しないことを示しています。

exists 
Array 
(
    [product] => Array 
     (
      [oven] => Array 
       (
        [url] => http 
        [category] => Array 
         (
          [single] => Array 
           (
            [url] => http2 
           ) 

         ) 

       ) 

     ) 

) 
Array 
(
    [product] => Array 
     (
      [oven] => Array 
       (
        [url] => http 
        [category] => Array 
         (
          [single] => Array 
           (
            [url] => http2 
           ) 

         ) 

       ) 

     ) 

) 
does not exist 
Array 
(
    [product] => Array 
     (
      [oven] => Array 
       (
        [url] => http 
        [category] => Array 
         (
          [single] => Array 
           (
            [url] => http2 
           ) 

         ) 

       ) 

     ) 

    [category] => Array 
     (
      [single] => Array 
       (
        [url] => someUrl 
       ) 

     ) 

) 
Array 
(
    [product] => Array 
     (
      [oven] => Array 
       (
        [url] => http 
        [category] => Array 
         (
          [single] => Array 
           (
            [url] => http2 
           ) 

         ) 

       ) 

     ) 

    [category] => Array 
     (
      [single] => Array 
       (
        [url] => someUrl 
       ) 

     ) 

) 
+0

期待している結果を表示してください。 – jaro1989

答えて

0

Returning Referencesを使用する必要があるため、 'moving into'行は機能しません。この場合は、コピーではなく参照で返信し、通常の割り当てではなく参照バインディングが$pointerであることを示すために、両方の場所で&を使用する必要があります。これは動作します:

$data = array('product' => 'oven', 'category' => 'single'); 
$pointer = &$a; 

foreach ($data as $field => $value) { 
    // returning by reference 
    $pointer = &func($field, $value, $pointer); 
    print_r($a); 
    print_r($pointer); 
} 

function &func($field, $value, &$pointer) { 
    $pointer = &$pointer[$field][$value]; 

    if (isset($pointer)) { 
     echo 'exists'; 
    } else { 
     echo 'does not exist'; 
     $pointer['url'] = 'someUrl'; 
    } 

    // returning reference 
    return $pointer; 
} 

注:PHP、only referencesにはポインタが存在しないことを忘れないでください。

+0

私は働いています。同じことをする方法がありますが、$ポインタを返さない(URLを返す)が、パラメータを使って更新しますか? –

+0

いいえ、残念ながらあなたはそれを行うことはできません。あなたが 'func'の外にURLを取得したいなら、 '$ func($ field、$ value、&$ pointer、&$ url)'に$ urlパラメータを追加し、 'func'本体の中に設定し、 'func'呼び出しの後の' foreach' – krlv

0

$データforeachにするのではなく、再帰を使用することをお勧めします。この参照ビジネスは、コードをデバッグするのが難しくなりがちです。

func($data, $a); 

function func($data, &$a) { // the only place where you need a reference now 
    if (!is_array($a) || !count($data)) return; // nothing more to do 
    list($field, $value) = each($data); // get first data key/value 
    if (!isset($a[$field][$value])) { 
     echo 'does not exist'; 
     $a[$field][$value] = array('url' => 'someUrl'); 
    } 
    // recursive call, without first element of $data, and going deeper in $a 
    func(array_slice($data, 1), $a[$field][$value]); 
}