通过字符串获取 PHP 类属性

Posted

技术标签:

【中文标题】通过字符串获取 PHP 类属性【英文标题】:Get PHP class property by string 【发布时间】:2010-10-22 17:39:03 【问题描述】:

如何在 php 中基于字符串获取属性?我会称之为magic。那么magic是什么?

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

会像...

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

【问题讨论】:

【参考方案1】:

这样

<?php

$prop = 'Name';

echo $obj->$prop;

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

echo $obj['Name'];

【讨论】:

使用第二个选项比第一个有什么好处? @Clox 通常,如果您有一个以类似数组的方式使用变量的现有系统,但您希望对象提供的灵活性和功能,则使用后者的主要好处。如果一个类实现了ArrayAccessCountable 和其中一个迭代器接口,它与普通的array() 几乎没有区别【参考方案2】:

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

function magic($obj, $var, $value = NULL)

    if($value == NULL)
    
        return $obj->$var;
    
    else
    
        $obj->$var = $value;
    

【讨论】:

+1,不知道可以使用字符串访问对象属性。【参考方案3】:

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

$name = 'Name';

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

【讨论】:

【参考方案4】:

您要问的是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

【讨论】:

可变变量是另一回事。 问题是当名称包含在字符串(变量)中时如何获取类属性(变量)。还是我看错了问题?【参考方案5】:

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

$x = new StdClass;

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

object(stdClass)#1 (2) 
  ["a b"]=>
  整数(1)
  [“x y”]=>
  整数(2)
(不是你应该这样做,但如果你必须这样做)。 如果你想做更高级的东西,你应该看看reflection

【讨论】:

【参考方案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(邪恶) 之后:根本没有评估。用这门语言老了。

【讨论】:

这是一个非常糟糕的建议,eval() 函数是一个非常危险的工具,会让您极易受到注入攻击。 blog.highub.com/php/php-core/php-eval-is-evil 应该会给你一些信息。 删除此答案,您将获得徽章!【参考方案7】:

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

您可以将这些“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";

?>

【讨论】:

【参考方案8】:

很简单,$obj->$obj->Name 大括号会将属性包裹起来,就像变量变量一样。

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

使用 Code Igniter 获取实例的示例

在带有父类实例的源库类中调用的东西

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

需要从另一个类中获取源的库类以及父实例

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

【讨论】:

【参考方案9】:

如果您想在不创建中间变量的情况下访问该属性,请使用 表示法:

$something = $object->'something';

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

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

【讨论】:

如果要访问数组值$this-&gt;$property[$name],这是唯一的方法,否则$this-&gt;$property[$name]会抛出错误 @goyote:这取决于值和 PHP 版本。在 5.3 中,它触发 E_NOTICE 因为找不到属性,而不是“错误”,因为它仍然是有效的 PHP 语法。 $this-&gt;$property[$name] 可能实际上会成功,尽管这可能是一个错误。 $name 被默默地转换为整数。如果是非数字字符串,则为0。然后将$property 的值的这个字符串index 用作属性名称。如果$property 持有值“abc”,那么这将引用属性$this-&gt;a(索引0)。如果有这样的属性,那么这将成功。 @goyote:但是,在 PHP 5.4 中,非数字字符串索引不会默默地转换为整数 0,它会触发 E_WARNING。【参考方案10】:

此函数的作用是检查该属性是否存在于他孩子的任何此类中,如果存在则获取值,否则返回 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);

【讨论】:

【参考方案11】:

可能有这个问题的答案,但您可能希望看到这些迁移到 PHP 7

来源:php.net

【讨论】:

【参考方案12】:

如果其他人想要找到深度未知的深度属性,我想出了下面的方法,而无需遍历所有子节点的所有已知属性。

例如,要查找$foo-&gt;Bar-&gt;baz-&gt;bam,给定一个对象 ($foo) 和一个类似“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;

    

然后调用类似:

$foo = new SomeClass(); // this class imports PropertyGetter trait
echo $foo->getProperty("bar->baz->bam");

【讨论】:

以上是关于通过字符串获取 PHP 类属性的主要内容,如果未能解决你的问题,请参考以下文章

java 反射机制,通过字符串获取一个类的属性,并且得到这个属性是啥类型的。

Python如何通过字符或数字动态获取对象的名称或者属性?

python string字符串转类属性

Flutter Dart - 动态获取类的属性

java中如何通过反射获取类的属性

如何获取类的公共属性?