Reputation: 18054
I have a multidimensional array in php, which I want to manipulate according to some rules.
Input-Array: (Variable printed as JSON)
[
{
"meta":{
"title": "Adressdata",
"name": "adress"
},
"data":{
"desc":{ "tooltip": "text",
"maxlength": "100"
},
"line1":{ "tooltip": "Recipient",
"maxlength": "40"
}
}
]
Rules:
{
"0>meta>title": "Companyaddress",
"0>data>desc": {
"tooltip": "Another Text",
"maxLength": "150"
}
}
(There are 2 rules, the index explains which field from the input-array has to be changed, and the value contains the data to be inserted instead. Note that the second rule wants to insert an object)
Problem:
I want to change the content of the input-array according to the rules, but I struggle in doing that.
Here's the php-Code I already have:
<?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);
?>
Everything works, in except that I can't change the values. Why? Because everytime I set $node-Variable, I create a new Variable. And I only change the content of $node, but not the content of $input.
So I tried to use references - which doesn't work either: When I change the 2 $node-Lines to this code:
$node = &$input;
[...]
$node = &$node[$keys[$i]]; //go to child-node
But this doesn't work, because the second line, where I just want to navigate to a child-node, changes the parent-element (because $node is a reference).
I have no idea if there's a trick to do that, I hope someone can help me
Upvotes: 1
Views: 215
Reputation: 54831
Okay, here's some decision, but you should change $rules
structure, it should be the same as $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!
Upvotes: 1
Reputation: 18054
Ok, after some frustrating hours, I finally found a way to achieve this.
This is the function I wrote:
/**
* 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;
}
Description:
The solution is, that I just generate a new variable/reference for each child-node I find. In order to do this, I need the $$-Syntax provided by php.
It's a bit dirty, because I have a variable-factory, so if someone finds a better solution it would be awesome.
It would be great, if I would get some feedback if this is a good solution or not.
Upvotes: 0