PHP:变量变量中的类属性链接
因此,我有一个结构类似于下面的对象,所有这些对象都作为 stdClass
对象
$person->contact->phone;
$person->contact->email;
$person->contact->address->line_1;
$person->contact->address->line_2;
$person->dob->day;
$person->dob->month;
$person->dob->year;
$album->name;
$album->image->height;
$album->image->width;
$album->artist->name;
$album->artist->id;
等返回给我......(请注意,这些示例没有链接在一起)。
是否可以使用可变变量来调用 contact->phone
作为 $person
的直接属性?
例如:
$property = 'contact->phone';
echo $person->$property;
这将无法按原样工作并抛出 E_NOTICE
因此我正在尝试找出一种替代方法来实现此目的。
有什么想法吗?
响应与代理方法相关的答案:
我希望这个对象来自一个库,并使用它来使用数组映射填充新对象,如下所示:
array(
'contactPhone' => 'contact->phone',
'contactEmail' => 'contact->email'
);
然后遍历映射以填充新对象。我想我可以用映射器代替......
So, I have a object with structure similar to below, all of which are returned to me as stdClass
objects
$person->contact->phone;
$person->contact->email;
$person->contact->address->line_1;
$person->contact->address->line_2;
$person->dob->day;
$person->dob->month;
$person->dob->year;
$album->name;
$album->image->height;
$album->image->width;
$album->artist->name;
$album->artist->id;
etc... (note these examples are not linked together).
Is it possible to use variable variables to call contact->phone
as a direct property of $person
?
For example:
$property = 'contact->phone';
echo $person->$property;
This will not work as is and throws a E_NOTICE
so I am trying to work out an alternative method to achieve this.
Any ideas?
In response to answers relating to proxy methods:
And I would except this object is from a library and am using it to populate a new object with an array map as follows:
array(
'contactPhone' => 'contact->phone',
'contactEmail' => 'contact->email'
);
and then foreaching through the map to populate the new object. I guess I could envole the mapper instead...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
如果我是你,我会创建一个简单的方法
->property();
,返回$this->contact->phone
If i was you I would create a simple method
->property();
that returns$this->contact->phone
不可能使用表达式作为变量变量名。
但你总是可以作弊:
It's not possible to use expressions as variable variable names.
But you can always cheat:
试试这个代码
try this code
我认为这是一件坏事,因为它会导致不可读的代码在其他级别上也是明显错误的,但一般来说,如果您需要在对象语法中包含变量,您应该将其用大括号括起来,以便首先解析它。
例如:
如果您需要访问名称中含有禁止字符的对象,则同样适用,这种情况在 SimpleXML 对象中经常发生。
I think this is a bad thing to to as it leads to unreadable code is is plain wrong on other levels too, but in general if you need to include variables in the object syntax you should wrap it in braces so that it gets parsed first.
For example:
The same applies if you need to access an object that has disalowed characters in the name which can happen with SimpleXML objects regularly.
如果它是合法的,并不意味着它也是道德的。这是 PHP 的主要问题,是的,你几乎可以做任何你能想到的事情,但这并不意味着它是正确的。看看德米特定律:
德米特定律
如果你真的很想的话,试试这个:
json_decode(json_encode($person),true);
您将能够将其解析为数组而不是对象,但它的工作是获取而不是设置。
编辑:
}
If it is legal it does not mean it is also moral. And this is the main issue with PHP, yes, you can do almost whatever you can think of, but that does not make it right. Take a look at the law of demeter:
Law of Demeter
try this if you really really want to:
json_decode(json_encode($person),true);
you will be able to parse it as an array not an object but it does your job for the getting not for the setting.
EDIT:
}
OOP 主要是保护对象的内部不受外界影响。您在这里尝试做的是提供一种通过
person
界面公开phone
内部结构的方法。这不太好。如果您想要一种方便的方法来获取“所有”属性,您可能需要为此编写一组显式的便利函数,如果您愿意,可以将其包装在另一个类中。这样,您就可以发展支持的实用程序,而不必触及(并可能破坏)核心数据结构:
如果您需要更专业的功能,请将其添加到实用程序中。恕我直言,这是一个很好的解决方案:将便利性与核心分开,以降低复杂性,并提高可维护性/可理解性。
另一种方法是围绕核心类的内部结构构建便利的“扩展”Person 类:
OOP is much about shielding the object's internals from the outside world. What you try to do here is provide a way to publicize the innards of the
phone
through theperson
interface. That's not nice.If you want a convenient way to get "all" the properties, you may want to write an explicit set of convenience functions for that, maybe wrapped in another class if you like. That way you can evolve the supported utilities without having to touch (and possibly break) the core data structures:
If ever you need a more specialized function, you add it to the utilities. This is imho the nices solution: separate the convenience from the core to decrease complexity, and increase maintainability/understandability.
Another way is to 'extend' the
Person
class with conveniences, built around the core class' innards:您可以使用类型转换将对象更改为数组。
You could use type casting to change the object to an array.
在大多数情况下,如果您有嵌套的内部对象,那么现在可能是重新评估数据结构的好时机。
在上面的示例中,person 有 contact 和 dob。 联系人还包含地址。在编写复杂的数据库应用程序时,尝试从最上层访问数据并不罕见。但是,您可能会发现对此的最佳解决方案是将数据合并到 person 类中,而不是尝试本质上“挖掘”到内部对象中。
In most cases where you have nested internal objects, it might be a good time to re-evaluate your data structures.
In the example above, person has contact and dob. The contact also contains address. Trying to access the data from the uppermost level is not uncommon when writing complex database applications. However, you might find your the best solution to this is to consolidate data up into the person class instead of trying to essentially "mine" into the internal objects.
尽管我讨厌这么说,但你可以进行 eval :
As much as I hate saying it, you could do an eval :
除了使用
function getPhone(){return $this->contact->phone;}
之外,您还可以创建一个神奇的方法来查找请求字段的内部对象。请记住,魔法方法虽然有点慢。Besides making
function getPhone(){return $this->contact->phone;}
you could make a magic method that would look through internal objects for requested field. Do remember that magic methods are somewhat slow though.我决定放弃整个方法,转而采用更冗长但更干净、而且很可能更高效的方法。我一开始并不太热衷于这个想法,大多数人都在这里发表了意见,让我做出了决定。感谢您的回答。
编辑:
如果您有兴趣:
I have decided to scrap this whole approach and go with a more long-winded but cleaner and most probably more efficient. I wasn't too keen on this idea in the first place, and the majority has spoken on here to make my mind up for me. Thank for you for your answers.
Edit:
If you are interested:
如果您以类似结构的方式使用对象,则可以显式地为请求的节点建模“路径”。然后,您可以使用相同的检索代码“装饰”您的对象。
“仅检索”装饰代码的示例:(
在 codepad 上找到它)
In case you use your object in a struct-like way, you can model a 'path' to the requested node explicitly. You can then 'decorate' your objects with the same retrieval code.
An example of 'retrieval only' decoration code:
(find it on codepad)
如果你知道这两个函数的名称,你能做到吗? (未经测试)
如果它并不总是两个功能,您可以对其进行更多修改以使其工作。要点是,只要使用括号格式,您就可以使用可变变量调用链式函数。
If you know the two function's names, could you do this? (not tested)
If it's not always two functions, you could hack it more to make it work. Point is, you can call chained functions using variable variables, as long as you use the bracket format.
我所知道的最简单、最干净的方法。
用法
Simplest and cleanest way I know of.
Usage