├── .editorconfig ├── .env.example ├── .gitattributes ├── .gitignore ├── .styleci.yml ├── README.md ├── app ├── Console │ └── Kernel.php ├── Exceptions │ └── Handler.php ├── Http │ ├── Controllers │ │ ├── CartController.php │ │ ├── Controller.php │ │ ├── PagesController.php │ │ └── ProductController.php │ ├── Kernel.php │ └── Middleware │ │ ├── Authenticate.php │ │ ├── EncryptCookies.php │ │ ├── PreventRequestsDuringMaintenance.php │ │ ├── RedirectIfAuthenticated.php │ │ ├── TrimStrings.php │ │ ├── TrustHosts.php │ │ ├── TrustProxies.php │ │ └── VerifyCsrfToken.php ├── Models │ ├── Product.php │ └── User.php └── Providers │ ├── AppServiceProvider.php │ ├── AuthServiceProvider.php │ ├── BroadcastServiceProvider.php │ ├── EventServiceProvider.php │ └── RouteServiceProvider.php ├── artisan ├── bootstrap ├── app.php └── cache │ └── .gitignore ├── composer.json ├── composer.lock ├── config ├── app.php ├── auth.php ├── broadcasting.php ├── cache.php ├── cors.php ├── database.php ├── filesystems.php ├── hashing.php ├── logging.php ├── mail.php ├── queue.php ├── sanctum.php ├── services.php ├── session.php └── view.php ├── database ├── .gitignore ├── factories │ └── UserFactory.php ├── migrations │ ├── 2014_10_12_000000_create_users_table.php │ ├── 2014_10_12_100000_create_password_resets_table.php │ ├── 2019_08_19_000000_create_failed_jobs_table.php │ ├── 2019_12_14_000001_create_personal_access_tokens_table.php │ └── 2021_11_19_182429_create_products_table.php └── seeders │ ├── DatabaseSeeder.php │ └── ProductSeeder.php ├── package.json ├── phpunit.xml ├── public ├── .htaccess ├── favicon.ico ├── index.php ├── robots.txt └── web.config ├── resources ├── css │ └── app.css ├── js │ ├── app.js │ └── bootstrap.js ├── lang │ └── en │ │ ├── auth.php │ │ ├── pagination.php │ │ ├── passwords.php │ │ └── validation.php └── views │ ├── cart │ └── cart.blade.php │ ├── index.blade.php │ ├── layouts │ └── app.blade.php │ └── shop │ ├── index.blade.php │ └── show.blade.php ├── routes ├── api.php ├── channels.php ├── console.php └── web.php ├── server.php ├── storage ├── app │ ├── .gitignore │ └── public │ │ ├── .gitignore │ │ ├── product1.png │ │ └── product2.png ├── framework │ ├── .gitignore │ ├── cache │ │ ├── .gitignore │ │ └── data │ │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ ├── testing │ │ └── .gitignore │ └── views │ │ └── .gitignore └── logs │ └── .gitignore ├── tests ├── CreatesApplication.php ├── Feature │ └── ExampleTest.php ├── TestCase.php └── Unit │ └── ExampleTest.php └── webpack.mix.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.{yml,yaml}] 15 | indent_size = 2 16 | 17 | [docker-compose.yml] 18 | indent_size = 4 19 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME=Laravel 2 | APP_ENV=local 3 | APP_KEY= 4 | APP_DEBUG=true 5 | APP_URL=http://localhost 6 | 7 | LOG_CHANNEL=stack 8 | LOG_DEPRECATIONS_CHANNEL=null 9 | LOG_LEVEL=debug 10 | 11 | DB_CONNECTION=mysql 12 | DB_HOST=127.0.0.1 13 | DB_PORT=3306 14 | DB_DATABASE=laravel_cart_cloudways 15 | DB_USERNAME=root 16 | DB_PASSWORD= 17 | 18 | BROADCAST_DRIVER=log 19 | CACHE_DRIVER=file 20 | FILESYSTEM_DRIVER=local 21 | QUEUE_CONNECTION=sync 22 | SESSION_DRIVER=file 23 | SESSION_LIFETIME=120 24 | 25 | MEMCACHED_HOST=127.0.0.1 26 | 27 | REDIS_HOST=127.0.0.1 28 | REDIS_PASSWORD=null 29 | REDIS_PORT=6379 30 | 31 | MAIL_MAILER=smtp 32 | MAIL_HOST=mailhog 33 | MAIL_PORT=1025 34 | MAIL_USERNAME=null 35 | MAIL_PASSWORD=null 36 | MAIL_ENCRYPTION=null 37 | MAIL_FROM_ADDRESS=null 38 | MAIL_FROM_NAME="${APP_NAME}" 39 | 40 | AWS_ACCESS_KEY_ID= 41 | AWS_SECRET_ACCESS_KEY= 42 | AWS_DEFAULT_REGION=us-east-1 43 | AWS_BUCKET= 44 | AWS_USE_PATH_STYLE_ENDPOINT=false 45 | 46 | PUSHER_APP_ID= 47 | PUSHER_APP_KEY= 48 | PUSHER_APP_SECRET= 49 | PUSHER_APP_CLUSTER=mt1 50 | 51 | MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" 52 | MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" 53 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.css linguist-vendored 3 | *.scss linguist-vendored 4 | *.js linguist-vendored 5 | CHANGELOG.md export-ignore 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /public/hot 3 | /public/storage 4 | /storage/*.key 5 | /vendor 6 | .env 7 | .env.backup 8 | .phpunit.result.cache 9 | docker-compose.override.yml 10 | Homestead.json 11 | Homestead.yaml 12 | npm-debug.log 13 | yarn-error.log 14 | /.idea 15 | /.vscode 16 | -------------------------------------------------------------------------------- /.styleci.yml: -------------------------------------------------------------------------------- 1 | php: 2 | preset: laravel 3 | version: 8 4 | disabled: 5 | - no_unused_imports 6 | finder: 7 | not-name: 8 | - index.php 9 | - server.php 10 | js: 11 | finder: 12 | not-name: 13 | - webpack.mix.js 14 | css: true 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Shopping Cart in Laravel 2 | 3 | The following documentation is based on my [Laravel 8 - Creating a shopping cart in Laravel 8](https://www.udemy.com/course/laravel-8-build-a-shopping-cart-and-deploy-it-on-cloudways/) tutorial where we will be creating a shopping cart in Laravel.

