This is a bit philosophical but I think many people encountered this problem. The goal is to access various (dynamically declared) properties in PHP and get rid of notices when they are not set.
这有点哲学,但我想很多人都遇到过这个问题。目标是在PHP中访问各种(动态声明的)属性,并在未设置时删除通知。
Why not to __get
?
That's good option if you can declare your own class, but not in case of stdClass
, SimpleXML
or similar. Extending them is not and option since you usually do not instantiate these classes directly, they are returned as a result of JSON/XML parsing.
为什么不__get?如果您可以声明自己的类,那么这是一个很好的选择,但不是stdClass,SimpleXML或类似的情况。扩展它们不是选项,因为您通常不直接实例化这些类,它们是作为JSON / XML解析的结果返回的。
Example:
例:
$data = '{"name": "Pavel", "job": "programmer"}';
$object = json_decode($data);
We have simple stdClass
object. The problems is obvious:
我们有简单的stdClass对象。问题很明显:
$b = $data->birthday;
The property is not defined and therefore a notice is raised:
该属性未定义,因此会发出通知:
PHP Notice: Undefined property: stdClass::$birthday
This can happen very often if you consider that you get that object from parsing some JSON. The naive solution is obvious:
如果您认为通过解析某些JSON获得该对象,则会经常发生这种情况。天真的解决方案是显而易见的:
$b = isset($data->birthday) ? $data->birthday : null;
However, one gets tired very soon when wrapping every accessor into this. Especially when chaining the objects, such as $data->people[0]->birthday->year
. Check whether people
is set. Check if the first element is set. Check if birthday
is set. Check if year
is set. I feel a bit overchecked...
然而,当将每个存取器包装到其中时,很快就会感到疲倦。特别是在链接对象时,例如$ data-> people [0] - > birthday-> year。检查是否已设置人员。检查是否设置了第一个元素。检查生日是否已设定。检查年份是否已设定。我觉得有点过分了......
Question: Finally, my question is here.
What is the best approach to this issue? Silencing notices does not seem to be the best idea. And checking every property is difficult. I have seen some solutions such as Symfony property access but I think it is still too much boilerplate. Is there any simpler way? Either third party library, PHP setting, C extension, I don't care as far as it works... And what are the possible pitfalls?
问:最后,我的问题在这里。解决这个问题的最佳方法是什么?沉默通知似乎不是最好的主意。检查每个房产都很困难。我已经看到一些解决方案,如Symfony属性访问,但我认为它仍然是太多的样板。有没有更简单的方法?无论是第三方库,PHP设置,C扩展,我都不在乎它的工作原理......还有什么可能的陷阱?
8 个解决方案
#1
3
If I understand correctly, you want to deal with 3rd party Objects, where you have no control, but your logic requires certain properties that may not be present on the Object. That means, the data you accepting are invalid (or should be declared invalid) for your logic. Then the burden of checking the validity goes into your validator. Which I hope you already have following best practices to deal with 3rd party data. :)
如果我理解正确,你想要处理你无法控制的第三方对象,但你的逻辑需要某些属性可能不存在于对象上。这意味着,您接受的数据对您的逻辑无效(或应被宣布无效)。然后检查有效性的负担进入验证器。我希望您已经有以下最佳实践来处理第三方数据。 :)
You can use your own validator or one by frameworks. A common way is to write a set of Rules that your data needs to obey in order to be valid.
您可以使用自己的验证器或框架。一种常见的方法是编写一组规则,数据需要遵守这些规则才能生效。
Now inside your validator, whenever a rule is not obeyed, you throw
an Exception describing the error and attaching Exception properties that carry the information you want to use. Later when you call your validator somewhere in your logic, you place it inside try {...}
block and you catch()
your Exceptions and deal with them, that is, write your special logic reserved for those exceptions. As general practice, if your logic becomes too large in a block, you want to "outsource" it as function. Quoting the great book by Robert Martin "Clean Code", highly recommended for any developer:
现在在验证器内部,每当不遵守规则时,您将抛出一个描述错误的异常并附加包含您要使用的信息的Exception属性。稍后当您在逻辑中的某个地方调用验证器时,将它放在try {...}块中,然后捕获()您的异常并处理它们,即编写为这些异常保留的特殊逻辑。作为一般惯例,如果您的逻辑在块中变得太大,您希望将其“外包”为函数。引用罗伯特·马丁“清洁代码”这本伟大的书,强烈推荐给任何开发者:
The first rule of function is that they should be small. The second is that they should be smaller than that.
功能的第一个规则是它们应该很小。第二是他们应该小于那个。
I understand your frustration dealing with eternal isset
s and see as cause of the problem here that each time you need to write a handler dealing with that technical issue of this or that property not present. That technical issue is of very low level in your abstraction hierarchy, and in order to handle it properly, you have to go all the way up your abstraction chain to reach a higher step that has a meaning for your logic. It is always hard to jump between different levels of abstraction, especially far apart. It is also what makes your code hard to maintain and is recommended to avoid. Ideally your whole architecture is designed as a tree where Controllers sitting at its nodes only know about the edges going down from them.
我理解你处理永恒issets的挫败感,并将此问题看作是每次你需要编写一个处理这个或那个属性不存在的技术问题的处理程序的原因。这个技术问题在你的抽象层次结构中是非常低级的,为了正确处理它,你必须在你的抽象链上一直走到一个对你的逻辑有意义的更高的步骤。在不同的抽象层次之间跳转总是很难,尤其是相距甚远。这也是使您的代码难以维护的原因,建议避免使用。理想情况下,您的整个架构都设计为树,其中坐在其节点上的控制器只知道从它们向下的边缘。
For instance, coming back to your example, the question is -
例如,回到你的例子,问题是 -
- Q - What is the meaning for your app of the situation that
$data->birthday
is missing? - 问 - 你的应用程序对$ data-> birthday缺失的情况有什么意义?
The meaning will depend on what the current function throwing the Exception wants to achieve. That is a convenient place to handle your Exception.
意义将取决于抛出Exception想要实现的当前函数。这是处理您的例外的一个方便的地方。
Hope it helps :)
希望能帮助到你 :)
#2
3
One solution (I don't know if it's the better solution, but one possible solution) is to create a function like this:
一个解决方案(我不知道它是否是更好的解决方案,但是一个可能的解决方案)是创建一个这样的函数:
function from_obj(&$type,$default = "") {
return isset($type)? $type : $default;
}
then
然后
$data = '{"name": "Pavel", "job": "programmer"}';
$object = json_decode($data);
$name = from_obj( $object->name , "unknown");
$job = from_obj( $object->job , "unknown");
$skill = from_obj( $object->skills[0] , "unknown");
$skills = from_obj( $object->skills , Array());
echo "Your name is $name. You are a $job and your main skill is $skill";
if(count($skills) > 0 ) {
echo "\n\nYour skills: " . implode(",",$skills);
}
I think it's convienent because you have at the top of your script what you want and what it should be (array, string, etc)
我认为它很方便,因为你在脚本的顶部有你想要的和它应该是什么(数组,字符串等)
EDIT:
编辑:
Another solution. You could create a Bridge class that extends ArrayObject:
另一解决方案您可以创建一个扩展ArrayObject的Bridge类:
class ObjectBridge extends ArrayObject{
private $obj;
public function __construct(&$obj) {
$this->obj = $obj;
}
public function __get($a) {
if(isset($this->obj->$a)) {
return $this->obj->$a;
}else {
// return an empty object in order to prevent errors with chain call
$tmp = new stdClass();
return new ObjectBridge($tmp);
}
}
public function __set($key,$value) {
$this->obj->$key = $value;
}
public function __call($method,$args) {
call_user_func_array(Array($this->obj,$method),$args);
}
public function __toString() {
return "";
}
}
$data = '{"name": "Pavel", "job": "programmer"}';
$object = json_decode($data);
$bridge = new ObjectBridge($object);
echo "My name is {$bridge->name}, I have " . count($bridge->skills). " skills and {$bridge->donald->duck->is->paperinik}<br/>";
// output: My name is Pavel, I have 0 skills and
// (no notice, no warning)
// we can set a property
$bridge->skills = Array('php','javascript');
// output: My name is Pavel, my main skill is php
echo "My name is {$bridge->name}, my main skill is {$bridge->skills[0]}<br/>";
// available also on original object
echo $object->skills[0]; // output: php
Personally I would prefer the first solution. It's more clear and more safe.
我个人更喜欢第一种解决方案。它更清晰,更安全。
#3
2
Data formats which have optional fields are quite difficult to deal with. They're problematic in particular if you have third parties accessing or providing the data, since there rarely is enough documentation to comprehensively cover all causes for the fields to appear or disappear. And of course, the permutations tend to be harder to test, because coders won't instinctively realize that the fields may be there.
具有可选字段的数据格式很难处理。如果您有第三方访问或提供数据,它们尤其成问题,因为很少有足够的文档来全面涵盖字段出现或消失的所有原因。当然,排列往往更难以测试,因为编码人员不会本能地意识到字段可能存在。
That's a long way of saying that if you can avoid having optional fields in your data, the best approach to dealing with missing object properties in PHP is to not have any missing object properties...
这是一个很长的路要说,如果你可以避免在数据中使用可选字段,那么在PHP中处理缺少的对象属性的最佳方法是不要有任何丢失的对象属性......
If the data you're dealing with is not up to you, then I'd look into forcing default values on all fields, perhaps via a helper function or some sort of crazy variation of the prototype pattern. You could build a data template, which contains default values for all fields of the data, and merge that with the real data.
如果您正在处理的数据不适合您,那么我会考虑强制所有字段的默认值,可能是通过辅助函数或原型模式的某种疯狂变化。您可以构建一个数据模板,其中包含数据所有字段的默认值,并将其与实际数据合并。
However, if you do that, are you failing, unless? (Which is another programming philosophy to take into heart.) I suppose one could make the case that providing safe default parameters satisfies data validation for any missing fields. But particularly when dealing with third party data, you should exercise high level of paranoia against any field you're plastering with default values. It's too easy to just set it to null and -- in the process -- fail to understand why it was missing in the first place.
但是,如果你这样做,你是否会失败,除非? (这是另一种深入思考的编程理念。)我想可以证明提供安全的默认参数满足任何缺失字段的数据验证。但特别是在处理第三方数据时,您应该对使用默认值进行填充的任何字段进行高度偏执。将它设置为null并且 - 在此过程中 - 很难理解为什么它首先缺失。
You should also ask what are you trying to achieve? Clarity? Safety? Stability? Minimal code duplication? These are all valid goals. Being tired? Less so. It suggests a lack disciprine, and a good programmer is always disciprined. Of course, I'll accept that people are less likely to do something, if they view it as a chore.
你还应该问一下你想要达到的目标是什么?明晰?安全?稳定性?最小代码重复?这些都是有效的目标。累吗?不那么好了。它表明缺乏学科,一个优秀的程序员总是受到训练。当然,我会接受人们不太可能做某事,如果他们认为这是一件苦差事。
My point is, the answer to your question may differ depending on why it's being asked. Zero effort solution is probably not going to be available, so if you're only exchanging one menial programming task to another one, are you solving anything?
我的观点是,你的问题的答案可能会有所不同,这取决于你被问到的原因。零努力解决方案可能无法使用,所以如果你只是将一个琐碎的编程任务交换到另一个,你在解决任何问题吗?
If you are looking for a systematic solution that will guarantee that the data is always in the format you have specified, leading to reduced number of logical tests in the code that processes that data, then perhaps what I suggested above will be of help. But it will not come without a cost and effort.
如果您正在寻找能够保证数据始终采用您指定格式的系统解决方案,从而减少处理该数据的代码中的逻辑测试数量,那么我上面建议的可能会有所帮助。但它不会没有成本和努力。
#4
1
The best answers have been given, but here is a lazy one:
已经给出了最好的答案,但这是一个懒惰的答案:
$data = '{"name": "Pavel", "job": "programmer"}';
$object = json_decode($data);
if(
//...check mandatory properties: !isset($object->...)&&
){
//error
}
error_reporting(E_ALL^E_NOTICE);//Yes you're right, not the best idea...
$b = $object->birthday?:'0000-00-00';//thanks Elvis (php>5.3)
//Notice that if your default value is "null", you can just do $b = $object->birthday;
//assign other vars here
error_reporting(E_ALL);
//Your code
#5
1
Use a Proxy object - it will add just one tiny class and one line per object instantiation to use it.
使用代理对象 - 它将为每个对象实例添加一个小类和一行来使用它。
class ProxyObj {
protected $obj;
public function __construct( $obj ) {
$this->_obj = $obj;
}
public function __get($key) {
if (isset($this->_obj->$key)) {
return $this->_obj->$key;
}
return null;
}
public function __set($key, $value) {
$this->_obj->$key = $value;
}
}
$proxy = new ProxyObj(json_decode($data));
$b = $proxy->birthday;
#6
0
function check($temp=null) {
if(isset($temp))
return $temp;
else
return null;
}
$b = check($data->birthday);
#7
0
I've hit this problem, mainly from getting json data from a nosql backed api that by design has inconsistent structures, eg if a user has an address you'll get $user->address otherwise the address key just isn't there. Rather than put tons of issets in my templates I wrote this class...
我遇到了这个问题,主要是从一个nosql支持的api获取json数据,设计中有不一致的结构,例如,如果用户有一个地址,你会得到$ user->地址,否则地址键就不存在了。我写了这个课,而不是在我的模板中放入大量的issets ...
class GracefulData
{
private $_path;
public function __construct($d=null,$p='')
{
$this->_path=$p;
if($d){
foreach(get_object_vars($d) as $property => $value) {
if(is_object($d->$property)){
$this->$property = new GracefulData($d->$property,$this->_path . '->' . $property);
}else{
$this->$property = $value;
}
}
}
}
public function __get($property) {
return new GracefulData(null,$this->_path . '->' . $property);
}
public function __toString() {
Log::info('GracefulData: Invalid property accessed' . $this->_path);
return '';
}
}
and then instantiate it like so
然后像这样实例化它
$user = new GracefulData($response->body);
It will gracefully handle nested calls to existing and non existing properties. What it can't handle though is if you access a child of an existing non-object property eg
它将优雅地处理对现有和非现有属性的嵌套调用。它无法处理的是,如果您访问现有非对象属性的子节点,例如
$user->firstName->something
$用户> firstName->的东西
#8
0
You can decode the JSON object to an array:
您可以将JSON对象解码为数组:
$data = '{"name": "Pavel", "job": "programmer"}';
$jsonarray = json_decode($data, true);
$b = $jsonarray["birthday"]; // NULL
#1
3
If I understand correctly, you want to deal with 3rd party Objects, where you have no control, but your logic requires certain properties that may not be present on the Object. That means, the data you accepting are invalid (or should be declared invalid) for your logic. Then the burden of checking the validity goes into your validator. Which I hope you already have following best practices to deal with 3rd party data. :)
如果我理解正确,你想要处理你无法控制的第三方对象,但你的逻辑需要某些属性可能不存在于对象上。这意味着,您接受的数据对您的逻辑无效(或应被宣布无效)。然后检查有效性的负担进入验证器。我希望您已经有以下最佳实践来处理第三方数据。 :)
You can use your own validator or one by frameworks. A common way is to write a set of Rules that your data needs to obey in order to be valid.
您可以使用自己的验证器或框架。一种常见的方法是编写一组规则,数据需要遵守这些规则才能生效。
Now inside your validator, whenever a rule is not obeyed, you throw
an Exception describing the error and attaching Exception properties that carry the information you want to use. Later when you call your validator somewhere in your logic, you place it inside try {...}
block and you catch()
your Exceptions and deal with them, that is, write your special logic reserved for those exceptions. As general practice, if your logic becomes too large in a block, you want to "outsource" it as function. Quoting the great book by Robert Martin "Clean Code", highly recommended for any developer:
现在在验证器内部,每当不遵守规则时,您将抛出一个描述错误的异常并附加包含您要使用的信息的Exception属性。稍后当您在逻辑中的某个地方调用验证器时,将它放在try {...}块中,然后捕获()您的异常并处理它们,即编写为这些异常保留的特殊逻辑。作为一般惯例,如果您的逻辑在块中变得太大,您希望将其“外包”为函数。引用罗伯特·马丁“清洁代码”这本伟大的书,强烈推荐给任何开发者:
The first rule of function is that they should be small. The second is that they should be smaller than that.
功能的第一个规则是它们应该很小。第二是他们应该小于那个。
I understand your frustration dealing with eternal isset
s and see as cause of the problem here that each time you need to write a handler dealing with that technical issue of this or that property not present. That technical issue is of very low level in your abstraction hierarchy, and in order to handle it properly, you have to go all the way up your abstraction chain to reach a higher step that has a meaning for your logic. It is always hard to jump between different levels of abstraction, especially far apart. It is also what makes your code hard to maintain and is recommended to avoid. Ideally your whole architecture is designed as a tree where Controllers sitting at its nodes only know about the edges going down from them.
我理解你处理永恒issets的挫败感,并将此问题看作是每次你需要编写一个处理这个或那个属性不存在的技术问题的处理程序的原因。这个技术问题在你的抽象层次结构中是非常低级的,为了正确处理它,你必须在你的抽象链上一直走到一个对你的逻辑有意义的更高的步骤。在不同的抽象层次之间跳转总是很难,尤其是相距甚远。这也是使您的代码难以维护的原因,建议避免使用。理想情况下,您的整个架构都设计为树,其中坐在其节点上的控制器只知道从它们向下的边缘。
For instance, coming back to your example, the question is -
例如,回到你的例子,问题是 -
- Q - What is the meaning for your app of the situation that
$data->birthday
is missing? - 问 - 你的应用程序对$ data-> birthday缺失的情况有什么意义?
The meaning will depend on what the current function throwing the Exception wants to achieve. That is a convenient place to handle your Exception.
意义将取决于抛出Exception想要实现的当前函数。这是处理您的例外的一个方便的地方。
Hope it helps :)
希望能帮助到你 :)
#2
3
One solution (I don't know if it's the better solution, but one possible solution) is to create a function like this:
一个解决方案(我不知道它是否是更好的解决方案,但是一个可能的解决方案)是创建一个这样的函数:
function from_obj(&$type,$default = "") {
return isset($type)? $type : $default;
}
then
然后
$data = '{"name": "Pavel", "job": "programmer"}';
$object = json_decode($data);
$name = from_obj( $object->name , "unknown");
$job = from_obj( $object->job , "unknown");
$skill = from_obj( $object->skills[0] , "unknown");
$skills = from_obj( $object->skills , Array());
echo "Your name is $name. You are a $job and your main skill is $skill";
if(count($skills) > 0 ) {
echo "\n\nYour skills: " . implode(",",$skills);
}
I think it's convienent because you have at the top of your script what you want and what it should be (array, string, etc)
我认为它很方便,因为你在脚本的顶部有你想要的和它应该是什么(数组,字符串等)
EDIT:
编辑:
Another solution. You could create a Bridge class that extends ArrayObject:
另一解决方案您可以创建一个扩展ArrayObject的Bridge类:
class ObjectBridge extends ArrayObject{
private $obj;
public function __construct(&$obj) {
$this->obj = $obj;
}
public function __get($a) {
if(isset($this->obj->$a)) {
return $this->obj->$a;
}else {
// return an empty object in order to prevent errors with chain call
$tmp = new stdClass();
return new ObjectBridge($tmp);
}
}
public function __set($key,$value) {
$this->obj->$key = $value;
}
public function __call($method,$args) {
call_user_func_array(Array($this->obj,$method),$args);
}
public function __toString() {
return "";
}
}
$data = '{"name": "Pavel", "job": "programmer"}';
$object = json_decode($data);
$bridge = new ObjectBridge($object);
echo "My name is {$bridge->name}, I have " . count($bridge->skills). " skills and {$bridge->donald->duck->is->paperinik}<br/>";
// output: My name is Pavel, I have 0 skills and
// (no notice, no warning)
// we can set a property
$bridge->skills = Array('php','javascript');
// output: My name is Pavel, my main skill is php
echo "My name is {$bridge->name}, my main skill is {$bridge->skills[0]}<br/>";
// available also on original object
echo $object->skills[0]; // output: php
Personally I would prefer the first solution. It's more clear and more safe.
我个人更喜欢第一种解决方案。它更清晰,更安全。
#3
2
Data formats which have optional fields are quite difficult to deal with. They're problematic in particular if you have third parties accessing or providing the data, since there rarely is enough documentation to comprehensively cover all causes for the fields to appear or disappear. And of course, the permutations tend to be harder to test, because coders won't instinctively realize that the fields may be there.
具有可选字段的数据格式很难处理。如果您有第三方访问或提供数据,它们尤其成问题,因为很少有足够的文档来全面涵盖字段出现或消失的所有原因。当然,排列往往更难以测试,因为编码人员不会本能地意识到字段可能存在。
That's a long way of saying that if you can avoid having optional fields in your data, the best approach to dealing with missing object properties in PHP is to not have any missing object properties...
这是一个很长的路要说,如果你可以避免在数据中使用可选字段,那么在PHP中处理缺少的对象属性的最佳方法是不要有任何丢失的对象属性......
If the data you're dealing with is not up to you, then I'd look into forcing default values on all fields, perhaps via a helper function or some sort of crazy variation of the prototype pattern. You could build a data template, which contains default values for all fields of the data, and merge that with the real data.
如果您正在处理的数据不适合您,那么我会考虑强制所有字段的默认值,可能是通过辅助函数或原型模式的某种疯狂变化。您可以构建一个数据模板,其中包含数据所有字段的默认值,并将其与实际数据合并。
However, if you do that, are you failing, unless? (Which is another programming philosophy to take into heart.) I suppose one could make the case that providing safe default parameters satisfies data validation for any missing fields. But particularly when dealing with third party data, you should exercise high level of paranoia against any field you're plastering with default values. It's too easy to just set it to null and -- in the process -- fail to understand why it was missing in the first place.
但是,如果你这样做,你是否会失败,除非? (这是另一种深入思考的编程理念。)我想可以证明提供安全的默认参数满足任何缺失字段的数据验证。但特别是在处理第三方数据时,您应该对使用默认值进行填充的任何字段进行高度偏执。将它设置为null并且 - 在此过程中 - 很难理解为什么它首先缺失。
You should also ask what are you trying to achieve? Clarity? Safety? Stability? Minimal code duplication? These are all valid goals. Being tired? Less so. It suggests a lack disciprine, and a good programmer is always disciprined. Of course, I'll accept that people are less likely to do something, if they view it as a chore.
你还应该问一下你想要达到的目标是什么?明晰?安全?稳定性?最小代码重复?这些都是有效的目标。累吗?不那么好了。它表明缺乏学科,一个优秀的程序员总是受到训练。当然,我会接受人们不太可能做某事,如果他们认为这是一件苦差事。
My point is, the answer to your question may differ depending on why it's being asked. Zero effort solution is probably not going to be available, so if you're only exchanging one menial programming task to another one, are you solving anything?
我的观点是,你的问题的答案可能会有所不同,这取决于你被问到的原因。零努力解决方案可能无法使用,所以如果你只是将一个琐碎的编程任务交换到另一个,你在解决任何问题吗?
If you are looking for a systematic solution that will guarantee that the data is always in the format you have specified, leading to reduced number of logical tests in the code that processes that data, then perhaps what I suggested above will be of help. But it will not come without a cost and effort.
如果您正在寻找能够保证数据始终采用您指定格式的系统解决方案,从而减少处理该数据的代码中的逻辑测试数量,那么我上面建议的可能会有所帮助。但它不会没有成本和努力。
#4
1
The best answers have been given, but here is a lazy one:
已经给出了最好的答案,但这是一个懒惰的答案:
$data = '{"name": "Pavel", "job": "programmer"}';
$object = json_decode($data);
if(
//...check mandatory properties: !isset($object->...)&&
){
//error
}
error_reporting(E_ALL^E_NOTICE);//Yes you're right, not the best idea...
$b = $object->birthday?:'0000-00-00';//thanks Elvis (php>5.3)
//Notice that if your default value is "null", you can just do $b = $object->birthday;
//assign other vars here
error_reporting(E_ALL);
//Your code
#5
1
Use a Proxy object - it will add just one tiny class and one line per object instantiation to use it.
使用代理对象 - 它将为每个对象实例添加一个小类和一行来使用它。
class ProxyObj {
protected $obj;
public function __construct( $obj ) {
$this->_obj = $obj;
}
public function __get($key) {
if (isset($this->_obj->$key)) {
return $this->_obj->$key;
}
return null;
}
public function __set($key, $value) {
$this->_obj->$key = $value;
}
}
$proxy = new ProxyObj(json_decode($data));
$b = $proxy->birthday;
#6
0
function check($temp=null) {
if(isset($temp))
return $temp;
else
return null;
}
$b = check($data->birthday);
#7
0
I've hit this problem, mainly from getting json data from a nosql backed api that by design has inconsistent structures, eg if a user has an address you'll get $user->address otherwise the address key just isn't there. Rather than put tons of issets in my templates I wrote this class...
我遇到了这个问题,主要是从一个nosql支持的api获取json数据,设计中有不一致的结构,例如,如果用户有一个地址,你会得到$ user->地址,否则地址键就不存在了。我写了这个课,而不是在我的模板中放入大量的issets ...
class GracefulData
{
private $_path;
public function __construct($d=null,$p='')
{
$this->_path=$p;
if($d){
foreach(get_object_vars($d) as $property => $value) {
if(is_object($d->$property)){
$this->$property = new GracefulData($d->$property,$this->_path . '->' . $property);
}else{
$this->$property = $value;
}
}
}
}
public function __get($property) {
return new GracefulData(null,$this->_path . '->' . $property);
}
public function __toString() {
Log::info('GracefulData: Invalid property accessed' . $this->_path);
return '';
}
}
and then instantiate it like so
然后像这样实例化它
$user = new GracefulData($response->body);
It will gracefully handle nested calls to existing and non existing properties. What it can't handle though is if you access a child of an existing non-object property eg
它将优雅地处理对现有和非现有属性的嵌套调用。它无法处理的是,如果您访问现有非对象属性的子节点,例如
$user->firstName->something
$用户> firstName->的东西
#8
0
You can decode the JSON object to an array:
您可以将JSON对象解码为数组:
$data = '{"name": "Pavel", "job": "programmer"}';
$jsonarray = json_decode($data, true);
$b = $jsonarray["birthday"]; // NULL