当上传我的文件的表单嵌入另一个表单时,似乎不会触发我的生命周期回调 . 如果上载表单是独立的,则会触发生命周期回调 .

我有一个创建“用户”实体的表单,对于这个用户,我与具有生命周期回调的'ProfilePicture'实体有一对一的关系,我想在同一表单上上传profilepicture文件 . 我按照“如何处理文件上传”的教程,但没有解释如何处理嵌入式表格 .

UserType

<?php
namespace CashBack\AdminBundle\Form\Type;

use CashBack\DefaultBundle\Entity\ProfilePicture;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        /* additional fields that should not be saved in this object need ->add('agreeWithTerms', null,array('mapped' => false))*/
        $builder
            ->add('id','hidden',array('mapped' => false))
            ->add('username')
            ->add('password')
            ->add('firstname')
            ->add('lastname')
            ->add('email')
            ->add('gender')
            ->add('dateOfBirth','birthday')
            ->add('customrole')
            ->add('profilepicture', new ProfilePictureType())
            ->add('save', 'submit');

    }
       /* Identifier */
    public function getName()
    {
        return 'User';
    }
    /* Makes sure the form doesn't need to guess the date type */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'CashBack\DefaultBundle\Entity\User',
            'cascade_validation' => true,

        ));
    }
}

ProfilePictureType

<?php
namespace CashBack\AdminBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class ProfilePictureType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        /* additional fields that should not be saved in this object need ->add('agreeWithTerms', null,array('mapped' => false))*/
        $builder
            ->add('id','hidden',array('mapped' => false))
            ->add('file','file');


    }
    /* Identifier */
    public function getName()
    {
        return 'ProfilePicture';
    }
    /* Makes sure the form doesn't need to guess the date type */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'CashBack\DefaultBundle\Entity\ProfilePicture',
        ));
    }
}

ProfilePicture Entity

<?php
namespace CashBack\DefaultBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\UploadedFile;

/**
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks
 */
class ProfilePicture
{
    /**
     * @var integer
     *
     * @ORM\Column(name="Id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;


    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $path;

    public function getAbsolutePath()
    {
        return null === $this->path
            ? null
            : $this->getUploadRootDir() . '/' . $this->path;
    }

    public function getWebPath()
    {
        return null === $this->path
            ? null
            : $this->getUploadDir() . '/' . $this->path;
    }

    protected function getUploadRootDir()
    {
        // the absolute directory path where uploaded
        // documents should be saved
        return __DIR__ . '/../../../../web/' . $this->getUploadDir();
    }

    protected function getUploadDir()
    {
        // get rid of the __DIR__ so it doesn't screw up
        // when displaying uploaded doc/image in the view.
        return 'uploads/documents';
    }

    /**
     * @Assert\File(maxSize="6000000")
     */
    private $file;

    private $temp;

    /**
     * Sets file.
     *
     * @param UploadedFile $file
     */
    public function setFile(UploadedFile $file = null)
    {
        $this->file = $file;
        // check if we have an old image path
        if (isset($this->path)) {
            // store the old name to delete after the update
            $this->temp = $this->path;
            $this->path = null;
        } else {
            $this->path = 'initial';
        }
    }

    /**
     * @ORM\PrePersist()
     * @ORM\PreUpdate()
     */
    public function preUpload()
    {
        if (null !== $this->getFile()) {
            // do whatever you want to generate a unique name
            $filename   = sha1(uniqid(mt_rand(), true));
            $this->path = $filename . '.' . $this->getFile()->guessExtension();
        }
    }

    /**
     * @ORM\PostPersist()
     * @ORM\PostUpdate()
     */
    public function upload()
    {
        if (null === $this->getFile()) {
            return;
        }

        // if there is an error when moving the file, an exception will
        // be automatically thrown by move(). This will properly prevent
        // the entity from being persisted to the database on error
        $this->getFile()->move($this->getUploadRootDir(), $this->path);

        // check if we have an old image
        if (isset($this->temp)) {
            // delete the old image
            unlink($this->getUploadRootDir() . '/' . $this->temp);
            // clear the temp image path
            $this->temp = null;
        }
        $this->file = null;
    }

    /**
     * @ORM\PostRemove()
     */
    public function removeUpload()
    {
        if ($file = $this->getAbsolutePath()) {
            unlink($file);
        }
    }

