嵌入的表单实体不会保留

时间:2015-06-12 12:21:37

标签: symfony

Symfony 2.6.9

我的UserProfile实体具有avatar属性,与oneToOne实体和级联持久性具有UserAvatar单向关系。

BlogBundle\Entity\UserProfile:
    type: entity
    table: user_profiles
    id:
        id:
            type: integer
            generator:
                strategy: AUTO
    fields:
        #...
    oneToOne:
        #...
        avatar:
            targetEntity: UserAvatar
            cascade: ['persist', 'remove']

我创建了UserProfile表单类型,其中包含嵌入的头像表单字段:

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            #...
            ->add('avatar', new UserAvatarType, [
                'required' => false,
            ])
            ->add('submit', 'submit', [
                'attr' => [
                    'class' => 'right'
                ]
            ])
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'BlogBundle\Entity\UserProfile',
            'cascade_validation' => true,
        ));
    }

    public function getName()
    {
        return 'userProfile';
    }
}

UserAvatarType

class UserAvatarType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('file', 'file', [
                'label' => false
            ])
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'BlogBundle\Entity\UserAvatar',
        ));
    }

    public function getName()
    {
        return 'userAvatar';
    }
}
我提交表单时已经存在

UserProfileUserAvatar个实体,它们是在用户注册持久性事件时自动创建的。我只是编辑个人资料实体。

当我提交表单时,UserProfile中的所有字段都会保留良好,但不会嵌入avatar字段。未调用setAvatar内的方法UserProfileUserAvatar上的验证通过良好。没有错误,UserAvatar实体没有持久存在。

Gist.

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:0)

我只能猜测,但是在控制器级别犯了一个非常常见的错误。确保你有类似的东西:

$profile = new UserProfile();
$avatar = new UserAvatar();
$profile->setAvatar($avatar);

$form = $this->createForm(new UserProfileType(), $profile)

然后像你一样处理你的表格。

希望这有帮助。

修改

鉴于注释中提供了intel,问题已完全识别:用户对象被延迟加载,Doctrine无法继续存在。我会做的是:

  • 在你的UserController中,在profileEditAction()中,当通过调用$user来定义findOneByUsername($username)时,你可以从UserRepository中调用你自己的方法(将它命名为你想要的任何东西,让&#39 ; s say findOneByUsernameCustom),我们将创建。
  • 转到UserRepository并创建此自定义方法。它应该是这样的:

    public function findOneByUsernameCustom(){
    
    $em = $this->getEntityManager();
    $qb = $em->createQueryBuilder();
    $qb
        ->select('User','firstUserProperty','secondUserProperty')
        ->from('AppBundle\Entity\User','User')
        ->leftJoin('User.firstUserProperty','fistUserProperty')
        ->leftJoin('User.secondUserProperty','secondUserProperty')
        ;
    $q = $qb->getQuery();
    return $q->getResult();}
    

Basicaly leftJoin用户的每个属性,以便当您从数据库中检索用户时,它将正确完成。

有关详细信息,请参阅此优秀article

答案 1 :(得分:0)

我最终发现了问题所在。

如果没有更改的映射字段,实体将不会保留。在我的情况下,我只更改文件字段,它是虚拟字段,而不是映射到数据库。

以下是文档中有关此问题的一些信息:

  

PreUpdatePostUpdate回调只有在其中一个实体的字段中存在持续变化时才会触发。这意味着,默认情况下,如果仅修改$file属性,则不会触发这些事件,因为属性本​​身不会通过Doctrine直接保留。一种解决方案是使用持久保存到Doctrine的更新字段,并在更改文件时手动修改它。

以下是我们如何解决它。我们可以创建一些虚拟字段,在setFile()调用时将更改:

<?php
public function setFile(UploadedFile $file)
{
    $this->file = $file;
    $this->createdAt = new \DateTime;
}
?>