DEV Community

Cover image for How To Create Your Own Advance Cart Package with Laravel
Rayees Aadil
Rayees Aadil

Posted on

How To Create Your Own Advance Cart Package with Laravel

" The More Packages and Plugins you use, the Less Control you will have over your Code".


Based on what you read above, we are building our cart package on our own because sometimes you might want to modify the cart package, but you have to read the entire code of the package to add a new function or functionality and it also requires big brain to do so or maybe sometimes its impossible to change it …

So in today's tutorial, we'll build a cart package that will satisfy your cart needs and allows you to customize it further, so let's begin !

Lets Create a folder called Service and inside the service we will create a file called Cart.php where we make a new class called Cart and we will store all our cart methods inside it .

<?php

namespace App\Services;

use App\Models\Product;
use App\Models\Category;

use Session; 

class Cart {

}

Enter fullscreen mode Exit fullscreen mode

Now we will define a static function which will be called statically as the data will be same across all instances and we don't wanna create different instance every time, so that's why we are using static method .

Now create a static function called add which will be our main method for adding the cart items to the session

We will pass some parameters in the method which will be our data values like name, id, price etc..


public static function add($id,$name,$category,$price,$quantity)
{
    $cart = session('cart', []); //or session()->get('cart', []);   
}

Enter fullscreen mode Exit fullscreen mode

We will use Session Global Helper here to create a session and we will pass an empty array inside the helper as default .

Than we will define a new variable called cartId which will generate random number every time the new item is added , it will be useful when we will delete a specific item from the cart

$cartId = rand(000000,999999); //generates the random CartId for every item

Enter fullscreen mode Exit fullscreen mode

After that, we update the $cart array by adding the cartId as the key and we will create one more array inside it where we will store our cart data from the parameters like this:


$cart[$cartId] = [
      "id"     => $id,
      "name"   => $name,
      "category" => $category,
      "quantity" => $quantity,  
      "price"=> $price,
    ]

Enter fullscreen mode Exit fullscreen mode

Now we will add that array into the Cart Session like this:


public static function add($id,$name,$category,$price,$quantity)
{
    //Create an Empty Session called 'Cart' with an Empty array as default
    $cart = session('cart', []); //or session()->get('cart', []);  

    $cart[$cartId] = [ //Adds the cartId as the key to remove/update items
      "id"     => $id,
      "name"   => $name,
      "category" => $category,
      "quantity" => $quantity,  
      "price"=> $price,
     ];
     //Update the array into the Cart session 
     $cartSession = session()->put('cart', $cart);
}

Enter fullscreen mode Exit fullscreen mode

But now the main problem arises what if we want to add more values to the cart like weight or additional values or even a model with relationships loaded ?

You will be like is that possible ? well yes of course ! and also its pretty easy to do, lets see how we can do that !

So instead of passing an id , name, price in the parameters we can remove those parameters and pass a whole model just like this:

In the Cart.php :


public static function add($product)
{
  "product" => $product,
}

Enter fullscreen mode Exit fullscreen mode

In the controller :


public function addCartItem(Request $request)
{
  $product = Product::where('id',$request->id)->first()->toArray();
  Cart::add($product); //adding the whole model 
}

Enter fullscreen mode Exit fullscreen mode

but what if you want to load relationships too, you can use ' with ' method in the query to load the relationships and then you can access it like this:


//In the Cart Controller
public function addCartItem(Request $request)
{
  $product = Product::where('id',$request->id)->with('tags')->first()->toArray();
  Cart::add($product);  
}

//In the View:

foreach (Cart::getContent() as $key => $value) {

        echo $value["product"]["name"];

        //Accessing Relationship
        foreach ($value["product"]["tags"] as $key => $tag) 

           echo $tag->name;

        }
    }

Enter fullscreen mode Exit fullscreen mode

Now the 2 problem arises imagine if you want store some more data which is not available in the model or you want to put some additional data which can in array form for eg:- Attributes like Size with XL, XS, XXL or Color with Red, Blue or Green etc... now the 2nd problem arises what you will do is change the function again for the additional data, you can see we are updating the cart array again and we are doing modifications now if you have studied Open Closed Principle in the SOLID Principles it says

" Classes and Methods should be Opened For Extension but Closed for Modification "

and our method is violating this principle so here is an idea to tackle this , we will pass the whole array in the add method parameter which will be dynamic array (the cart data) and will use it in the Frontside which is the controller so it will look like this:


