简体   繁体   中英

Cart feature with Doctrine

I'm trying to implement a Cart feature in my Symfony app. The purpose is to allow a User to add some events in a Cart.

So I have created 3 Entities. User , Event and Cart . A User need to access his Cart to get his events. Like $user->getCart , which will return an ArrayCollection of events.

I have no idea what is the best way to do it with the Doctrine relation. Everything I have tried does not seems to work.

Here is what I have made so far:

In my User Entity

/**
* @ORM\OneToOne(targetEntity="App\Entity\Cart", mappedBy="user", cascade={"persist", "remove"})
*/
private $cart;

public function getCart(): ?Cart
{
    return $this->cart;
}

public function setCart(Cart $cart): self
{
    $this->cart = $cart;

    // set the owning side of the relation if necessary
    if ($this !== $cart->getUser()) {
        $cart->setUser($this);
    }

    return $this;
}

In my User Entity

/**
* @ORM\OneToOne(targetEntity="App\Entity\User", inversedBy="cart", cascade={"persist", "remove"})
* @ORM\JoinColumn(nullable=false)
*/
private $user;

I have stopped here, because I feel like I'm not doing the right approach.

May I have your feeling about it?

Although I haven't tested it myself, it will highly likely work.

Entities:

class User
{
    ...

    /**
     * @ORM\OneToMany(targetEntity="Cart", mappedBy="user", cascade={"persist"})
     */
    private $carts;

    public function __construct()
    {
        $this->carts = new ArrayCollection();
    }

    public function addCart(Cart $cart): self
    {
        $this->carts[] = $cart;

        return $this;
    }

    public function removeCart(Cart $cart): bool
    {
        return $this->carts->removeElement($cart);
    }

    public function getCarts(): Collection
    {
        return $this->carts;
    }
}

class Cart
{
    ...

    /**
     * @ORM\ManyToOne(targetEntity="User", inversedBy="carts", cascade={"persist"})
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false)
     */
    private $user;

    /**
     * @ORM\OneToMany(targetEntity="Event", mappedBy="cart", cascade={"persist"})
     */
    private $events;

    public function __construct()
    {
        $this->events = new ArrayCollection();
    }

    public function setUser(User $user): self
    {
        $this->user = $user;

        return $this;
    }

    public function getUser(): User
    {
        return $this->user;
    }

    public function addEvent(Event $event): self
    {
        $this->events[] = $event;

        return $this;
    }

    public function removeEvent(Event $event): bool
    {
        return $this->events->removeElement($event);
    }

    public function getEvents(): Collection
    {
        return $this->events;
    }
}

class Event
{
    ...

    /**
     * @ORM\ManyToOne(targetEntity="Cart", inversedBy="events", cascade={"persist"})
     * @ORM\JoinColumn(name="cart_id", referencedColumnName="id", nullable=false)
     */
    private $cart;

    public function setCart(Cart $cart): self
    {
        $this->cart = $cart;

        return $this;
    }

    public function getCart(): User
    {
        return $this->cart;
    }
}

When doing carts and e-commerces you have to keep in mind a lot of things, and need to ask yourself what kind of information you want to persist. Some people develop Cart modules in a Event Sourced way so they don't loose any data. This talk by Greg Young is great on the subject. That's the approach I would use, but is not the easiest one.

But maybe you don't want to persist all that valuable extra state. In that case, you can use the traditional CRUD approach as you are trying to.

When using this, keep in mind two things.

  1. Your events are mutable. Price can change, location can change, time can change.
  2. When the purchase is complete, you will take that cart and generate a Purchase object from it. That Purchase object CAN NOT have any relationship to Event , because of 1.
  3. You don't want a user to have a single Cart, I guess. A User can have many Carts, so maybe you should make that relationship a ManyToOne on the cart side. Otherwise, Cart can be just a value object that you can store in user.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM