I have the following problem with shopping cart. I don’t know where to place the calculation, so it can update total price dynamically (Such when the cart item is removed, or the quantity updated). Because I need to call updateTotalPrice()
method almost everywhere, but I don’t want to repeat the code that many times
CartService
class CartService extends AbstractController
{
private CartRepository $cartRepository;
private ManagerRegistry $managerRegistry;
private CartItemRepository $cartItemRepository;
public function __construct(CartItemRepository $cartItemRepository, CartRepository $cartRepository, ManagerRegistry $managerRegistry)
{
$this->cartItemRepository = $cartItemRepository;
$this->cartRepository = $cartRepository;
$this->managerRegistry = $managerRegistry;
}
/**
* Get Cart by ID
*
* @return Cart|null
*/
public function getCartByUserId(): ?Cart
{
/**
* @var User $user
*/
$user = $this->getUser();
return $this->cartRepository->findOneBy(['customer' => $user->getId()]);
}
/**
* Create Cart for Customer
*
* @return Cart|null
*/
public function createNewCart(): ?Cart
{
$entityManager = $this->managerRegistry->getManager();
$cart = new Cart();
/**
* @var User $user
*/
$cart->setCustomer($this->getUser());
$entityManager->persist($cart);
$entityManager->flush();
return $cart;
}
/**
* @param Cart $cart
* @param Product $product
* @return CartItem|null
*/
public function isProductInCart(Cart $cart, Product $product): ?CartItem
{
return $this->cartItemRepository->findOneBy(['product' => $product->getId(), 'cart' => $cart->getId()]);
}
/**
* Add new product to cart
*
* @param Cart $cart
* @param Product $product
* @param int $quantity
* @return void
*/
public function insertProduct(Cart $cart, Product $product, int $quantity): void
{
$entityManager = $this->managerRegistry->getManager();
$insertProduct = new CartItem();
$insertProduct->setCart($cart)
->setCart($cart)
->setQuantity($quantity)
->setProduct($product);
$cart->addCartItem($insertProduct);
$cart->setTotalprice($cart->getTotalprice() + $insertProduct->getQuantity() * $insertProduct->getProduct()->getPrice());
$entityManager->persist($insertProduct);
$entityManager->flush();
}
/**
* Update item's quantity
*
* @param CartItem $cartItem
* @param int $quantity
* @return void
*/
public function updateCartItemQuantity(CartItem $cartItem, int $quantity): void
{
$entityManager = $this->managerRegistry->getManager();
$cartItem->setQuantity($quantity);
$entityManager->persist($cartItem);
$entityManager->flush();
}
/**
* Remove specific product from cart
*
* @param int $id
* @return void
*/
public function removeProductFromCart(int $id): void
{
$product = $this->cartItemRepository->findOneBy(['product' => $id]);
$entityManager = $this->managerRegistry->getManager();
$entityManager->remove($product);
$entityManager->flush();
}
/**
* Set or update total price
*
* @param Cart $cart
* @param float $totalprice
* @return void
*/
public function updateTotalPrice(Cart $cart, float $totalprice): void
{
$entityManager = $this->managerRegistry->getManager();
$cart->setTotalprice($cart->getTotalprice() + $totalprice);
$entityManager->persist($cart);
$entityManager->flush($cart);
}
/**
* Add Product to Cart
*
* @param Product $product
* @param $cartItem
* @return void
*/
public function addOrUpdateProduct(Product $product, $cartItem): void
{
$cart = $this->getCartByUserId();
if (!$cart instanceof Cart) {
$cart = $this->createNewCart();
}
$isProductInCart = $this->isProductInCart($cart, $product);
//If product doens't exist, insert it inside cart. If exist, update quantity and add message
if (!$isProductInCart) {
$this->insertProduct($cart, $product, $cartItem->getQuantity());
$this->addFlash('productAdded', 'Product added to Cart');
} else {
$this->updateCartItemQuantity($isProductInCart, $cartItem->getQuantity() + $isProductInCart->getQuantity());
$this->updateTotalPrice($cart, $cartItem->getQuantity() * $cartItem->getProduct()->getPrice());
$this->addFlash('productAdded', 'Product already in cart. Quantity Updated');
}
}
OrderController (That's the cart)
<?php
namespace App\Controller;
/**
* @IsGranted("IS_AUTHENTICATED_FULLY")
*/
#[Route('/cart', name: 'cart.')]
class OrderController extends AbstractController
{
/**
* Show current Cart
*
* @param CartService $cartService
* @return Response
*/
#[Route('/', name: 'show_cart')]
public function showCart(CartService $cartService): Response
{
$cart = $cartService->getCartByUserId();
return $this->render('cart/index.html.twig', [
'cart' => $cart,
]);
}
/**
* Update existing cart item quantity
*
* @param CartItem $cartItem
* @param int $quantity
* @param CartService $cartService
* @return Response
*/
#[Route('/updatecartquantity/{id}/{quantity}', name: 'updatequantity')]
public function updateCartQuantity(CartItem $cartItem, int $quantity, CartService $cartService): Response
{
$cartService->updateCartItemQuantity($cartItem, $quantity);
return $this->redirect($this->generateUrl('cart.show_cart'));
}
/**
* Remove product from cart
*
* @param CartService $cartService
* @param int $id
* @return Response
*/
#[Route('/removeitem/{id}', name: 'removefromcart')]
public function removeFromCart(CartService $cartService, int $id): Response
{
$cartService->removeProductFromCart($id);
return $this->redirect($this->generateUrl('cart.show_cart'));
}
}
Product Controller (Shows the product -> After choosing quantity can be inserted inside cart
#[Route('/product', name: 'product.')]
class ProductController extends AbstractController
{
/**
* Show Product, and add to cart
*
* @param Product $product
* @param CartService $cartService
* @param Request $request
* @return Response
*/
#[Route('/showproduct/{id}', name: 'showproduct')]
public function showProduct(Product $product, CartService $cartService, Request $request): Response
{
$form = $this->createForm(CartItemType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$item = $form->getData();
$item->setProduct($product);
$cartService->addOrUpdateProduct($product, $item);
}
return $this->render('product/showproduct.html.twig', [
'product' => $product,
'form' => $form->createView()
]);
}
}
My Answer:
To calculate the total price dynamically and update it whenever a cart item is added, removed, or the quantity is updated, you can modify the `updateTotalPrice()` method in your `CartService` class. Here's how you can update the method:
php
/**
* Set or update total price
*
* @param Cart $cart
* @return void
*/
public function updateTotalPrice(Cart $cart): void
{
$totalPrice = 0;
foreach ($cart->getCartItems() as $cartItem) {
$totalPrice += $cartItem->getQuantity() * $cartItem->getProduct()->getPrice();
}
$cart->setTotalprice($totalPrice);
$entityManager = $this->managerRegistry->getManager();
$entityManager->persist($cart);
$entityManager->flush();
}
Now, you can call the `updateTotalPrice()` method whenever you add, update, or remove a cart item in your `CartService` class. For example, in the `insertProduct()`, `updateCartItemQuantity()`, and `removeProductFromCart()` methods, you can call `updateTotalPrice($cart)` after making the necessary changes to the cart items.
This way, the total price will be updated dynamically based on the cart items' quantities and prices. This approach avoids repeating the code for updating the total price in multiple places and ensures that the total price is always accurate.
Rate this post
4 of 5 based on 3321 votesComments