//the Cart Array which we will pass from the controller
public static function add($cartData) 
{
    //Create an Empty Session called 'Cart' with an Empty array as default
    $cart = session('cart', []); //or session()->get('cart', []);  

    $cart[$cartId] = $cartData; 
     //Update the array into the Cart session 
     $cartSession = session()->put('cart', $cart);
}

//In CartController.php 

public function addCartItem(Request $request)
{
  $product = Product::where('id',$request->id)->with('tags')->first()->toArray();

    Cart::add([

      "product" => $product, //Your Model
      "weight" => 0.600,

      //Your Attributes Array to Add addtional data in array form
      "colors" => ['Red','Blue','Purple'], 
      "attributes" => ['XS,'XL','XXL'], 

      ]);
}
In View :

foreach (Cart::getContent() as $key => $value) {

    echo $value["product"]["name"];

    //Accessing Relationship
    foreach ($value["product"]["tags"] as $key => $tag) 
    {
       echo $tag->name;
    }
    //Accessing the Attributes Array
    foreach ($value["product"]["colors"] as $key => $tag) 
    {
       echo $tag->name;
    }
}

Enter fullscreen mode Exit fullscreen mode

Now You see our add method is now much more cleaner, shorter and customizable and we don't have to modify it again ! just simply pass the data you want .Just Simple As That ! .

Lets create another method called getContent to retrieve our Cart Session:


public static function getContent()
{
    return Session::get('cart');
}

Enter fullscreen mode Exit fullscreen mode

You can use this method to retrieve Cart Items and you can use it in view as metioned above .

Create another function to calculate our GrandTotal Price :


public $grandTotalWeight;

public function GrandTotalWeight()
{
  $cartItems = self::getContent();

  if($cartItems !== NULL &&  count($cartItems) > 0){

      foreach ($cartItems as $key => $value) {
          /*here we will add the product price 
          and we will multiple it with quantity to achieve the
          grandtotal results
          */
          $this->grandTotalWeight += $value['price'] * $value['quantity'];
      }
  }

  return $this->grandTotalWeight;
}

Enter fullscreen mode Exit fullscreen mode

Now lets make some more methods like destroyCart, _destroyCartItem _ etc…

Here we will pass the _cartId _parameter in the function and we will find it by accessing it as an index (cartId) and remove the item with unset method :


public static function destroyCartItem($cartId)
{
    $cartItems = Cart::getContent();

    //find the cart item and remove it by using unset method
    unset($cartItems[$cartId]); 

    Session::put('cart', $cartItems); //update the array

    return;
}


Enter fullscreen mode Exit fullscreen mode

Destroy/Clear Cart :


public static function destroyCartItem($cartId)
{

  if(Session::has('cart'){

    return Session::forget('cart'); //update the array
  }

  return;
}

Enter fullscreen mode Exit fullscreen mode

Check If The Cart is Empty Or Not .

public static function EmptyCheck()
{
    $cartItems = self::getContent();

    if($cartItems !== NULL && count($cartItems) > 0 ){

        return true;
    }

    return false;

}

Enter fullscreen mode Exit fullscreen mode

Here what our Final Cart Class would look like :


<?php

namespace App\Services;

use Session; 

class Cart {

  public $grandTotalWeight;

  public static function add($cartData) 
  {
      $cart = session('cart', []); 

      $cart[$cartId] = $cartData; 

      $cartSession = session()->put('cart', $cart);
  }

  public function GrandTotalWeight()
  {
    $cartItems = self::getContent();

    if($cartItems !== NULL &&  count($cartItems) > 0){

        foreach ($cartItems as $key => $value) {

            //the $value['price'] & $value['quantity'] should be passed 
            //in cart array or it wont be able to calculate the total
            $this->grandTotalWeight += $value['price'] * $value['quantity'];
        }
    }

    return $this->grandTotalWeight;
  }

  public static function destroyCartItem($cartId)
  {
      $cartItems = Cart::getContent();

      //find the cart item and remove it by using unset method
      unset($cartItems[$cartId]); 

      Session::put('cart', $cartItems); //update the array

      return;
  }

  public static function destroyCartItem($cartId)
  {

    if(Session::has('cart'){

      return Session::forget('cart'); //update the array
    }

    return;
  }

  public static function EmptyCheck()
  {
      $cartItems = self::getContent();

      if($cartItems !== NULL && count($cartItems) > 0 ){

          return true;
      }

      return false;

  }
}

Enter fullscreen mode Exit fullscreen mode

Now you can use these methods in your controller !

So I Hope you like this articles , if you have any ideas or modification that we can customize this Cart Package , do comment down below. I will cover those topics in the Next Chapter .

Thank You So Much If You Have Read This Far. It Really Means Alot To Me .

Top comments (0)