【问题标题】:Symfony 2 many to one cannot nullSymfony 2 多对一不能为空
【发布时间】:2014-05-20 22:08:00
【问题描述】:

我有:

    An exception occurred while executing 'INSERT INTO image (image_name, artiste_id) VALUES (?, ?)' with params ["537bd9df69db9.png", null]:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'artiste_id' cannot be null

我与公司的“形象”和“艺术家”是多对一的关系。我真的不明白问题出在哪里。

我的实体图片:

 <?php

namespace Acme\ArtisteBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;

use Acme\ArtisteBundle\Entity\Artiste;

/**
 * Acme\ArtisteBundle\Entity\Image
 *
 * @ORM\Table(name="image")
 * @ORM\Entity(repositoryClass="Acme\ArtisteBundle\Entity\ImageRepository")
 * @ORM\HasLifecycleCallbacks
 * @Vich\Uploadable
 */
class Image
{
    /**
     * @var integer $id
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @Assert\File(
     *     maxSize="1M",
     *     mimeTypes={"image/png", "image/jpeg", "image/pjpeg"}
     * )
     * @Vich\UploadableField(mapping="product_image", fileNameProperty="imageName")
     *
     * @var File $image
     */
    public $image;

    /**
     * @var string $imageName
     * @ORM\Column(type="string", length=255, name="image_name", type="integer", nullable=false)
     */
    protected $imageName;

    /**
     * @ORM\ManyToOne(targetEntity="Acme\ArtisteBundle\Entity\Artiste", inversedBy="image", cascade={"remove"})
     * @ORM\JoinColumn(name="artiste_id", referencedColumnName="id", nullable=false)
     */
    private $artiste;

    /**
    * Set artiste
    *
    * @param \Acme\ArtisteBundle\Entity\Artiste $artiste
    */
    public function setArtiste(\Acme\ArtisteBundle\Entity\Artiste $artiste)
    {
        $this->artiste = $artiste;
    }

    /**
    * Get artiste
    *
    * @return \Acme\ArtisteBundle\Entity\Artiste
    */
    public function getArtiste()
    {
        return $this->artiste;
    }

     /** 
     * @param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
     */
    public function setImage(File $image)
    {
        $this->image = $image;
    }

    /**
     * Get Image
     * @return File
     */
    public function getImage()
    {
        return $this->image;
    }

    /**
     * @param string $imageName
     */
    public function setImageName($imageName)
    {
        $this->imageName = $imageName;
    }

    /**
     * @return string
     */
    public function getImageName()
    {
        return $this->imageName;
    }
}

和我的实体艺人

    <?php

namespace Acme\ArtisteBundle\Entity;

use FOS\UserBundle\Entity\User as BaseUser;
use Acme\ArtisteBundle\Entity\Image;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use Vich\UploaderBundle\Mapping\Annotation as Vich;

/**
 * Artiste
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="Acme\ArtisteBundle\Entity\ArtisteRepository")
 * @ORM\HasLifecycleCallbacks()
 */
class Artiste extends BaseUser
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var string
     *
     * @ORM\Column(name="valideAdmin", type="boolean", nullable=true)
     */
    private $valideAdmin = '0';

    /**
     * @ORM\OneToMany(targetEntity="Acme\ArtisteBundle\Entity\Image", mappedBy="artiste", cascade={"persist", "remove"})
     */
    protected $image;

    public function __construct()
    {
        trigger_error(sprintf('%s is deprecated. Extend FOS\UserBundle\Model\User directly.', __CLASS__), E_USER_DEPRECATED);
        parent::__construct();

        $this->image = new \Doctrine\Common\Collections\ArrayCollection();
    }

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

    /**
     * Set image
     *
     * @param \Doctrine\Common\Collections\Collection $image
     */
    public function setImage(\Doctrine\Common\Collections\Collection $image)
    {
        $this->image = $image;
    }

    /**
     * Add image
     *
     * @param \Acme\ArtisteBundle\Entity\Image $image
     */
    public function addImage(\Acme\ArtisteBundle\Entity\Image $image)
    {
        $this->image[] = $image;
    }

    /**
     * Remove image
     *
     * @param \Acme\ArtisteBundle\Entity\Artiste $image
     */
    public function removeImage(\Acme\ArtisteBundle\Entity\Artiste $image)
    {
        $this->image->removeElement($image);
    }
}

