如何修复"未定义的索引"优雅地注意到?

时间:2018-06-10 05:06:21

标签: php validation php-7

这可能是一个普遍的问题,我读过的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 coalesce operator ?? null。这也感觉重复,而且不那么可读。

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

1 个答案:

答案 0 :(得分:2)

优雅没有客观指标。一个开发人员可能会发现优雅的其他人会发现冗长和重复。无论什么被认为是 best 这样的事情总是完全主观的。

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

根据您的使用方向,您的用例可能的解决方案会有很大差异。您可以创建一个实现ArrayAccess的参数对象,这样消费者仍然可以将参数视为数组,但您可以在方法中更简洁地使用它。

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

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

但这一切都取决于您的实施细节,您愿意为此相对方便而进行的额外工作,以及您想要解决的具体内容。

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

E.g:

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

没有多少魔法会为没有收到一个的User对象命名,但这样至少设置了数组键,你可以用它来设置其他默认值和他们一起工作。

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