【问题标题】:Dealing with PHP fatal type errors caused by introduction of type hinting处理引入类型提示导致的 PHP 致命类型错误
【发布时间】:2019-01-23 10:13:59
【问题描述】:

TL;DR

  • 我们是否可以配置 PHP,使其在类型提示导致参数类型错误时不会导致致命错误,而是导致警告?
  • PhpStorm / GIT 是否有插件/扩展可以防止保存或推送包含未解决问题的代码(最好仅针对类型提示问题进行过滤)。

对于我正在处理的一个代码库有点古怪的项目,我们正在尝试在我们可以的地方合并类型提示。 我们决定这样做是为了使代码库更易于阅读和维护。

我来自 C# 背景,所以很明显编译器让我变得懒惰,因为它基本上会告诉我何时尝试传递不正确类型的值。在PHP中,我们必须依靠IDE告诉我们,但由于没有编译,它确实不妨碍我们实现会导致运行时致命错误的代码路径。

由于我们都想继续使用这些类型提示,并且不让它在运行时导致致命错误,我们想知道是否可以将 PHP 配置为抛出 WARNING 而不是 FATAL当类型提示失败时。这将允许代码继续运行,并仍然通知我们需要解决此问题的事实。

我知道类型提示在设计上应该会导致致命,但是我们正在尝试暂时解决这个问题

对我们也有用(并且可能是理想的)是某种插件,它以某种方式阻止我们保存/推送具有此类未解决问题的代码。我们正在使用 PhpStorm 和 GIT 进行版本控制。

【问题讨论】:

  • 您是否考虑过添加自动化单元测试以在开发过程中捕获这些致命错误?
  • @EriksKlotins 实际上很多,但是我正在处理的代码库非常大,不幸的是,开始添加测试并不是一件小事。要是这样就好了。
  • 感觉就像你真的想设置一个static analysis tool 并且 PhpStorm 有一个内置的“严格类型检查规则违规”检查也应该警告你。我想关键是自动化它,对吗?
  • @ÁlvaroGonzález 我想我们已经在使用它了(我对 PHP 还不太熟悉,所以我可能错了)。问题是我想要一个工具来防止代码与主分支合并(并且严格的类型检查只会发出警告)。我不在乎它在哪个阶段被阻止,在 PhpStorm 的某个地方或 Git 客户端对我来说似乎是合乎逻辑的。

标签: php phpstorm


【解决方案1】:

我的建议是开始对添加的任何新代码或更改的旧代码实施自动化测试。因此,您将立即查看是否有任何损坏或是否存在触发类型错误的执行路径。

Here is an article on how to implement test automation in legacy systems

【讨论】:

  • 我是自动化测试的支持者,如果可能的话,我很乐意添加测试。我会根据您提供的文章重新考虑。但是,即使我们进行了自动化测试,也不能保证不会因添加类型提示而导致类型错误,因为人类仍然必须涵盖所有这些情况。
  • 假设系统按原样工作,只需要对更改的部分进行测试。当然,仍然需要人类来设计测试用例。但是,您只做一次,就不会再回头看同一个问题
【解决方案2】:

不确定这是否可能,我怀疑它是可能的。

但是:请不要。

相反,您可以:

  • 编写单元测试,例如using PhpUnit
  • 如果传递值,则在需要类型时允许“空”响应和参数
  • 使用代码质量检查器要求代码通过某些条件,例如Codacy(还有很多其他的!)

对于空响应或空参数,请考虑以下事项:

/**
 * @var User
 * @ORM\ManyToOne(targetEntity="User\Entity\User", fetch="EAGER")
 * @ORM\JoinColumn(name="bcc_user_id", referencedColumnName="id", nullable=false)
 */
protected $bcc;

这是我的一个项目中的一个类的属性示例。在这种情况下,对于邮件实体。它应该有一个实例用户的类对象。一个普通的(生成的)getter/setter 最终会是:

/**
 * @return User
 */
public function getBcc() : User
{
    return $this->bcc;
}

/**
 * @param User $bcc
 *
 * @return Mail
 */
public function setBcc(User $bcc) : Mail
{
    $this->bcc = $bcc;

    return $this;
}

但是,它是电子邮件的“密件抄送”。太好了,它可以为空。或者可以删除一个值以使其为空。因此,我们必须在 setter 中允许 null 作为参数。 getter 必须能够返回 null

/**
 * @return null|User
 */
public function getBcc() : ? User
{
    return $this->bcc;
}

/**
 * @param null|User $bcc
 *
 * @return Mail
 */
public function setBcc( ? User $to) : Mail
{
    $this->bcc = $bcc;

    return $this;
}

完成。 2个问号就够了。

还可以查看this question & answersPHP 7.2 "new features" 发行说明。

【讨论】:

  • 允许参数为空对我来说似乎很棘手,除非它们“可以”像您的示例中那样为空。我们的问题是我们的开发人员不小心在他们应该检查它或抛出异常或 w/e 的地方传递了 null。正如我在另一个答案中所说的那样,单元测试对我来说似乎很棒,因为没有它们我通常不会工作,但在这个特定的项目中它有点难。 Codacy 是我必须研究的东西,如果它阻止我们提交或保存根据 Codacy 无效的代码,那肯定是我想要使用的东西。
猜你喜欢
  • 2013-11-24
  • 1970-01-01
  • 2020-06-02
  • 2014-07-01
  • 1970-01-01
  • 2011-01-28
  • 1970-01-01
  • 1970-01-01
  • 2022-12-14
相关资源
最近更新 更多