장바구니 항목 만들기 | Symfony로 장바구니 만들기
Generating entities
OrderItem
entity Order
entity 튜토리얼 전체에서 장바구니에 대해 주문에 대해 설명합니다. 아직 주문되지 않은 진행 중인 주문입니다.
Actually, a cart is an Order in a
cart
status.
엔티티 생성
The Order
entity contains:
- a collection of
OrderItem
entity: it represents products as its physical copies, with chosen quantities, - a status: it will be initialized to
cart
, - a creation date: the creation date of the order,
- a modification date: the date the order was last modified.
OrderItem 엔터티 생성
Use the Maker bundle to generate the OrderItem
entity:
$ symfony console make:entity OrderItem
Add the fields that we need:
- product, relation, related to the Product entity, ManyToOne, no, no
- quantity, integer, no
<?php
namespace App\Entity;
use App\Repository\OrderItemRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=OrderItemRepository::class)
*/
class OrderItem
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity=Product::class)
* @ORM\JoinColumn(nullable=false)
*/
private $product;
/**
* @ORM\Column(type="integer")
*/
private $quantity;
public function getId(): ?int
{
return $this->id;
}
public function getProduct(): ?Product
{
return $this->product;
}
public function setProduct(?Product $product): self
{
$this->product = $product;
return $this;
}
public function getQuantity(): ?int
{
return $this->quantity;
}
public function setQuantity(int $quantity): self
{
$this->quantity = $quantity;
return $this;
}
}
주문 엔터티 생성
One more time, use Maker bundle to generate the Order
entity:
$ symfony console make:entity Order
Add the fields that we need:
- items, relation, related to the
OrderItem
entity, OneToMany, orderRef (order is a reserved word in Mysql), no, yes - status, string, 255, no
- createdAt, datetime, no
- updatedAt, datetime, no
<?php
namespace App\Entity;
use App\Repository\OrderRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=OrderRepository::class)
* @ORM\Table(name="`order`")
*/
class Order
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\OneToMany(targetEntity=OrderItem::class, mappedBy="orderRef", orphanRemoval=true)
*/
private $items;
/**
* @ORM\Column(type="string", length=255)
*/
private $status;
/**
* @ORM\Column(type="datetime")
*/
private $createdAt;
/**
* @ORM\Column(type="datetime")
*/
private $updatedAt;
public function __construct()
{
$this->items = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
/**
* @return Collection|OrderItem[]
*/
public function getItems(): Collection
{
return $this->items;
}
public function addItem(OrderItem $item): self
{
if (!$this->items->contains($item)) {
$this->items[] = $item;
$item->setOrderRef($this);
}
return $this;
}
public function removeItem(OrderItem $item): self
{
if ($this->items->removeElement($item)) {
// set the owning side to null (unless already changed)
if ($item->getOrderRef() === $this) {
$item->setOrderRef(null);
}
}
return $this;
}
public function getStatus(): ?string
{
return $this->status;
}
public function setStatus(string $status): self
{
$this->status = $status;
return $this;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updatedAt;
}
public function setUpdatedAt(\DateTimeInterface $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
}
The OrderItem
has been updated with the following changes:
<?php
namespace App\Entity;
use App\Repository\OrderItemRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=OrderItemRepository::class)
*/
class OrderItem
{
// ...
/**
* @ORM\ManyToOne(targetEntity=Order::class, inversedBy="items")
* @ORM\JoinColumn(nullable=false)
*/
private $orderRef;
// ...
public function getOrderRef(): ?Order
{
return $this->orderRef;
}
public function setOrderRef(?Order $orderRef): self
{
$this->orderRef = $orderRef;
return $this;
}
}
캐스케이드 작업 설정
When we add a new OrderItem
entity to an Order
entity, we should persist it before persisting the Order
entity. Also, when we will want to remove an Order
entity, we should remove all OrderItem
entities before removing the Order
entity.
It can be really boring, so we will let Doctrine take care of this internally by using the cascade operations. To do that, add a new cascade option on the items
property of the Order
entity:
/**
* @ORM\OneToMany(targetEntity=OrderItem::class, mappedBy="orderRef", cascade={"persist", "remove"}, orphanRemoval=true)
*/
private $items;
Therefore, when we will persist/remove an Order
entity, Doctrine will automatically call persist/remove on each of the OrderItem
objects associated with the Order
entity.
데이터베이스 마이그레이션
Create a migration file via the Maker bundle:
$ symfony console make:migration
A migration file has been stored under the migrations/
directory:
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20201215150141 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TABLE `order` (id INT AUTO_INCREMENT NOT NULL, status VARCHAR(255) NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('CREATE TABLE order_item (id INT AUTO_INCREMENT NOT NULL, product_id INT NOT NULL, order_ref_id INT NOT NULL, quantity INT NOT NULL, INDEX IDX_52EA1F094584665A (product_id), INDEX IDX_52EA1F09E238517C (order_ref_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('ALTER TABLE order_item ADD CONSTRAINT FK_52EA1F094584665A FOREIGN KEY (product_id) REFERENCES product (id)');
$this->addSql('ALTER TABLE order_item ADD CONSTRAINT FK_52EA1F09E238517C FOREIGN KEY (order_ref_id) REFERENCES `order` (id)');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE order_item DROP FOREIGN KEY FK_52EA1F09E238517C');
$this->addSql('DROP TABLE `order`');
$this->addSql('DROP TABLE order_item');
}
}
Now, we can update the local database schema:
$ symfony console doctrine:migrations:migrate
기본 주문 상태 설정
All new orders must be in the default cart
state. In the generated Order
entity, initialize the status using a STATUS_CART
constant:
<?php
namespace App\Entity;
// ...
/**
* @ORM\Entity(repositoryClass=OrderRepository::class)
* @ORM\Table(name="`order`")
*/
class Order
{
// ...
/**
* @ORM\Column(type="string", length=255)
*/
private $status = self::STATUS_CART;
/**
* An order that is in progress, not placed yet.
*
* @var string
*/
const STATUS_CART = 'cart';
// ...
}
중복 주문 항목 추가 방지
Currently, it's possible to add duplicate OrderItem
entities (with the same Product) to the Order
entity. Let's fix it.
Add a equals()
method to the OrderItem
class to know if the item corresponds to an item given as an argument.
/**
* Tests if the given item given corresponds to the same order item.
*
* @param OrderItem $item
*
* @return bool
*/
public function equals(OrderItem $item): bool
{
return $this->getProduct()->getId() === $item->getProduct()->getId();
}
Update the addItem()
method of the Order
entity to sum the quantity if the item already exists:
public function addItem(OrderItem $item): self
{
foreach ($this->getItems() as $existingItem) {
// The item already exists, update the quantity
if ($existingItem->equals($item)) {
$existingItem->setQuantity(
$existingItem->getQuantity() + $item->getQuantity()
);
return $this;
}
}
$this->items[] = $item;
$item->setOrderRef($this);
return $this;
}
주문에서 모든 항목 제거
Add a removeItems()
method to the Order
class to remove all items from the Order:
/**
* Removes all items from the order.
*
* @return $this
*/
public function removeItems(): self
{
foreach ($this->getItems() as $item) {
$this->removeItem($item);
}
return $this;
}
주문 합계 계산
We will need to show the cart summary. Note that we ignore adjustments that order could have such as shipping cost, promo code, etc.
First, add a getTotal()
method to the OrderItem
entity to calculate the item total:
/**
* Calculates the item total.
*
* @return float|int
*/
public function getTotal(): float
{
return $this->getProduct()->getPrice() * $this->getQuantity();
}
Finally, add a getTotal()
method to the Order
entity to calculate the order total:
/**
* Calculates the order total.
*
* @return float
*/
public function getTotal(): float
{
$total = 0;
foreach ($this->getItems() as $item) {
$total += $item->getTotal();
}
return $total;
}
공장 만들기
The OrderFactory
factory will help us to create Order
and OrderItem
entities with default data. It also allows you to change the Order
entity easily.
<?php
namespace App\Factory;
use App\Entity\Order;
use App\Entity\OrderItem;
use App\Entity\Product;
/**
* Class OrderFactory
* @package App\Factory
*/
class OrderFactory
{
/**
* Creates an order.
*
* @return Order
*/
public function create(): Order
{
$order = new Order();
$order
->setStatus(Order::STATUS_CART)
->setCreatedAt(new \DateTime())
->setUpdatedAt(new \DateTime());
return $order;
}
/**
* Creates an item for a product.
*
* @param Product $product
*
* @return OrderItem
*/
public function createItem(Product $product): OrderItem
{
$item = new OrderItem();
$item->setProduct($product);
$item->setQuantity(1);
return $item;
}
}
Let's go to the next step to manage cart storage.
Reference
이 문제에 관하여(장바구니 항목 만들기 | Symfony로 장바구니 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/qferrer/creating-cart-entities-building-a-shopping-cart-with-symfony-h90텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)