我有这个实体:
AppBundle\Entity\Ciudad
class Ciudad{
...
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\ComunidadAutonoma")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="id_ccaa", referencedColumnName="id")
* })
*/
private $ccaa;
....
public function getCcaa()
{
return $this->ccaa;
}
public function setCcaa(ComunidadAutonoma $ccaa)
{
$this->ccaa = $ccaa;
}
}
另一个实体是:
AppBundle\Entity\ComunidadAutonoma
class ComunidadAutonoma{
properties
getters
setters
}
在控制器中,我从表单中获取数据,并试图将数据反序列化为Ciudad
实体,但始终使我遇到相同的错误:
Expected argument of type "AppBundle\Entity\ComunidadAutonoma", "integer" given
在我发送给控制器中动作的表单数据中,comunidadautonoma的值是组合中所选选项的ID:
{
parameters...
ccaa:7,
parameters...
}
在我的控制器中,我有这个:
<?php
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use AppBundle\Entity\Ciudad;
class CiudadController extends Controller
{
public function procesarAction(Request $request)
{
$encoders = array(new XmlEncoder(), new JsonEncoder());
$normalizers = array(new ObjectNormalizer());
$this->serializer = new Serializer($normalizers, $encoders);
$ciudad= $this->serializer->deserialize($parametros['parametros'], Ciudad::class, 'json');
}
}
我缺少什么吗?我需要任何特殊的配置来反序列化具有关系的实体吗?
答案 0 :(得分:0)
如果正确配置了类型,则无需执行任何操作。为您的实体创建表单类型时,请将类名添加到您的类型中,例如:
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Ciudad::class,
]);
}
请在项目中使用英文命名。
答案 1 :(得分:0)
首先,由于您要向控制器发送表单数据,因此可以使用“表单类型”类来利用Symfony表单组件的全部功能来为您完成所有工作。
回答您的特定问题(并假设您不能/不希望使用Symfony Form Component),绝对会出现此错误。正如您在setCcaa
类中的Ciudad
函数声明中所看到的:
public function setCcaa(ComunidadAutonoma $ccaa)
由于类型提示(ComunidadAutonoma $ccaa
)setCcaa
函数需要类型为ComunidadAutonoma
的参数。现在,当Symfony序列化程序尝试对您的json对象进行非规范化时,它将使用参数json中提供的ccaa值(在您的示例中为7)调用setCcaa
函数,该值恰好是整数。因此,Symfony抱怨您提供的是整数而不是ComunidadAutonoma
类型。
为了解决此问题,您必须创建并使用自己的normalizer,以便可以将此整数转换为数据库中的相应实体对象。像这样:
class EntityNormalizer extends ObjectNormalizer
{
/**
* Entity manager
* @var EntityManagerInterface
*/
protected $em;
public function __construct(
EntityManagerInterface $em,
?ClassMetadataFactoryInterface $classMetadataFactory = null,
?NameConverterInterface $nameConverter = null,
?PropertyAccessorInterface $propertyAccessor = null,
?PropertyTypeExtractorInterface $propertyTypeExtractor = null
) {
parent::__construct($classMetadataFactory, $nameConverter, $propertyAccessor, $propertyTypeExtractor);
// Entity manager
$this->em = $em;
}
public function supportsDenormalization($data, $type, $format = null)
{
return strpos($type, 'App\\Entity\\') === 0 && (is_numeric($data) || is_string($data));
}
public function denormalize($data, $class, $format = null, array $context = [])
{
return $this->em->find($class, $data);
}
}
此规范化器的作用是检查您的数据类型(在本例中为$ ccaa)是否为实体类型,并且所提供的数据值(在本例中为7)是否为整数,则将该整数转换为相应的整数。数据库中的实体对象(如果存在)。
要使此规范化器正常工作,您还应该在services.yaml配置中注册它,并使用适当的标签,如下所示:
services:
App\Normalizer\EntityNormalizer:
public: false
autowire: true
autoconfigure: true
tags:
- { name: serializer.normalizer }
您还可以设置规范化器的优先级,但是由于当Symfony的内置规范化器的优先级默认为负时,默认优先级值等于0,因此将首先使用规范化器。
您可以在article中查看有关此问题的完整说明示例。