调用Doctrine flush保存X实体时遇UUID类型转换错误,Stringable未被识别
Doctrine flush时Stringable UUID类类型转换错误的解决方法
调用Doctrine的flush()保存X实体时触发类型转换错误:
Could not convert PHP value of type X to type uuid. Expected one of the following types: null, string, Symfony\Component\Uid\AbstractUid
相关代码:
final class X extends MyUuid { }
abstract class MyUuid implements \Stringable { final public function __construct(protected string $value) { } public function __toString(): string { return $this->value; } }
问题原因
Doctrine的UUID类型转换器只会检查变量的实际类型是否匹配(null/string/AbstractUid实例),不会自动调用__toString()将Stringable对象转换为字符串。你的X类实例的类型是X,不是string,因此触发类型检查失败。
解决方案
方案1:自定义Doctrine类型
创建专门的Doctrine类型来处理你的MyUuid/X类,让Doctrine明确如何在PHP对象和数据库值之间转换:
- 实现自定义类型类:
use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Platforms\AbstractPlatform; class MyUuidType extends Type { public const NAME = 'my_uuid'; public function getSQLDeclaration(array $column, AbstractPlatform $platform): string { // 复用数据库原生UUID类型的声明 return $platform->getGuidTypeDeclarationSQL($column); } public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string { if ($value instanceof MyUuid) { return (string) $value; } return $value; } public function convertToPHPValue($value, AbstractPlatform $platform): ?MyUuid { if (is_string($value) && !empty($value)) { return new X($value); } return null; } public function getName(): string { return self::NAME; } public function requiresSQLCommentHint(AbstractPlatform $platform): bool { return true; } }
- 注册自定义类型(以Symfony为例,修改
config/packages/doctrine.yaml):
doctrine: dbal: types: my_uuid: App\Doctrine\Type\MyUuidType
- 在实体中使用该类型:
use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity */ class YourEntity { /** * @ORM\Column(type="my_uuid") */ private X $uuid; }
方案2:使用转换回调
在实体映射中添加转换回调,手动实现PHP对象与数据库值的转换:
use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity */ class YourEntity { /** * @ORM\Column(type="uuid") * @ORM\ConvertToDatabaseValue(callback="static::convertXToUuidString") * @ORM\ConvertToPHPValue(callback="static::convertUuidStringToX") */ private X $uuid; public static function convertXToUuidString(X $value): string { return (string) $value; } public static function convertUuidStringToX(string $value): X { return new X($value); } }
方案3:继承Symfony的AbstractUid
如果可以修改基类,让MyUuid继承Symfony\Component\Uid\AbstractUid,直接符合Doctrine UUID类型的要求:
abstract class MyUuid extends \Symfony\Component\Uid\AbstractUid { public function __construct(string $value) { parent::__construct($value); } }
这样X类作为AbstractUid的子类,实例会被Doctrine自动识别,无需额外转换。
内容的提问来源于stack exchange,提问作者Carlos 2V
相关产品推荐
相关产品推荐

