0

Original Title: How can I dynamically enclose attributes in variable before actual object call

Generic Question

How can I create $target in a way that it can be correctly var_dumped?

    $type = 'lib';
    $target = 'test->test2';

    var_dump($GLOBALS[$this->context]->$type->test->test2);//returns object(test\test2)#15 (0) { } 

    var_dump($GLOBALS[$this->context]->$type->{$target}); //returns NULL ( Undefined property: stdClass::$test->test2 )

More Examples

this (below) works like a charm

   $target = 'test';
   $type = new \stdClass();
   $type->test = new \stdClass();
   $type->test->test2 = 5;
   var_dump($type->$target); // Returns object(stdClass)#24 (1) { ["test2"]=> int(5) } 

this (below) does not :

   $target = 'test->test2';
   $type = new \stdClass();
   $type->test = new \stdClass();
   $type->test->test2 = 5;
   var_dump($type->$target);// Returns NULL (Notice: Undefined property: stdClass::$test->test2)

Real Case :

I want to unset $GLOBALS[$this->context]->$type->test->test2

My first though :

public function unSys($type, $thing) {

//$type = 'lib';
//$thing = 'test/test2';

$parts = explode('/',$thing);
$final = implode('->',$parts);
unset($GLOBALS[$this->context]->$type->{$final});

}

What I've tried after that :

...

$parts = explode('/',$thing);
$target = $GLOBALS[$this->context]->$type;

        foreach ($parts as $value) {
            $target = $target->$value;
        }

unset($target);
var_dump($GLOBALS[$this->context]->$type->test->test2);//still exist

...

I also tried passing by reference without luck :

...
$target = &$GLOBALS[$this->context]->$type;
...
14
  • why not: var_dump($target) ? Commented Apr 27, 2015 at 16:09
  • hum... ok wait, It may need some contextual, sorry Commented Apr 27, 2015 at 16:11
  • call_user_func() is your friend Commented Apr 27, 2015 at 16:21
  • why not just unset in your loop? Commented Apr 27, 2015 at 16:22
  • providing some more info about the data sent in as $thing and what the global value is would be helpful as well. Commented Apr 27, 2015 at 16:22

1 Answer 1

1

Guillaume,

I think you're wanting to use an array of property names that represent a chain of nested objects to remove the last nested object property.

See if this code makes sense and solves your problem.

<?PHP

$GLOBALS['tmp'] = (object)array( 'lib' => (object)array( 'test' => (object)array( 'test2' => (object)array()) ) );
var_dump( $GLOBALS['tmp'] );

$context = 'tmp';

$type = 'lib';
$thing = 'test/test2';

$parts = explode('/',$thing);
$target = $GLOBALS[$context]->$type;
var_dump( $target );
var_dump( $parts );
$itemToUnset = array_pop( $parts );

foreach ($parts as &$value) {
    $target =& $target->$value;
}

unset( $target->{$itemToUnset} );
var_dump( $GLOBALS['tmp'] );

// test 2 is not set
var_dump( $GLOBALS['tmp']->lib->test->test2 );

The output looks like this:

object(stdClass)[4]
public 'lib' => 
    object(stdClass)[3]
        public 'test' => 
          object(stdClass)[2]
            public 'test2' => 
              object(stdClass)[1]
                ...
object(stdClass)[3]
public 'test' => 
    object(stdClass)[2]
        public 'test2' => 
        object(stdClass)[1]

array (size=2)
0 => string 'test' (length=4)
1 => string 'test2' (length=5)

object(stdClass)[4]
public 'lib' => 
    object(stdClass)[3]
        public 'test' => &
        object(stdClass)[2]

Notice: Undefined property: stdClass::$test2
Sign up to request clarification or add additional context in comments.

3 Comments

Tim, thank you, it answer perfectly my problem. Iwas focusin (in third try) to give & to Global, but I should have give it to $target. My fault, shows I still don't have a clear view of passing by reference. But it makes totally sense. Just to be sure : "$target = & $target->$value" and "$target = &$target->$value" are the same hu? (I talk about the position of &). Int the code it doesnt make any difference, but I would like to be sure. Ty again!
References: objects are automatically passed around as references. I chose to explicitly force a reference assignment by using the ampersand. However I think the real solution here was the array_pop used to remove the name of the class property you're wanting to remove. In fact, removing & from the foreach loop reveals that everything still works.
(continued) Removing the & from the foreach yields a slightly different var_dump output that needs further investigation - you will notice that the var_dump output shows public 'test' => & I'm not sure if this will cause problems or not - I would code this without the reference in the foreach if I were you.

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.