PHP声明返回类型为object的函数,错误场景下如何返回明确错误值?
嘿,完全懂你在十年老PHP项目里推进类型声明的难处——作为初级开发者,在管理层不重视的情况下坚持写整洁代码,真的值得点赞!咱们一步步解决你的问题:
1. 解决返回object时不能返回null的问题
PHP从7.1版本开始支持可空类型声明,只需要在类型前面加个?,就能允许函数返回该类型或者null。所以你只需要把返回类型改成?object就行:
function coefficient(?int $pack_size = null) : ?object { $result = null; // ... 你的代码逻辑 ... return $result; }
顺便提一句:你把参数$pack_size声明为int|null,其实可以简化成?int,效果完全一致且更简洁。另外检查数字的逻辑,用is_numeric()比正则表达式更高效,毕竟你已经声明了参数是?int,null的情况直接跳过检查就好。
2. 错误场景下的返回值选择
在PHP里,错误场景的处理方式主要分两种,取决于你遇到的是「无结果」还是「真正的程序错误」:
场景一:无结果(比如找不到对应系数)
这种情况属于正常业务逻辑的一部分,不是程序错误,用**可空类型返回null**就很合适。但一定要在PHPDoc里明确说明什么时候会返回null,方便其他开发者调用时处理:
/** * Returns a coefficient object depending on the pack size given as an argument * @param ?int $pack_size * @return object|null Returns the matching coefficient object if found; null otherwise */
场景二:真正的错误(比如参数不合法、实例ID无效)
这种情况应该抛出异常,而不是返回null。因为null很容易被忽略,导致后续代码出现意外的Call to a member function ... on null错误,而异常会强制调用者处理错误情况,代码更健壮。
比如修改你的代码,在错误场景抛出对应异常:
/** * Returns a coefficient object depending on the pack size given as an argument * @param ?int $pack_size * @return object Returns the matching coefficient object * @throws InvalidArgumentException If pack_size is not a valid number * @throws RuntimeException If instance ID is invalid or no coefficient found */ function coefficient(?int $pack_size = null) : object { // 实例ID无效是错误,抛出异常 if (!est_id($this->id)) { throw new RuntimeException("Current instance has an invalid ID"); } // 参数不合法,抛出参数异常 if ($pack_size !== null && !is_numeric($pack_size)) { throw new InvalidArgumentException("Pack size must be a valid number or null"); } if (is_object($this->coefficient_group)) { $coefficient_resultSQL = coefficient::list(['group' => $this->coefficient_group->id(), 'size' => $pack_size]); if (!empty($coefficient_resultSQL->result)) { $coefficient_src = reset($coefficient_resultSQL->result); $coefficient = new coefficient(null, ['element' => $coefficient_src]); if (est_id($coefficient->id())) { return $coefficient; } } } // 找不到系数也是错误,抛出异常 throw new RuntimeException("No coefficient found for pack size: " . $pack_size); }
备选方案:返回带状态的结果结构
如果老项目团队不习惯用异常,也可以返回一个包含状态的数组或自定义对象,比如:
function coefficient(?int $pack_size = null) : array { // ... 逻辑 ... if ($result) { return ['success' => true, 'data' => $result]; } else { return ['success' => false, 'error' => 'No coefficient found']; } }
不过这种方式需要调用者每次都检查success字段,代码会稍微繁琐一点,但在团队统一习惯的情况下也能工作。
最后给你个小建议
在老项目里推进规范,不用一下子全面铺开——先从自己负责的函数开始,写好清晰的注释和类型声明,慢慢让其他开发者看到整洁代码的好处,逐步带动团队习惯。加油!
内容的提问来源于stack exchange,提问作者CodeKiwi

