使用Doctrine存日期出现Call to a member function format() on string错误如何解决
报错根本原因
你定义的@ORM\Column(type="date")要求实体的startDate属性必须是\DateTimeInterface实例,Doctrine在持久化数据到数据库时,会自动调用该对象的format()方法转为数据库支持的日期字符串格式。你当前直接传入拼接好的字符串,字符串没有format()方法,就触发了该报错。另外你现有Setter的参数标注为integer属于完全错误的类型定义,也需要同步修正。
修复步骤
1. 修正实体字段及Getter/Setter定义
首先调整startDate字段的类型声明和注解,如果你业务允许用NULL代替不规范的0000-00-00(更符合SQL标准,避免后续日期计算的坑),可以直接将字段设为可空:
/** * @ORM\Column(type="date", nullable=true) */ protected ?\DateTimeInterface $startDate = null; /** * Set startDate * * @param \DateTimeInterface|null $startDate * @return Campaign */ public function setStartDate(?\DateTimeInterface $startDate): self { $this->startDate = $startDate; return $this; } /** * Get startDate * * @return \DateTimeInterface|null */ public function getStartDate(): ?\DateTimeInterface { return $this->startDate; }
2. 修正表单赋值逻辑
不要用explode拼接字符串的方式处理日期,改用DateTime::createFromFormat直接解析德语格式的日期,既可以自动校验日期合法性,也能直接得到需要的DateTime实例:
if (!empty($formData["startDate"])) { $startDate = \DateTime::createFromFormat('d.m.Y', $formData["startDate"]); // 校验日期格式是否合法 if ($startDate) { $campaign->setStartDate($startDate); } else { // 日期格式错误时的处理逻辑,比如抛出表单校验错误 $campaign->setStartDate(null); } } else { $campaign->setStartDate(null); }
Doctrine会自动将DateTime实例转为Y-m-d格式的字符串存入数据库,空值会存为NULL。
特殊情况:必须保留0000-00-00存储逻辑
如果你的旧业务逻辑强依赖数据库存0000-00-00而不能用NULL,需要自定义Doctrine的日期映射类型,兼容0000-00-00的转换:
第一步:创建自定义日期类型
use Doctrine\DBAL\Types\DateType; use Doctrine\DBAL\Platforms\AbstractPlatform; class ZeroCompatibleDateType extends DateType { // 数据库值转PHP值 public function convertToPHPValue($value, AbstractPlatform $platform) { if ($value === '0000-00-00') { return null; } return parent::convertToPHPValue($value, $platform); } // PHP值转数据库值 public function convertToDatabaseValue($value, AbstractPlatform $platform) { if ($value === null) { return '0000-00-00'; } return parent::convertToDatabaseValue($value, $platform); } }
第二步:注册自定义类型
在Doctrine配置中注册该类型,替换默认的date类型,或者新增为独立类型:
# 以Symfony框架的yaml配置为例 doctrine: dbal: types: date: App\Doctrine\Type\ZeroCompatibleDateType
完成配置后,空值传入Setter时,会自动转为0000-00-00存入数据库。
内容的提问来源于stack exchange,提问作者lxg95
相关产品推荐
相关产品推荐