    /**
     * Get file.
     *
     * @return UploadedFile
     */
    public function getFile()
    {
        return $this->file;
    }

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }


    /**
     * Set path
     *
     * @param string $path
     *
     * @return ProfilePicture
     */
    public function setPath($path)
    {
        $this->path = $path;

        return $this;
    }

    /**
     * Get path
     *
     * @return string
     */
    public function getPath()
    {
        return $this->path;
    }

    /**
     * @ORM\OneToOne(targetEntity="User", inversedBy="profilepicture")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="Id")
     */
    protected $user;

    /**
     * Set user
     *
     * @param \CashBack\DefaultBundle\Entity\User $user
     *
     * @return ProfilePicture
     */
    public function setUser(\CashBack\DefaultBundle\Entity\User $user = null)
    {
        $this->user = $user;

        return $this;
    }

    /**
     * Get user
     *
     * @return \CashBack\DefaultBundle\Entity\User
     */
    public function getUser()
    {
        return $this->user;
    }

}

User Entity

<?php
namespace CashBack\DefaultBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * User
 *
 * @ORM\Table(name="user")
 * @ORM\Entity
 */
class User
{
    /**
     * @var string
     *
     * @ORM\Column(name="FirstName", type="string", length=10, nullable=true)
     */
    private $firstname;

    /**
     * @var string
     *
     * @ORM\Column(name="LastName", type="string", length=20, nullable=true)
     */
    private $lastname;

    /**
     * @var string
     *
     * @ORM\Column(name="Gender", type="string", length=1, nullable=true)
     */
    private $gender;

