通过字符串获取 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 通常,如果您有一个以类似数组的方式使用变量的现有系统,但您希望对象提供的灵活性和功能,则使用后者的主要好处。如果一个类实现了ArrayAccess
、Countable
和其中一个迭代器接口,它与普通的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->$property[$name]
,这是唯一的方法,否则$this->$property[$name]
会抛出错误
@goyote:这取决于值和 PHP 版本。在 5.3 中,它触发 E_NOTICE 因为找不到属性,而不是“错误”,因为它仍然是有效的 PHP 语法。 $this->$property[$name]
可能实际上会成功,尽管这可能是一个错误。 $name
被默默地转换为整数。如果是非数字字符串,则为0
。然后将$property
的值的这个字符串index 用作属性名称。如果$property
持有值“abc”,那么这将引用属性$this->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->Bar->baz->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 类属性的主要内容,如果未能解决你的问题,请参考以下文章