以及我对 FOS 的注册操作

namespace Unikness\ArtisteBundle\Controller;

use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\Event\UserEvent;
use FOS\UserBundle\Event\FilterUserResponseEvent;

use Symfony\Component\DependencyInjection\ContainerAware;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use FOS\UserBundle\Model\UserInterface;

use Acme\ArtisteBundle\Entity\Image;

use FOS\UserBundle\Controller\RegistrationController as BaseController;

class RegistrationController extends ContainerAware
{
    public function registerAction(Request $request)
    {
        /** @var $formFactory \FOS\UserBundle\Form\Factory\FactoryInterface */
        $formFactory = $this->container->get('fos_user.registration.form.factory');
        /** @var $userManager \FOS\UserBundle\Model\UserManagerInterface */
        $userManager = $this->container->get('fos_user.user_manager');
        /** @var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface */
        $dispatcher = $this->container->get('event_dispatcher');

        $user = $userManager->createUser();
        $user->setEnabled(true);

        $event = new GetResponseUserEvent($user, $request);
        $dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);

        if (null !== $event->getResponse()) {
            return $event->getResponse();
        }

        $form = $formFactory->createForm();
        $form->setData($user);

        $image = new Image();

        if ('POST' === $request->getMethod()) {
            $form->bind($request);

            if ($form->isValid()) {
                $event = new FormEvent($form, $request);
                $dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);

                $userManager->updateUser($user);
                $image->setArtiste($user);
                $em = $this->container->get('doctrine')->getEntityManager();
                $em->persist($image);
                $em->flush();

                if (null === $response = $event->getResponse()) {
                    $url = $this->container->get('router')->generate('fos_user_registration_confirmed');
                    $response = new RedirectResponse($url);
                }

                $dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));

                return $response;
            }
        }

        return $this->container->get('templating')->renderResponse('FOSUserBundle:Registration:register.html.'.$this->getEngine(), array(
            'form' => $form->createView(),
        ));
    }

我一直坚持,但我总是为空。任何帮助将不胜感激:)

【问题讨论】:

  • 并且在您的 registerAction 中,如果您在 "$userManager->updateUser($user);" 行之前执行此操作会发生什么情况--> $user->addImage($image);然后你可以删除行“$image->setArtiste($user);”以及持久化 $image 的行,因为在 Artiste 类中的 OneToMany 关系上存在级联持久化。它会改变什么吗?

标签: symfony doctrine-orm persist


【解决方案1】:

尝试在 ManyToOne 注释中添加“persist”选项

/**
 * @ORM\ManyToOne(targetEntity="Acme\ArtisteBundle\Entity\Artiste", inversedBy="image", cascade={"remove","persist"})
 * @ORM\JoinColumn(name="artiste_id", referencedColumnName="id", nullable=false)
 */
private $artiste;

【讨论】:

  • 您能否显示完整的错误消息以及负责保存实体的操作方法?
【解决方案2】:

为了确保双向关系有一个技巧:

在您的 Artiste 类中,像这样修改您的设置器 setImage:

public function setImage(\Doctrine\Common\Collections\Collection $image)
{
    foreach ($image as $img) {
        $img->setArtiste($this);
    }
    $this->image = $image;
}

此外,为了更好地阅读您的代码,我建议您将 Artiste 类中的“图像”字段重命名为“图像”,因为该字段是图像实体的集合。

我还在这篇文章doctrine2: in a one-to-many bidirectional relationship, how to save from the inverse side? 中读到,您可以这样做(选择这两种解决方案,如果您创建图像,则第二种解决方案很有趣,然后将 Artiste 附加到创建的图像 = "从反面保存边”):

在你的类 Image 中像这样修改设置器 setArtiste:

public function setArtiste($artiste)
{
    $this->artiste = $artiste;  
    $artiste->addImage($this);
}

【讨论】:

  • 我刚刚编辑了我的帖子,您可以尝试第二种解决方案吗?总是没有变化?
【解决方案3】:

这应该可以工作

public function addImage(\Acme\ArtisteBundle\Entity\Image $image)
{
    if(!$this->image->contains($image)){
        $this->image[] = $image;
        $image->setArtiste($this);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-04
    相关资源
    最近更新 更多