183

How do I get a property in a PHP based on a string? I'll call it magic. So what is magic?

$obj->Name = 'something';
$get = $obj->Name;

would be like...

magic($obj, 'Name', 'something');
$get = magic($obj, 'Name');
laurent
  • 88,262
  • 77
  • 290
  • 428
Daniel A. White
  • 187,200
  • 47
  • 362
  • 445

12 Answers12

289

Like this

<?php

$prop = 'Name';

echo $obj->$prop;

Or, if you have control over the class, implement the ArrayAccess interface and just do this

echo $obj['Name'];
GSee
  • 48,880
  • 13
  • 125
  • 145
Peter Bailey
  • 105,256
  • 31
  • 182
  • 206
  • Any benefit of using the second option over the first? – Clox May 12 '15 at 19:23
  • 2
    @Clox Generally, the main benefit of using the latter if if you have an existing system that consumes a variable in an array-like way, but you want the flexibility and power offered by objects. If a class implements `ArrayAccess`, `Countable`, and one of the iterator interfaces, it's mostly indistinguishable from a normal `array()` – Peter Bailey May 13 '15 at 13:06
199

If you want to access the property without creating an intermediate variable, use the {} notation:

$something = $object->{'something'};

That also allows you to build the property name in a loop for example:

for ($i = 0; $i < 5; $i++) {
    $something = $object->{'something' . $i};
    // ...
}
laurent
  • 88,262
  • 77
  • 290
  • 428
  • 11
    This is the only way if you want to access an array value `$this->{$property}[$name]`, otherwise `$this->$property[$name]` will throw an error – goyote Dec 08 '12 at 04:05
  • 1
    @goyote: It depends values and PHP version. In 5.3 it triggers an E_NOTICE because the property cannot be found, rather than an "error", since it is still valid PHP syntax. It's possible that `$this->$property[$name]` might actually succeed, although this is likely to be a bug. `$name` is silently cast to an integer. In the case of a non-numeric string this is `0`. Then this string _index_ of the value of `$property` is used as the property name. If `$property` holds the value "abc", then this will refer to the property `$this->a` (index 0). If there is such a property then this will succeed. – MrWhite Oct 26 '13 at 00:13
  • 1
    @goyote: However, in PHP 5.4, a non-numeric string index is not silently cast to the integer 0, it will trigger an E_WARNING. – MrWhite Oct 26 '13 at 00:14
17

What you're asking about is called Variable Variables. All you need to do is store your string in a variable and access it like so:

$Class = 'MyCustomClass';
$Property = 'Name';
$List = array('Name');

$Object = new $Class();

// All of these will echo the same property
echo $Object->$Property;  // Evaluates to $Object->Name
echo $Object->{$List[0]}; // Use if your variable is in an array
matpie
  • 17,033
  • 9
  • 61
  • 82
9

Something like this? Haven't tested it but should work fine.

function magic($obj, $var, $value = NULL)
{
    if($value == NULL)
    {
        return $obj->$var;
    }
    else
    {
        $obj->$var = $value;
    }
}
Ólafur Waage
  • 68,817
  • 22
  • 142
  • 198
6

Just store the property name in a variable, and use the variable to access the property. Like this:

$name = 'Name';

$obj->$name = 'something';
$get = $obj->$name;
Jon Benedicto
  • 10,492
  • 3
  • 28
  • 30
5

There might be answers to this question, but you may want to see these migrations to PHP 7

backward incompatible change

source: php.net

Petter Friberg
  • 21,252
  • 9
  • 60
  • 109
Muhammad Maulana
  • 180
  • 2
  • 11
4

It is simple, $obj->{$obj->Name} the curly brackets will wrap the property much like a variable variable.

This was a top search. But did not resolve my question, which was using $this. In the case of my circumstance using the curly bracket also helped...

example with Code Igniter get instance

in an sourced library class called something with a parent class instance

$this->someClass='something';
$this->someID=34;

the library class needing to source from another class also with the parents instance

echo $this->CI->{$this->someClass}->{$this->someID};
Mark Allen
  • 69
  • 2
2

In case anyone else wants to find a deep property of unknown depth, I came up with the below without needing to loop through all known properties of all children.

