如何优雅地修复"undefined index"通知?



这可能是一个通用问题,我读过的99%的解决方案都是使用isset来保持安全和冗长。但是,我仍然认为它不是那么优雅,而且有点重复。

为了更好地理解我的问题,以下是我的代码的一般模式:

public static function buildObject(array $userProperties) {
// Here, I'm building a user from an associative array.
// If the developer passes in an array with missing name or address,
// this will generate an undefined index notice!
$user = new User();
$user->setName($userProperties['name']);
$user->setAddress($userProperties['address']);
return $user;
}

到目前为止我尝试过:

  1. 添加对所有设置调用的isset()检查。对于此示例来说,这可能不是一个坏主意,但是我有一些具有许多属性的大型类,并且看起来和感觉都非常重复。

  2. 通过循环访问属性并将其设置为 null(如果数组中不存在(来确保数组安全。这在代码中似乎并不那么糟糕,但感觉像是一种解决方法。

  3. 使用空合并运算符?? null。这也感觉重复且不可读

我更喜欢一个简单的解决方案,它不会添加太多逻辑,但看起来很优雅。我知道最好在这里进行验证,但是在处理可选字段时会遇到同样的问题。

优雅没有客观的衡量标准。一个开发人员可能会觉得优雅的东西,另一个开发人员会发现冗长和重复。对于这样的事情,无论什么被认为是最好的,总是完全主观的。

话虽如此,如果你发现自己一遍又一遍地做一些不必要的重复和冗长的事情,这通常是一种可以改进的气味。

您的用例的可能解决方案会有很大差异,具体取决于您想要的方向。您可以创建一个实现ArrayAccess的参数对象,以便使用者仍然可以将参数视为数组,但您可以在方法中更简洁地使用它。

或者,您可以创建一个具有流畅界面的构建器对象,以便创建用户根本不需要数组:

$user = UserBuilder::start()
->setName('Foo')
->setLastName('Bar')
->build();

但这完全取决于你的实现细节,取决于你愿意为这种相对方便而经历的额外工作,以及你想要解决的具体问题。

当将关联数组作为参数传递并且您希望访问一些有保证的键时,一种非常常见且非常简单的模式是使用array_merge()

例如:

function foo(array $arguments) {
$arguments = array_merge( [
'name'     => null,
'lastName' => null,
'role'     => ROLE_USER
],
$arguments);
}

再多的魔法也不会给一个没有收到名字的User对象命名,但这样至少设置了数组键,你可以在使用它们之前使用它来设置其他默认值。

最后,你必须决定什么对你有用,你认为什么是优雅的,以及什么样的实现在你的项目中真正值得。

最新更新