一对一关系:在Symfony中复制user_id

时间:2017-04-23 18:12:58

标签: php symfony

我有一个具有一对一关系的2个实体。一个用户=一个购物车和一个购物车=一个用户。首先,当我尝试将产品添加到当前登录的用户包时没有问题,但是当我添加第二个产品时,它会抛出以下异常:

An exception occurred while executing 'INSERT INTO cart (name, price, image, user_id) VALUES (?, ?, ?, ?)' with params ["Olympus - TG-4", "379.99", "65d30071a19252f3361af3b2e134b0f4", 8]:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '8' for key 'UNIQ_BA388B7A76ED395'

这是用户实体:

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * User
 *
 * @ORM\Table(name="users")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
 */
class User implements UserInterface
{

    const ROLE_USER = 'ROLE_USER';
    const ROLE_EDITOR= 'ROLE_EDITOR';
    const ROLE_ADMIN=  'ROLE_ADMIN';

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

    /**
     * @Assert\Email(
     *     message = "The email '{{ value }}' is not a valid email."
     * )
     * @ORM\Column(name="email", type="string", length=255, unique=true)
     */
    private $email;

    /**
     * @Assert\Length(
     *     min = 4,
     *     max = 10,
     *     minMessage = "Your username must be at least {{ limit }} characters long.",
     *     maxMessage = "Your username cannot be longer than {{ limit }} characters."
     * )
     * @var string
     * @ORM\Column(name="username", type="string", length=255, unique=true)
     */
    private $username;

    /**
     * @Assert\Length(
     *     min = 4,
     *     max = 20,
     *     minMessage = "Your name must be at least {{ limit }} characters long.",
     *     maxMessage = "Your name cannot be longer than {{ limit }} characters."
     * )
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
    private $name;

    /**
     * @Assert\Length(
     *     min = 4,
     *     max = 10,
     *     minMessage = "Your password must be at least {{ limit }} characters long.",
     *     maxMessage = "Your password cannot be longer than {{ limit }} characters."
     * )
     * @var string
     *
     * @ORM\Column(name="password", type="string", length=255)
     */
    private $password;

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

    /**
     * @Assert\Image(mimeTypes={"image/png", "image/jpeg"}, maxSize="5M")
     */
    private $image_form;

    /**
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\Product", mappedBy="user")
     */
    private $products;

    /**
     * @ORM\Column(name="role", type="string", length=255)
     */
    private $role;

    /**
     * One user has One Cart
     * @ORM\OneToOne(targetEntity="AppBundle\Entity\Cart", mappedBy="user")
     */
    private $cart;

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

    /**
     * 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 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 name
     *
     * @param string $name
     *
     * @return User
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

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

    /**
     * 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;
    }

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

        return $this;
    }

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

    /**
     * @return mixed
     */
    public function getImageForm()
    {
        return $this->image_form;
    }

    /**
     * @param mixed $image_form
     */
    public function setImageForm($image_form)
    {
        $this->image_form = $image_form;
    }

    /**
     * Returns the roles granted to the user.
     *
     * <code>
     * public function getRoles()
     * {
     *     return array('ROLE_USER');
     * }
     * </code>
     *
     * Alternatively, the roles might be stored on a ``roles`` property,
     * and populated in any number of different ways when the user object
     * is created.
     *
     * @return (Role|string)[] The user roles
     */
    public function getRoles()
    {
        return explode(',', $this->getRole());
    }

    /**
     * Returns the salt that was originally used to encode the password.
     *
     * This can return null if the password was not encoded using a salt.
     *
     * @return string|null The salt
     */
    public function getSalt()
    {
        return null;
    }

    /**
     * Removes sensitive data from the user.
     *
     * This is important if, at any given point, sensitive information like
     * the plain-text password is stored on this object.
     */
    public function eraseCredentials()
    {
        return null;
    }

    public function getDefaultRole()
    {
        return self::ROLE_USER;
    }

    /**
     * @return mixed
     */
    public function getRole()
    {
        return $this->role;
    }

    /**
     * @param mixed $role
     */
    public function setRole($role)
    {
        $this->role = $role;
    }

