1

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

3
  • Please show us the code which declares Input-Array. Commented Jul 28, 2013 at 14:49
  • @Smandoli: I have a textfile with the above JSON-content. And I load it with $input = json_decode(file_get_contents("path.json"),true); Commented Jul 28, 2013 at 14:54
  • I can also change the rules so they have another format, but I need to have the same functionality. Commented Jul 28, 2013 at 14:58

2 Answers 2

1

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!
Sign up to request clarification or add additional context in comments.

1 Comment

simple and awesome .. I would have never thought about this. There's only one thing which works differently: When I have a rule to replace a node with an object, this solutions may not delete existing content from the input-array. But in my case it's no problem
0

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.

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.