1

I can't figure out how do this at all. My first attempt involved using references and calling unset on a reference simply unlinks the reference. I tried recursion but couldn't get it to work, I then tried array_walk and array_filter without success. Here is a simple example that demonstrates what I am trying to do.

<?
class Sample {
    //Please note this can have a completely variable amount of vars/dimensions
    $data = array("system" => array("value1","value2"), "session" => array("value1"));

    public function erase($value){
         //Here I am suppose to somehow delete that exists in $this->data
    }
    public function display(){
         print_r($this->data);
    }
 }


 $Sample = new Sample();
 $Sample->erase(array("system","value1"));
 //I am extremely flexible on the format of the erase parameter ($value)
 $Sample->display();

 should output with the variable unset($this->data["system"]["value1"]) :

 array("system" => array("value2"), "session" => array("value1")

Ohgodwhy helped by creating a eval.in with a slighly modified example

Thank you for your help

2 Answers 2

1

I've made this function and work pretty great.

function erase(array &$arr, array $children)
{
    $ref = &$arr;
    foreach ($children as $child)
        if (is_array($ref) && array_key_exists($child, $ref)) {
            $toUnset = &$ref;
            $ref = &$ref[$child];
        } else
            throw new Exception('Path does\'nt exist');
    unset($toUnset[end($children)]);
}

Example 1:

Here's an example of how you would unset $arr['session']['session3']['nestedSession2']

$arr = [
    "system" => [
        "system1" => "value1",
        "system2" => "value2"
    ],
    "session" => [
        "session1" => "value3",
        "session2" => "value4",
        "session3" => [
            "nestedSession1" => "value5",
            "nestedSession2" => "value6",
        ],
    ],
];

print_r($arr);
erase($arr, array('session', 'session3', 'nestedSession2'));
print_r($arr);

Example 2:

It can even unset a whole nested array, here's how you would do it (handling errors):

print_r($arr);
try {
    erase($arr, array('session', 'session3'));
}  catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}
print_r($arr);

Example 3:

It also work with non-assiociative array:

$arr = array('fruit1', 'fruit2', 'fruit3');
print_r($arr);
try {
    erase($arr, array(0));
}  catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}
print_r($arr);

Example 4:

In case of error:

$arr = array('fruit1', 'fruit2', 'fruit3');
print_r($arr);
try {
    erase($arr, array('pathThatDoesNotExit'));
}  catch (Exception $e) {
    // do what you got to do here in case of error (if the path you gave doesn't exist)!
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}
print_r($arr);
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks so much! It was my understanding (and I even coded an example that provided it) that doing an unset on a reference causes it to simply unlink the reference (not delete the item). How does your code get around this?
@hendr1x By passing by reference you can, inside the function, unset an element of an array. However unset($theWholeArray) inside the function won't do work.
1

If you'll always be passing in the key name of the array that contains the value, followed by the value, we can use array_search to perform this.

if(false !== $key = array_search($value[1], $this->data[$value[0]])):
    unset($this->data[$value[0]][$key]);
endif;

Here's your eval.in example

3 Comments

Thank you for your help. Unfortunately I need the erase method to be flexible to handle any number of dimensions/variables and values (including associative arrays) ( eval.in/197702 )
@hendr1x Okay, then how are you going to pass along arguments? Do you just want to search all arrays for a value then get it's key and unset it? Do you want to pass in the subarray? etc..
I am really flexible on how the system works. Adam posted work code that took an array("level1","level2","level3"). If you want to discuss I'll keep checking. Thanks for your help.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.