    /**
     * @var string
     *
     * @ORM\Column(name="Email", type="string", length=50, nullable=false)
     */
    private $email;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="DateOfBirth", type="date", nullable=false)
     */
    private $dateofbirth;

    /**
     * @var string
     *
     * @ORM\Column(name="Username", type="string", length=50, nullable=false)
     */
    private $username;

    /**
     * @var string
     *
     * @ORM\Column(name="Password", type="string", length=100, nullable=false)
     */
    private $password;

    /**
     * @var integer
     *
     * @ORM\Column(name="Id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\ManyToMany(targetEntity="CashBack\DefaultBundle\Entity\Tag", inversedBy="user")
     * @ORM\JoinTable(name="user_tag",
     *   joinColumns={
     * @ORM\JoinColumn(name="user_id", referencedColumnName="Id")
     *   },
     *   inverseJoinColumns={
     * @ORM\JoinColumn(name="tag_id", referencedColumnName="Id")
     *   }
     * )
     */
    private $tag;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\ManyToMany(targetEntity="CashBack\DefaultBundle\Entity\Customrole", inversedBy="user")
     * @ORM\JoinTable(name="user_customrole",
     *   joinColumns={
     * @ORM\JoinColumn(name="user_id", referencedColumnName="Id")
     *   },
     *   inverseJoinColumns={
     * @ORM\JoinColumn(name="customrole_id", referencedColumnName="Id")
     *   }
     * )
     */
    private $customrole;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\ManyToMany(targetEntity="CashBack\DefaultBundle\Entity\Shop", inversedBy="user")
     * @ORM\JoinTable(name="user_shop",
     *   joinColumns={
     * @ORM\JoinColumn(name="user_id", referencedColumnName="Id")
     *   },
     *   inverseJoinColumns={
     * @ORM\JoinColumn(name="shop_id", referencedColumnName="Id")
     *   }
     * )
     */
    private $shop;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->tag        = new \Doctrine\Common\Collections\ArrayCollection();
        $this->customrole = new \Doctrine\Common\Collections\ArrayCollection();
        $this->shop       = new \Doctrine\Common\Collections\ArrayCollection();
    }


    /**
     * Set firstname
     *
     * @param string $firstname
     *
     * @return User
     */
    public function setFirstname($firstname)
    {
        $this->firstname = $firstname;

        return $this;
    }

    /**
     * Get firstname
     *
     * @return string
     */
    public function getFirstname()
    {
        return $this->firstname;
    }

    /**
     * Set lastname
     *
     * @param string $lastname
     *
     * @return User
     */
    public function setLastname($lastname)
    {
        $this->lastname = $lastname;

        return $this;
    }

    /**
     * Get lastname
     *
     * @return string
     */
    public function getLastname()
    {
        return $this->lastname;
    }

    /**
     * Set gender
     *
     * @param string $gender
     *
     * @return User
     */
    public function setGender($gender)
    {
        $this->gender = $gender;

        return $this;
    }

    /**
     * Get gender
     *
     * @return string
     */
    public function getGender()
    {
        return $this->gender;
    }

    /**
     * Set email
     *
     * @param string $email
     *
     * @return User
     */
    public function setEmail($email)
    {
        $this->email = $email;

        return $this;
    }

    /**
     * Get email
     *
     * @return string
     */
    public function getEmail()
    {
        return $this->email;
    }

    /**
     * Set dateofbirth
     *
     * @param \DateTime $dateofbirth
     *
     * @return User
     */
    public function setDateofbirth($dateofbirth)
    {
        $this->dateofbirth = $dateofbirth;

        return $this;
    }

    /**
     * Get dateofbirth
     *
     * @return \DateTime
     */
    public function getDateofbirth()
    {
        return $this->dateofbirth;
    }

    /**
     * Set username
     *
     * @param string $username
     *
     * @return User
     */
    public function setUsername($username)
    {
        $this->username = $username;

        return $this;
    }

    /**
     * Get username
     *
     * @return string
     */
    public function getUsername()
    {
        return $this->username;
    }

    /**
     * Set password
     *
     * @param string $password
     *
     * @return User
     */
    public function setPassword($password)
    {
        $this->password = $password;

        return $this;
    }

    /**
     * Get password
     *
     * @return string
     */
    public function getPassword()
    {
        return $this->password;
    }

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Add tag
     *
     * @param \CashBack\DefaultBundle\Entity\Tag $tag
     *
     * @return User
     */
    public function addTag(\CashBack\DefaultBundle\Entity\Tag $tag)
    {
        $this->tag[] = $tag;

        return $this;
    }

    /**
     * Remove tag
     *
     * @param \CashBack\DefaultBundle\Entity\Tag $tag
     */
    public function removeTag(\CashBack\DefaultBundle\Entity\Tag $tag)
    {
        $this->tag->removeElement($tag);
    }

    /**
     * Get tag
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getTag()
    {
        return $this->tag;
    }

    /**
     * Add customrole
     *
     * @param \CashBack\DefaultBundle\Entity\Customrole $customrole
     *
     * @return User
     */
    public function addCustomrole(\CashBack\DefaultBundle\Entity\Customrole $customrole)
    {
        $this->customrole[] = $customrole;

        return $this;
    }

    /**
     * Remove customrole
     *
     * @param \CashBack\DefaultBundle\Entity\Customrole $customrole
     */
    public function removeCustomrole(\CashBack\DefaultBundle\Entity\Customrole $customrole)
    {
        $this->customrole->removeElement($customrole);
    }

    /**
     * Get customrole
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getCustomrole()
    {
        return $this->customrole;
    }

    /**
     * Add shop
     *
     * @param \CashBack\DefaultBundle\Entity\Shop $shop
     *
     * @return User
     */
    public function addShop(\CashBack\DefaultBundle\Entity\Shop $shop)
    {
        $this->shop[] = $shop;

        return $this;
    }

    /**
     * Remove shop
     *
     * @param \CashBack\DefaultBundle\Entity\Shop $shop
     */
    public function removeShop(\CashBack\DefaultBundle\Entity\Shop $shop)
    {
        $this->shop->removeElement($shop);
    }

    /**
     * Get shop
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getShop()
    {
        return $this->shop;
    }

    /** @ORM\OneToOne(targetEntity="ProfilePicture", mappedBy="user", cascade={"persist", "all"}) */
    protected $profilepicture;


    /**
     * Set profilepicture
     *
     * @param \CashBack\DefaultBundle\Entity\ProfilePicture $profilepicture
     *
     * @return User
     */
    public function setProfilepicture(\CashBack\DefaultBundle\Entity\ProfilePicture $profilepicture)
    {
        $this->profilepicture = $profilepicture;
        $profilepicture->setUser($this);
        return $this;
    }

    /**
     * Get profilepicture
     *
     * @return \CashBack\DefaultBundle\Entity\ProfilePicture
     */
    public function getProfilepicture()
    {
        return $this->profilepicture;
    }

}

User controller

//adds a new entity from data received via Ajax, no redirect
        public function addAjaxAction(Request $request)
        {

            $user = new User();

            $form = $this->createForm(new UserType(), $user);
            $form->handleRequest($request);
            $user = $form->getData();

            $em = $this->getDoctrine()->getManager();
            $em->persist($user);
            $em->flush();

            //prepare the response, e.g.
            $response = array("code" => 100, "success" => true);
            //you can return result as JSON  , remember to 'use' Response!
            return new Response(json_encode($response));

        }

编辑:当检查分析器时,我看到在表单中提交了以下对象:如果我检查分析器,我看到以下形式提交的对象:{“username”:“test”,“password”:“test” , “名字”: “测试”, “姓氏”: “测试”, “电子邮件”: “测试”, “性别”: “T”, “出生日期”:{ “月”: “1”, “天”: “1”, “年”: “1902”}, “customrole”:[ “2”], “ID”: “”, “profilepicture”:{ “ID”: “”}, “_标记”: “YUDiZLi8dY6jtmEhZWk6ivnH3vsQIpnM_fxQ3ClJ2Gw” }

Profiles 图片因此是空的 .