php – Calculate Total Price with Symfony

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 AppController;

/**
 * @IsGranted("IS_AUTHENTICATED_FULLY")
 */
#[Route('/cart', name: 'cart.')]
class OrderController extends AbstractController
{

    /**
     * Show current Cart
     *
     * @param CartService $cartService
     * @return Response
     */
    #[Route("https://stackoverflow.com/", 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()
        ]);
    }
}

Leave a Comment