如何解决PHP中缺少的对象属性?

Pav*_* S. 11 php properties boilerplate isset

这有点哲学,但我想很多人都遇到过这个问题.目标是在PHP中访问各种(动态声明的)属性,并在未设置时删除通知.

为什么不__get呢?
那是,如果你可以声明自己的类很好的选择,但不是在的情况下stdClass,SimpleXML或类似的.扩展它们不是选项,因为您通常不直接实例化这些类,它们是作为JSON/XML解析的结果返回的.

例:

$data = '{"name": "Pavel", "job": "programmer"}';
$object = json_decode($data);
Run Code Online (Sandbox Code Playgroud)

我们有简单的stdClass对象.问题很明显:

$b = $data->birthday;
Run Code Online (Sandbox Code Playgroud)

该属性未定义,因此会发出通知:

PHP Notice:  Undefined property: stdClass::$birthday
Run Code Online (Sandbox Code Playgroud)

如果您认为通过解析某些JSON获得该对象,则可能经常发生这种情况.天真的解决方案是显而易见的:

$b = isset($data->birthday) ? $data->birthday : null;
Run Code Online (Sandbox Code Playgroud)

然而,当将每个存取器包装到其中时,很快就会感到疲倦.特别是当链接对象时,例如$data->people[0]->birthday->year.检查是否people已设置.检查是否设置了第一个元素.检查是否birthday已设置.检查是否year已设置.我觉得有点过分了......

问: 最后,我的问题在这里.
解决这个问题的最佳方法是什么?沉默通知似乎不是最好的主意.检查每个房产都很困难.我已经看到一些解决方案,如Symfony属性访问,但我认为它仍然是太多样板.有没有更简单的方法?无论是第三方库,PHP设置,C扩展,我都不在乎它的工作原理......还有什么可能的陷阱?

Dmi*_*sev 6

如果我理解正确,您想处理无法控制的第 3 方对象,但您的逻辑需要某些可能不存在于对象上的属性。这意味着,您接受的数据对于您的逻辑无效(或应该被声明为无效)。然后检查有效性的负担就交给你的验证器了。我希望您已经拥有以下处理 3rd 方数据的最佳实践。:)

您可以使用自己的验证器或框架之一。一种常见的方法是编写一组规则,您的数据需要遵守这些规则才能有效。

现在在您的验证器中,只要不遵守规则,就会出现throw一个 Exception 描述错误并附加携带您要使用的信息的 Exception 属性。稍后,当您在逻辑中的某处调用验证器时,您将它放在try {...}块中,并将您catch()的异常放入并处理它们,也就是说,编写为这些异常保留的特殊逻辑。作为一般做法,如果块中的逻辑变得太大,您希望将其“外包”为函数。引用 Robert Martin “Clean Code” 的好书,强烈推荐给任何开发人员:

功能的第一条规则是它们应该很小。第二个是它们应该比那个小。

我理解您在处理永恒的issets 时遇到的挫折,并将问题的原因视为每次您需要编写处理程序来处理不存在的这个或那个属性的技术问题。该技术问题在您的抽象层次结构中处于非常低的级别,为了正确处理它,您必须一直沿着抽象链向上到达对您的逻辑有意义的更高步骤。在不同的抽象层次之间跳转总是很困难,尤其是相距很远的抽象层次。这也是使您的代码难以维护并建议避免的原因。理想情况下,您的整个架构被设计为一棵树,其中位于其节点的控制器只知道从它们下降的边缘。

例如,回到你的例子,问题是——

  • 问 - 您的应用程序$data->birthday缺少的情况是什么意思?

含义将取决于当前抛出异常的函数想要实现的目标。这是处理您的异常的一个方便的地方。

希望能帮助到你 :)