For example, to find $foo->Bar->baz->bam, given an object ($foo) and a string like "Bar->baz->bam".

trait PropertyGetter {
    public function getProperty($pathString, $delimiter = '->') {

        //split the string into an array
        $pathArray = explode($delimiter, $pathString);

        //get the first and last of the array
        $first = array_shift($pathArray);
        $last = array_pop($pathArray);

        //if the array is now empty, we can access simply without a loop
        if(count($pathArray) == 0){
            return $this->{$first}->{$last};
        }

        //we need to go deeper
        //$tmp = $this->Foo
        $tmp = $this->{$first};

        foreach($pathArray as $deeper) {
            //re-assign $tmp to be the next level of the object
            // $tmp = $Foo->Bar --- then $tmp = $tmp->baz
            $tmp = $tmp->{$deeper};
        }

        //now we are at the level we need to be and can access the property
        return $tmp->{$last};

    }
}

And then call with something like:

$foo = new SomeClass(); // this class imports PropertyGetter trait
echo $foo->getProperty("bar->baz->bam");
miken32
  • 42,008
  • 16
  • 111
  • 154
Jordan Whitfield
  • 1,413
  • 15
  • 17
2

Just as an addition: This way you can access properties with names that would be otherwise unusable

$x = new StdClass;

$prop = 'a b'; $x->$prop = 1; $x->{'x y'} = 2; var_dump($x);

object(stdClass)#1 (2) {
  ["a b"]=>
  int(1)
  ["x y"]=>
  int(2)
}
(not that you should, but in case you have to).
If you want to do even fancier stuff you should look into reflection
VolkerK
  • 95,432
  • 20
  • 163
  • 226
0

What this function does is it checks if the property exist on this class of any of his child's, and if so it gets the value otherwise it returns null. So now the properties are optional and dynamic.

/**
 * check if property is defined on this class or any of it's childes and return it
 *
 * @param $property
 *
 * @return bool
 */
private function getIfExist($property)
{
    $value = null;
    $propertiesArray = get_object_vars($this);

    if(array_has($propertiesArray, $property)){
        $value = $propertiesArray[$property];
    }

    return $value;
}

Usage:

const CONFIG_FILE_PATH_PROPERTY = 'configFilePath';

$configFilePath = $this->getIfExist(self::CONFIG_FILE_PATH_PROPERTY);
Mahmoud Zalt
  • 30,478
  • 7
  • 87
  • 83
0

Here is my attempt. It has some common 'stupidity' checks built in, making sure you don't try to set or get a member which isn't available.

You could move those 'property_exists' checks to __set and __get respectively and call them directly within magic().

<?php

class Foo {
    public $Name;

    public function magic($member, $value = NULL) {
        if ($value != NULL) {
            if (!property_exists($this, $member)) {
                trigger_error('Undefined property via magic(): ' .
                    $member, E_USER_ERROR);
                return NULL;
            }
            $this->$member = $value;
        } else {
            if (!property_exists($this, $member)) {
                trigger_error('Undefined property via magic(): ' .
                    $member, E_USER_ERROR);
                return NULL;
            }
            return $this->$member;
        }
    }
};

$f = new Foo();

$f->magic("Name", "Something");
echo $f->magic("Name") , "\n";

// error
$f->magic("Fame", "Something");
echo $f->magic("Fame") , "\n";

?>
Nick Presta
  • 28,134
  • 6
  • 57
  • 76
-6
$classname = "myclass";
$obj = new $classname($params);

$variable_name = "my_member_variable";
$val = $obj->$variable_name; //do care about the level(private,public,protected)

$func_name = "myFunction";
$val = $obj->$func_name($parameters);

why edit: before : using eval (evil) after : no eval at all. being old in this language.

r4ccoon
  • 3,056
  • 4
  • 26
  • 32
  • This is very bad advice, the eval() function is a very dangerous tool and will leave you hugely vulnerable to injection attacks. http://www.blog.highub.com/php/php-core/php-eval-is-evil/ should give you some information. – ridecar2 Dec 08 '11 at 10:25
  • 4
    Delete this answer and you'll have a badge ! – Thermech Feb 12 '14 at 20:03