    /**
     * @param array $roles
     */
    public function setRoles($roles){
        $this->setRole(implode(',', $roles));
    }

    /**
     * @return mixed
     */
    public function getProducts()
    {
        return $this->products;
    }

    /**
     * @param mixed $products
     */
    public function setProducts($products)
    {
        $this->products = $products;
    }

    /**
     * @return mixed
     */
    public function getCart()
    {
        return $this->cart;
    }

    /**
     * @param mixed $cart
     */
    public function setCart($cart)
    {
        $this->cart = $cart;
    }
}

这是购物车实体:

<?php

namespace AppBundle\Entity;

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

/**
 * Cart
 *
 * @ORM\Table(name="cart")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\CartRepository")
 */
class Cart
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
    private $name;

    /**
     * @var string
     *
     * @ORM\Column(name="price", type="string", length=255)
     */
    private $price;

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

    /**
     * @Assert\Image(mimeTypes={"image/png", "image/jpeg"}, maxSize="5M")
     */
    private $image_form;

    /**
     * One cart has One User
     * @ORM\OneToOne(targetEntity="AppBundle\Entity\User", inversedBy="cart")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
     */
    private $user;


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

    /**
     * Set name
     *
     * @param string $name
     *
     * @return Cart
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

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

    /**
     * Set price
     *
     * @param string $price
     *
     * @return Cart
     */
    public function setPrice($price)
    {
        $this->price = $price;

        return $this;
    }

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

    /**
     * Set image
     *
     * @param string $image
     *
     * @return Cart
     */
    public function setImage($image)
    {
        $this->image = $image;

        return $this;
    }

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

    /**
     * @return mixed
     */
    public function getImageForm()
    {
        return $this->image_form;
    }

    /**
     * @param mixed $image_form
     */
    public function setImageForm($image_form)
    {
        $this->image_form = $image_form;
    }

    /**
     * @return mixed
     */
    public function getUser()
    {
        return $this->user;
    }

    /**
     * @param mixed $user
     */
    public function setUser($user)
    {
        $this->user = $user;
    }
}

和推车控制器:

    <?php

namespace AppBundle\Controller;

use AppBundle\Entity\Cart;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\File\UploadedFile;


class CartController extends Controller
{
    /**
     * @Route("/cart/{id}", name="cart")
     * @param $id
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function listUserCartAction($id)
    {
        $cart = $this->getDoctrine()->getRepository('AppBundle:Cart')->findAll($id);

        return $this->render('cart/cart.view.html.twig', array(
            'cart' => $cart
        ));
    }

    /**
     * @Route("/cart/add/{id}", name="add_to_cart")
     * @return \Symfony\Component\HttpFoundation\Response
     * @internal param $id
     */
    public function addToCartAction($id)
    {
        $cart = new Cart();
        $product = $this->getDoctrine()->getRepository('AppBundle:Product')->find($id);

        $productName = $product->getName();
        $productPrice = $product->getPrice();

        /** @var UploadedFile $file */
        $filename = md5($product->getName());

        //Get Current User Id
        $user = $this->get('security.token_storage')->getToken()->getUser();

        $cart->setName($productName);
        $cart->setPrice($productPrice);
        $cart->setImage($filename);
        $cart->setUser($user);

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

         return $this->render('cart/cart.view.html.twig');
    }
}

2 个答案:

答案 0 :(得分:1)

您遇到的问题基于生成数据库模式,因为错误表明您在重复的密钥(user_id)上存在约束错误。

您必须更改UNIQUE INDEX,我认为您应该为INDEX更改它(user_id)

答案 1 :(得分:0)

这是因为你有一对一的双向关系。尝试从用户实体中删除以下代码

/**
 * One user has One Cart
 * @ORM\OneToOne(targetEntity="AppBundle\Entity\Cart", mappedBy="user")
 */
private $cart;

问题在于,对于特定用户,您要为添加的每个产品创建新购物车。相反,购物车应该只有id(主键)和user_id,并且应该有一个新表(cart_products),其中包含product_id到card_id的映射。