通过字符串获取PHP类属性


139

如何在基于字符串的PHP中获取属性?我给它打电话magic。那是什么magic呢?

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

就像...

magic($obj, 'Name', 'something');
$get = magic($obj, 'Name');

Answers:


241

像这样

<?php

$prop = 'Name';

echo $obj->$prop;

或者,如果您可以控制该类,请实现ArrayAccess接口,然后执行此操作

echo $obj['Name'];

使用第二个选项比第一个选项有什么好处?
Clox

2
@Clox通常,如果您有一个现有的系统以类似数组的方式使用变量,但又希望对象提供灵活性和功能,则使用后者的主要好处。如果一个类实现ArrayAccessCountable和迭代器接口之一,它是从一个正常的大多是没有区别array()
彼得·贝利

158

如果要访问属性而不创建中间变量,请使用{}表示法:

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

这还允许您例如在循环中构建属性名称:

for ($i = 0; $i < 5; $i++) {
    $something = $object->{'something' . $i};
    // ...
}

8
这是您要访问数组值的唯一方法$this->{$property}[$name],否则$this->$property[$name]将引发错误
goyote 2012年

@goyote:这取决于值和PHP版本。在5.3中,它触发E_NOTICE,因为找不到属性,而不是“错误”,因为它仍然是有效的PHP语法。$this->$property[$name]尽管这可能是一个错误,但实际上可能会成功。$name被静默转换为整数。如果是非数字字符串,则为0。然后,该值的字符串索引$property用作属性名称。如果$property保留值“ abc”,则它将引用属性$this->a(索引0)。如果有这样的属性,那么它将成功。
MrWhite

@goyote:但是,在PHP 5.4中,非数字字符串索引不会静默转换为整数0,它将触发E_WARNING。
MrWhite

13

您要问的是所谓的Variable Variables。您需要做的就是将字符串存储在变量中,然后像这样访问它:

$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

3
变量变量是另一回事。
奥拉维尔Waage

2
问题是当名称包含在字符串(变量)中时,如何获取类属性(变量)。还是我看错了问题?
matpie

8

像这样吗 尚未测试,但应该可以正常工作。

function magic($obj, $var, $value = NULL)
{
    if($value == NULL)
    {
        return $obj->$var;
    }
    else
    {
        $obj->$var = $value;
    }
}

2
+1,不知道可以使用字符串访问对象属性。
Marco Demaio 2011年

5

只需将属性名称存储在变量中,然后使用该变量访问属性。像这样:

$name = 'Name';

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


4

很简单,$ obj-> {$ obj-> Name}大括号将把属性包装起来就像一个变量变量。

这是一个热门搜索。但是并没有解决我的问题,那就是使用$ this。在我的情况下,使用大括号也有帮助...

Code Igniter的示例获取实例

在一个带有父类实例的源库类中

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

需要与父实例一起从另一个类中获取资源的库类

echo $this->CI->{$this->someClass}->{$this->someID};

2

作为补充:通过这种方式,您可以使用原本无法使用的名称访问属性

$ x =新的StdClass;

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

object(stdClass)#1(2){
  [“ a b”] =>
  整数(1)
  [“ x y”] =>
  整数(2)
}
(并不是您应该这样做,但万一必须这样做)。
如果你想要做的更炫的东西你应该看看反思


1

万一其他人想找到未知深度的深层属性,我想出了以下内容而无需遍历所有子级的所有已知属性。

例如,要查找$ Foo-> Bar-> baz或$ Foo-> baz或$ Foo-> Bar-> Baz-> dave,其中$ path是类似于'foo / bar / baz'的字符串。

public function callModule($pathString, $delimiter = '/'){

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

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

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

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

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

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

}

然后调用类似:

$propertyString = getXMLAttribute('string'); // '@Foo/Bar/baz'
$propertyString = substr($propertyString, 1);
$moduleCaller = new ModuleCaller();
echo $moduleCaller->callModule($propertyString);

0

这是我的尝试。它内置了一些常见的“愚蠢”检查,确保您不会尝试设置或获取不可用的成员。

您可以将“ property_exists”检查分别移到__set和__get,然后直接在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";

?>

0

该函数的作用是检查该属性是否存在于其孩子的任何此类的该类上,如果存在,则获取该值,否则返回null。因此,现在这些属性是可选的并且是动态的。

/**
 * 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;
}

用法:

const CONFIG_FILE_PATH_PROPERTY = 'configFilePath';

$configFilePath = $this->getIfExist(self::CONFIG_FILE_PATH_PROPERTY);

-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);

为什么要编辑:之前:使用eval(evil)之后:完全没有eval。用这种语言老了。


这是非常糟糕的建议,eval()函数是非常危险的工具,会使您极易受到注入攻击的攻击。 blog.highub.com/php/php-core/php-eval-is-evil应该给您一些信息。
ridecar2 2011年

3
删除此答案,您将获得徽章!
Thermech 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.