2013-07-28 3 views
1

У меня есть многомерный массив в php, который я хочу манипулировать в соответствии с некоторыми правилами.Изменение содержимого многомерного массива в php?

ввода-массив: (Variable распечатываются в формате JSON)

[ 
    { 
     "meta":{ 
       "title": "Adressdata", 
       "name": "adress" 
     },  
     "data":{ 
      "desc":{ "tooltip": "text", 
         "maxlength": "100" 
       }, 
      "line1":{ "tooltip": "Recipient", 
         "maxlength": "40" 
       } 
    } 
] 

Правило:

{ 
    "0>meta>title": "Companyaddress", 
    "0>data>desc": { 
     "tooltip": "Another Text", 
     "maxLength": "150" 
    } 
} 

(Есть 2 правила, индекс объясняет, какое поле из входнога -array необходимо изменить, а значение содержит данные, которые нужно вставить вместо этого. Обратите внимание, что второе правило хочет вставить объект)

Проблема:

Я хочу изменить содержимое входного массива в соответствии с правилами, но я изо всех сил, делая это.

Вот PHP-код у меня уже есть:

<?php 
    $input = json_decode(file_get_contents("inputData.json"),true); 
    $rules = json_decode(file_get_contents("rules.json"),true); 

    foreach ($rules as $target => $replacement) {  
     //rule: "0>meta>title": "newTitle" 

     $node = $input; 
     foreach (explode(">",$target) as $index) { 
      $node = $node[$index]; 
     } 

     $node = $replacement; //replace doesn't work  
    } 

    echo "Result-Array: "; 
    print_r($input); 
?> 

Все работает, в кроме того, что я не могу изменить значения. Почему? Поскольку каждый раз, когда я устанавливаю переменную $ node-Variable, я создаю новую переменную. И я только изменяю содержимое $ node, но не содержимое $ input.

Так что я пытался использовать ссылки - который не работает либо: Когда я изменяю 2 $ узловые-линии с этим кодом:

$node = &$input; 
[...] 
$node = &$node[$keys[$i]]; //go to child-node 

Но это не работает, потому что вторая строка, где я просто хочу перейти к дочернему узлу, изменяет родительский элемент (потому что $ node является ссылкой).

Я понятия не имею, если есть трюк, чтобы сделать это, я надеюсь, что кто-то может помочь мне

+0

Пожалуйста, покажите нам код, который объявляет 'Input-Array'. – Smandoli

+0

@Smandoli: У меня есть текстовый файл с указанным выше JSON-содержимым. И я загружаю его с помощью '$ input = json_decode (file_get_contents (" path.json "), true);' – maja

+0

Я также могу изменить правила, чтобы у них был другой формат, но мне нужно иметь ту же функциональность. – maja

ответ

1

Хорошо, вот какое-то решение, но вы должны изменить $rules структуру, она должна быть такой же, как $input:

$input = json_decode('[{"meta":{"title": "Adressdata","name": "adress"},"data":{"desc":{"tooltip":"text","maxlength":"100"},"line1":{"tooltip":"Recipient","maxlength":"40"}}}]',true); 
$rules = json_decode('[{"meta":{"title": "Companyaddress"},"data":{"desc":{"tooltip":"Another Text","maxlength":"150"}}}]',true); 

// if you print both arrays you will see that they have the similar structure 
// but $rules consists only of items that you need to change. 
// next: 
echo'<pre>',print_r(array_replace_recursive($input, $rules)),'</pre>'; 

// BINGO! 
+0

простой и удивительный .. Я бы никогда об этом не думал. Есть только одна вещь, которая работает по-другому: когда у меня есть правило для замены узла объектом, эти решения могут не удалять существующий контент из входного массива. Но в моем случае это не проблема – maja

0

Ok, после некоторых неприятных часов, я, наконец, нашел способ для достижения этой цели.

Это функция я писал:

/** 
* Manipulates an array according to the given rules 
*/ 
function manipulateData($input, $manipulations){ 

    foreach ($manipulations as $target => $replacement) { //for each rule 
     $tmpRefNum = 0;        //Variable-Nameprefix for the reference (don't generate random names) 

     $node = "node".(++$tmpRefNum);    //"node1" 
     $$node = &$input;       //$node1 --> $input 

     foreach (explode(">",$target) as $index) { //for each child in the rule   
      $parent = &$$node;      //We search for a child. So the old node becomes a parent 

      if(!isset($parent[$index])){    //Does the child exist?  no --> create missing child    
       $parent[$index] = "";    //give birth! (value will be set later)     
      } 

      $node = "node".(++$tmpRefNum);   //Generate a new reference-Name: "node2", "node3", ... 
      $$node = &$parent[$index];    //Point to child   
     } 

     $$node = $replacement;      //Change the child-content 

     //Unset all generated references (just to not spam the variables) 
     /* */ for($i=1;$i<=$tmpRefNum;$i++){ 
     /* */  $node = "node".$i; 
     /* */  unset($$node); 
     /* */ } 
     /* */ 
    } 
    return $input; 
} 

Описание:

Решение, что я просто сгенерировать новую переменную/ссылку для каждого дочернего узла-я нахожу. Для этого мне нужен $$ - Синтаксис, предоставляемый php.

Это немного грязно, потому что у меня переменная фабрика, поэтому, если кто-то найдет лучшее решение, это будет потрясающе.

Было бы здорово, если бы я получил некоторую обратную связь, если это хорошее решение или нет.