4 | • Author: [Code With Dary](https://github.com/codewithdary)
5 | • Twitter: [@codewithdary](https://twitter.com/codewithdary)
6 | • Instagram: [@codewithdary](https://www.instagram.com/codewithdary/)
7 | 8 | 9 | ## Technical Requirements 10 | • PHP => 7.2.5
11 | 12 | ## Prerequisites 13 | • Basic Laravel knowledge
14 | • Low level HTML & CSS/TailwindCSS knowledge
15 | • Object-Oriented Programming
16 | 17 | ## Course Overview 18 | 19 | | **Episode** | **Subject** | 20 | | ------------- |-------------| 21 | | Ep. 1 | Introduction to this course | 22 | | Ep. 2 | Creating our GitHub repository + Laravel project | 23 | | Ep. 3 | Creating all Controllers, Models, Migrations & Routes | 24 | | Ep. 4 | Setting up our database & credentials | 25 | | Ep. 5 | Setting up our migrations & data structure | 26 | | Ep. 6 | Creating our database seeding | 27 | | Ep. 7 | Storing images & adding | 28 | | Ep. 8 | Building the frontend | 29 | | Ep. 9 | Making our shop dynamic | 30 | | Ep. 10 | Saving products to our session/cart | 31 | | Ep. 11 | Making our cart dynamic | 32 | | Ep. 12 | Deleting products from our session/cart | 33 | | Ep. 13 | Updating the quantity | 34 | 35 | ## Usage
36 | Setup your coding environment
37 | ``` 38 | git clone git@github.com:codewithdary/laravel-cart-cloudways.git 39 | cd laravel-cart-cloudways 40 | composer install 41 | cp .env.example .env 42 | php artisan key:generate 43 | php artisan cache:clear && php artisan config:clear 44 | php artisan serve 45 | ``` 46 | 47 | # 1. Introduction to this course 48 | 49 | Working on a shopping cart in any type of programming language does require some kind of skip, and that applies for this course as well. We are going to work inside a Laravel 8 project, where we won’t be styling our pages, but we will be using a repository I have created before. 50 | 51 | There are multiple ways on how you can get in touch if you’re running into issues. I got to say that it’s difficult at times to maintain and respond to everyone, but I’ll definitely do my best. 52 | 53 | ### Instagram 54 | My Instagram username is codewithdary as well, and next to coding issues, you’ll find more personal stuff about me over here. 55 | 56 | ### YouTube 57 | If you are interested in learning more about coding, you can check me out on YouTube where you’ll can find me under the name of Code With Dary. I’m a developer and educator who created online courses in PHP, JavaScript, Laravel and TailwindCSS to help everyone out. 58 | 59 | ### Patreon 60 | If you are interested in getting into my Discord group and interact with other up and coming developers (and me) about your coding issues, my Patreon will be the right place for you! 61 | 62 | ## 2. Creating our GitHub repository + Laravel project 63 | 64 | When you want to deploy a Laravel project into the cloud, you should be working with ```GitHub```. GitHub is an open source platform where all developers over the entire world contribute to source codes, and where you can control your software. 65 | 66 | Once you are logged into your GitHub account, you need to make sure that you create a new repository. A ```repository``` is the location where you store your project files. 67 | 68 | The following fields needs to be defined: 69 | ``` 70 | Repository name: Laravel-cart-cloudways 71 | Visibility: public 72 | Select: Add a README file & add .gitignore 73 | ``` 74 | 75 | Once you have created your repository, the GitHub needs to be cloned somewhere on your local machine. I personally have a folder on my Desktop called Workspace where I store my coding projects. Make sure that you copy the ```HTTPS``` or ```SSH``` from your GitHub repository, open a terminal and execute the following commands. 76 | 77 | ``` 78 | cd /Desktop/workspace 79 | git clone https://github.com/{username}/{repository_name} 80 | ``` 81 | 82 | This will create a new directory inside your workspace directory with the name of ```Laravel-cart-cloudways```. When performing commands for your coding project, you need to be located inside the project. 83 | 84 | ``` 85 | cd laravel-cart-cloudways/ 86 | ``` 87 | 88 | We have not added our Laravel project into our GitHub repository. This can be done in two ways. The first method does not work on a Mac but will most likely work on Linux and/or Windows. 89 | 90 | ``` 91 | laravel new . 92 | ``` 93 | 94 | The command above will create a new Laravel project in the root of your GitHub repository. 95 | 96 | If this command throws an error, you need to create a new Laravel project with a folder name, and drag all files and folders into the root of your directory. 97 | 98 | ``` 99 | laravel new laravel-cart-cloudways 100 | ``` 101 | 102 | Finally, let’s run out project inside the browser. 103 | 104 | ``` 105 | php artisan serve 106 | ``` 107 | 108 | ## 3. Creating Controllers, Models, Migrations & Routes 109 | 110 | Laravel has the power to create Controllers in a pretty fast way through the CLI. Controllers are used to interact with the right Model, which will get the right data from the database that has been built with the migration, which will finally send data back to a view through the route. 111 | 112 | When creating a shopping cart, you will most likely have a ```Home page```, ```Product page``` and a ```Cart page```. 113 | 114 | The Home page will not have any interaction with models, but it will simply return the frontpage of our application. 115 | 116 | ``` 117 | php artisan make:controller PagesController 118 | ``` 119 | 120 | There will be a total of two product pages. One product that will show the overview of all pages, and one product page that accepts a route parameter, which allows us to dynamically render a page. 121 | 122 | ``` 123 | php artisan make:model Product -c -m 124 | ``` 125 | 126 | The ```-c``` flag will add the correct Controller to our ```Product``` model, and the ```-m``` flag adds the correct migration to our Product model. 127 | 128 | Our shopping cart does not need to have a model since we’re not going to save products into our database. We simply need to define a Controller for it. 129 | 130 | ``` 131 | php artisan make:controller CartController 132 | ``` 133 | 134 | Routes can be defined inside the ```/routes/web.php``` file. We will not be using the default route that Laravel provides for us, since we will be passing views directly into our Controller. 135 | 136 | ```ruby 137 | Route::get('/', function() { 138 | return view('welcome'); 139 | }); 140 | ``` 141 | 142 | We will be defining a total of 4 routes to interact with our home page, product pages, and shopping cart. 143 | 144 | ```ruby 145 | Route::get('/', [PagesController::class, 'index'])->name('home'); 146 | Route::get('/shop', [ProductController::class, 'index'])->name('shop'); 147 | Route::get('/shop/{id}', [ProductController::class, 'show'])->name('product'); 148 | Route::get('/cart', [CartController::class, 'cart'])->name('cart'); 149 | ``` 150 | 151 | ## 4. Setting up our database & credentials 152 | 153 | When dealing with migrations in Laravel, you obviously need to have your database credentials and database itself setup. 154 | 155 | The root of every Laravel project has a hidden file named ```.env``` inside of it. By default, Laravel adds the project name as your database name, sets the ```DB_USERNAME``` to root, but keeps the password empty. These values need to be changed in order to interact with your local database. 156 | 157 | ``` 158 | DB_CONNECTION=mysql 159 | DB_HOST=127.0.0.1 160 | DB_PORT=3306 161 | DB_DATABASE=laravel_cart_cloudways 162 | DB_USERNAME=root 163 | DB_PASSWORD= 164 | ``` 165 | 166 | Laravel will not create the database itself, so that is something that needs to be done as well. I’m using a Database extension in ```Visual Studio Code``` called “```Database Client```”, which allows me to interact with my databases. It also allows me to simply create a database through an interface. 167 | 168 | If you prefer to use the CLI, you can simply perform the following commands. 169 | ``` 170 | mysql; 171 | create database laravel_cart_cloudways; 172 | exit; 173 | ``` 174 | 175 | ## 5. Setting up our migrations 176 | 177 | A good back-end project always starts with the correct database. This will prevent a lot of issues when creating relationships inside your code. 178 | 179 | Our migration has already been defined in ```Chapter 3: Creating Controllers, Models, Migrations & Routes```, where we added the ```-m``` flag when defining our Product model. 180 | 181 | This migration can be found inside the ```/database/migrations``` folder, where a couple pre-defined migrations will be found that start with a timestamp, followed with the migration name. We need the last one, since it’s the last migration we have created. 182 | 183 | Our table structure needs to be defined inside the``` up()``` method. Replace the method that you have with the following. 184 | 185 | ```ruby 186 | public function up() { 187 | Schema::create('products', function (Blueprint $table) { 188 | $table->id(); 189 | $table->string('name')->unique()->nullable(false); 190 | $table->string('details')->nullable(false); 191 | $table->text('description')->nullable(false); 192 | $table->text('brand')->nullable(false); 193 | $table->double('price')->nullable(false); 194 | $table->double('shipping_cost'); 195 | $table->string('image_path')->nullable(false); 196 | $table->timestamps(); 197 | }); 198 | } 199 | ``` 200 | Once you have setup your migration, we need to migrate it into our database through the CLI. 201 | ``` 202 | php artisan migrate 203 | ``` 204 | 205 | This command will execute all ```up()``` methods from our ```/database/migrations``` folder. 206 | 207 | ## 6. Creating database seeders 208 | 209 | When it comes to creating dummy data in Laravel, I prefer to use database seeders rather than creating the data through a database client. A database seeder can simply be created through the CLI. 210 | 211 | ``` 212 | php artisan make:seeder ProductSeeder 213 | ``` 214 | 215 | The seeder will be added inside the ```/database/seeder``` folder, with a file name of ```ProductSeeder.php```. 216 | 217 | I prefer to define my products inside an array, and then loop over the array and perform an ```create()``` method. 218 | 219 | ```php 220 | public function run() 221 | { 222 | $products = [ 223 | [ 224 | 'name' => 'Apple Macbook Pro 16', 225 | 'details' => 'Apple M1 Pro, 16 GPU, 16 GB, 512 GB, 226 | 'description' => Description', 227 | 'brand' => 'Apple', 228 | 'price' => 2499, 229 | 'shipping_cost' => 25, 230 | 'image_path' => 'storage/product.png' 231 | ], 232 | [ 233 | 'name' => 'Samsung Galaxy Book Pro', 234 | 'details' => '13.3 inch, 8GB, DDR4 SDRAM, 256GB', 235 | 'description' => ‘Description', 236 | 'brand' => 'Samsung', 237 | 'price' => 1400, 238 | 'shipping_cost' => 25, 239 | 'image_path' => 'storage/product2.png' 240 | ], 241 | ]; 242 | ``` 243 | 244 | Right below our array, we need to iterate over it and create new products through the ```Product``` model. 245 | 246 | ```php 247 | foreach($products as $key => $value) { 248 | Product::create($value); 249 | } 250 | ``` 251 | 252 | We’re almost done. The last step is defining our ProductSeeder inside the DatabaseSeeder, so it 253 | 254 | ```php 255 | public function run() 256 | { 257 | $this->call(ProductSeeder::class); 258 | } 259 | ``` 260 | 261 | Alright! Let’s seed it through the CLI! 262 | 263 | ``` 264 | php artisan db:seed 265 | ``` 266 | 267 | If you open your database client, refresh the ```“Products”``` table, you will see that two new rows have been added. 268 | 269 | ## 7. Storing images & symbolic links 270 | 271 | When we defined our seeders, we added an ```image_path``` that we haven’t added inside our application. In Laravel, you can store images where ever you want if you have permission to access it from the view. Personally, storing them inside the public folder and creating a symbolic link is the way to go. 272 | 273 | ``` 274 | php artisan storage:link 275 | ``` 276 | 277 | This command will create a link between the ```/public/storage``` folder with the ```/storage``` folder inside the root of our directory. 278 | 279 | Make sure that you download the zip file attached to this specific video, open the ```laravel-cart-cloudways``` folder, and place them inside the ```/public/storage``` folder of your Laravel project. 280 | 281 | ## 8. Building the frontend 282 | 283 | In order to save time, I have already developed the entire frontend of our application, which can be found inside my [laravel-shopping-cart-static](https://github.com/codewithdary/laravel-shopping-cart-static) repository. 284 | 285 | The frontend of any Laravel application can be found inside the ```/resources/views``` folder. In the demonstration of the video, I copy pasted the files separately. This can be done a lot easier if you download the [/resources/views folder](https://github.com/codewithdary/laravel-shopping-cart-static/tree/main/resources/views), and add it inside the project directory. 286 | 287 | This does not work if we run it in the browser, since the methods inside our controllers have not been defined. 288 | 289 | PagesController 290 | 291 | ```php 292 | public function index() 293 | { 294 | return view('index'); 295 | } 296 | ``` 297 | 298 | ProductController 299 | 300 | ```php 301 | public function index() 302 | { 303 | return view('shop.index'); 304 | } 305 | ``` 306 | 307 | ```php 308 | public function show() 309 | { 310 | return view('shop.show') 311 | } 312 | ``` 313 | 314 | CartController 315 | 316 | ```php 317 | public function index() 318 | { 319 | return view(cart.cart); 320 | } 321 | ``` 322 | 323 | ## 9. Making our shop dynamic 324 | 325 | We have added products inside our database, and we also have a static frontend. If we combine those things together, we can basically render dynamic products into our shops. 326 | 327 | This needs to be done from the ```ProductController```, where we need to change the ```index()``` method. 328 | 329 | ```php 330 | public function index() 331 | { 332 | $products = Product::all(); 333 | 334 | return view('shop.index', compact('products')); 335 | } 336 | ``` 337 | 338 | Inside our ```/resources/views/shop/index.blade.php```, we can simply loop over our products. Let’s adjust our parent div with the following. 339 | 340 | ```php 341 |
342 | @foreach ($products as $product) 343 |
344 | … 345 |
346 | @endforeach 347 |
348 | @endsection 349 | ``` 350 | 351 | Don’t forget to replace static content inside the loop with dynamic content from the database. 352 | 353 | ```php 354 | {{ asset($product->image_path) }} 355 | {{ $product->name }} 356 | {{ $product->name }} 357 | {{ $product->details }} 358 | {{ $product->id }} 359 | ``` 360 | 361 | The same things needs to happen for our ```show()``` method and page, because we want to show Products from the database. 362 | 363 | ```php 364 | public function show($id) 365 | { 366 | $product = Product::FindOrFail($id); 367 | 368 | return view('shop.show', compact('product')); 369 | } 370 | ``` 371 | 372 | Also for the ```/resources/views/shop/show.blade.php``` file, Don’t forget to replace static content with dynamic content from the database. 373 | 374 | ```php 375 | {{ asset($product->image_path) }} 376 | {{ $product->name }} 377 | {{ $product->name }} 378 | {{ $product->details }} 379 | {{ $product->id }} 380 | ``` 381 | 382 | ## 10. Saving products to our session 383 | 384 | We will be storing products inside the session of our application because we are not dealing with logged in users. When dealing with a shopping cart on ecommerce sites, you have to keep in mind that you are dealing with critical data, because the entire web app is based on it. 385 | 386 | Since we’re not working with logged in users, we need to store our cart items into the web storage. This can be the cookie, session or local storage. Between these 3, I personally find sessions the most valid method. 387 | 388 | If you want to upgrade this application and add authentication, I recommend you to use a database to store cart items temporary. That allows you to easily trace cart items of a user. 389 | 390 | Before we can add our functionality, we need to define a new route that allows us to click on the ```“add to cart”``` button. 391 | 392 | ```php 393 | Route::get('/add-to-cart/{id}', [CartController::class, 'addToCart'])->name('add.to.cart'); 394 | ``` 395 | 396 | The named route needs to be added inside the “add to cart” button from our ```/resources/views/shop/show.blade.php``` file. 397 | 398 | ```php 399 | 404 | Add To Cart 405 | 406 | ``` 407 | The ```add.to.cart``` route interacts with the ```addToCart()``` method that we still need to define. There are two possible scenarios when adding products to a cart: one where a product already exists and needs to be increased, or a product does not exist in our session, and the session needs to be created. 408 | 409 | ```php 410 | public function addToCart($id) 411 | { 412 | $product = Product::findOrFail($id); 413 | $cartItems = session()->get('cartItems', []); 414 | 415 | if(isset($cartItems[$id])) { 416 | $cartItems[$id]['quantity']++; 417 | } else { 418 | $cartItems[$id] = [ 419 | "image_path" => $product->image_path, 420 | "name" => $product->name, 421 | "brand" => $product->brand, 422 | "details" => $product->details, 423 | "price" => $product->price, 424 | "quantity" => 1 425 | ]; 426 | } 427 | 428 | session()->put('cartItems', $cartItems); 429 | return redirect()->back()->with('success', 'Product added to cart!'); 430 | } 431 | ``` 432 | 433 | You can see the output by adding a ```dd()``` inside the cart method, which output the session. In here, you can see that the array has a key which is equal to the product id, and values that are coming from the database inside of it. 434 | 435 | ```php 436 | public function cart() 437 | { 438 | dd(session('cartItems')); 439 | return view('cart.cart'); 440 | } 441 | ``` 442 | 443 | ## 11. Making our cart dynamic 444 | 445 | With the information that we got inside our session, we should be able to print that data inside the shopping cart. There is a lot of ```HTML``` and ```CSS``` inside the ```/resources/views/cart/cart.blade.php``` file. Try to find the ``````tag, since that’s one row that needs to be outputted dynamically. 446 | 447 | ```php 448 | 449 | … 450 | 451 | ``` 452 | 453 | Our `````` tag and content need to be wrapped inside a foreach loop, that will loop over our products. First, we do need to check if our session has been set. 454 | 455 | 456 | ```php 457 | @if (session('cartItems')) 458 | @foreach (session('cartItems') as $key => $value) 459 | 460 | … 461 | 462 | @endforeach 463 | @endif 464 | ``` 465 | 466 | Once again, don’t forget to change the static content that we have with dynamic data. 467 | 468 | ```php 469 | {{ asset($value['image_path']) }} 470 | {{ $value['name'] }} 471 | {{ $value['name'] }} 472 | {{ $value['details'] }} 473 | {{ $value['price'] }} 474 | {{ $value['quantity'] * $value['price'] }} 475 | ``` 476 | 477 | In most cases, you want to showcase a message if the shopping cart is empty. This can be done by adding an else statement right after the ```endforeach``` directive. 478 | 479 | ```php 480 | @else 481 | 482 |

483 | Shopping cart is empty. 484 |

485 | 486 | ``` 487 | 488 | ## 12. Deleting products from our cart 489 | 490 | Whenever you reach the delete something part in any course, you know that you’re reaching the end of the coding part. 491 | 492 | Just like adding products, we need to make sure that we define a new route to delete products. 493 | 494 | ```php 495 | Route::get('/delete-from-cart/{id}', [CartController::class, 'delete'])->name('delete.from.cart'); 496 | ``` 497 | 498 | Deleting something from the cart needs to be handled inside the ```CartController```. 499 | 500 | ```php 501 | public function delete(Request $request) 502 | { 503 | if($request->id) { 504 | $cartItems = session()->get('cartItems'); 505 | 506 | if(isset($cartItems[$request->id])) { 507 | unset($cartItems[$request->id]); 508 | session()->put('cartItems', $cartItems); 509 | } 510 | 511 | return redirect()->back()->with('success', 'Product deleted successfully'); 512 | } 513 | } 514 | ``` 515 | 516 | To make the button work, we simply need to add the named route, into our delete button from the ```/resources/views/cart/cart.blade.php``` file. 517 | 518 | ```html 519 | 520 | 523 | Delete 524 | 525 | 526 | ``` 527 | 528 | ## 13. Updating the quantity 529 | 530 | When updating the quantity of the shopping cart, we will be performing a POST request which means that our select needs to be wrapped inside a form, that has a @csrf token below of it. 531 | 532 | ```html 533 |
534 | @csrf 535 | @method("PUT") 536 | 546 |
547 | ``` 548 | 549 | This still shouldn’t do the trick for us, because the form has no button so submit the actual content of our select. This can simply be done by adding the onchange on our select, that is an event which will be called after text inside the or