PHP 8.1 升级后,DateTime 字段为何频频报错?
2024-07-15 12:48:12
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;
}
这段代码的逻辑清晰易懂:
- 首先,检查
$this->starttime
是否为 null。如果是,则直接返回 null,符合类型声明。 - 如果
$this->starttime
不是 null,则进一步判断它是否为数字类型。 - 如果是数字类型,则使用
DateTime('@' . $this->starttime)
将其转换为DateTime
对象。 - 最后,返回
$this->starttime
,此时它要么是DateTime
对象,要么是 null,完全符合类型声明的要求。
通过这样的修改,你的 getStarttime()
方法就能优雅地处理数据库返回值为 0 的情况,避免 "Call to a member function getStarttime() on null" 错误的出现。
常见问题解答
-
为什么升级到 PHP 8.1 后会出现这个错误?
- 因为 PHP 8.1 对类型声明的处理更加严格,要求返回值必须与声明的类型完全一致。
-
除了修改代码,还有其他解决方法吗?
- 可以尝试修改数据库字段类型,将
int
类型改为datetime
类型,但这可能会导致其他兼容性问题。
- 可以尝试修改数据库字段类型,将
-
这个错误只会在 TYPO3 中出现吗?
- 不一定,任何使用 DateTime 字段并依赖 PHP 类型声明的代码都可能出现这个错误。
-
如何避免类似的兼容性问题?
- 在升级 PHP 版本之前,仔细阅读官方文档,了解新版本引入的 breaking changes,并进行充分的测试。
-
还有其他与 DateTime 类型相关的常见错误吗?
- 常见的还有 "Trying to access property 'format' of non-object",通常是因为没有对 DateTime 对象进行 null 判断导致的,可以通过类似上述代码的逻辑进行修复。