返回

PHP 8.1 升级后,DateTime 字段为何频频报错?

php

PHP 8.1 升级后, DateTime 字段为何频频报错?

"Call to a member function getStarttime() on null" 这个错误信息是不是很熟悉?当你兴冲冲地将 PHP 从 7.4 升级到 8.1,却在 TYPO3 11.5.32 版本中遇到它时,是不是有点恼火?别急,这篇文章将为你揭开错误背后的真相,并提供清晰易懂的解决方案。

问题的关键在于你自定义扩展中的 DateTime 字段。你可能会疑惑,数据库明明存储的是 0,为什么调用 getStarttime() 方法时会提示 null 呢?

让我们深入代码内部一探究竟。在 PHP 8.1 中,类型声明的处理机制更加严格。当你使用 getStarttime(): ?DateTime 这样的代码时,PHP 8.1 会严格要求返回值必须是 DateTime 对象或 null。然而,数据库中用于表示时间的字段通常存储为整数类型,例如你的 starttime 字段类型可能是 int(11)

当数据库中的 starttime 字段值为 0 时,TYPO3 会将其解读为 null 并返回。而你的 getStarttime() 方法却没有考虑到这种情况,直接返回了 null,导致与类型声明冲突,错误就这样产生了。

如何解决?

想要解决这个问题,我们需要对 getStarttime() 方法进行一些调整,确保它的返回值始终符合类型声明的要求。

以下是修改后的 getStarttime() 方法代码:

/**
 * Get start time
 *
 * @return DateTime|null
 */
public function getStarttime(): ?DateTime
{
    if ($this->starttime === null) {
        return null;
    }

    if (is_numeric($this->starttime)) {
        $this->starttime = new DateTime('@' . $this->starttime);
    }

    return $this->starttime;
}

这段代码的逻辑清晰易懂:

  1. 首先,检查 $this->starttime 是否为 null。如果是,则直接返回 null,符合类型声明。
  2. 如果 $this->starttime 不是 null,则进一步判断它是否为数字类型。
  3. 如果是数字类型,则使用 DateTime('@' . $this->starttime) 将其转换为 DateTime 对象。
  4. 最后,返回 $this->starttime,此时它要么是 DateTime 对象,要么是 null,完全符合类型声明的要求。

通过这样的修改,你的 getStarttime() 方法就能优雅地处理数据库返回值为 0 的情况,避免 "Call to a member function getStarttime() on null" 错误的出现。

常见问题解答

  1. 为什么升级到 PHP 8.1 后会出现这个错误?

    • 因为 PHP 8.1 对类型声明的处理更加严格,要求返回值必须与声明的类型完全一致。
  2. 除了修改代码,还有其他解决方法吗?

    • 可以尝试修改数据库字段类型,将 int 类型改为 datetime 类型,但这可能会导致其他兼容性问题。
  3. 这个错误只会在 TYPO3 中出现吗?

    • 不一定,任何使用 DateTime 字段并依赖 PHP 类型声明的代码都可能出现这个错误。
  4. 如何避免类似的兼容性问题?

    • 在升级 PHP 版本之前,仔细阅读官方文档,了解新版本引入的 breaking changes,并进行充分的测试。
  5. 还有其他与 DateTime 类型相关的常见错误吗?

    • 常见的还有 "Trying to access property 'format' of non-object",通常是因为没有对 DateTime 对象进行 null 判断导致的,可以通过类似上述代码的逻辑进行修复。