├── .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 |
483 | Shopping cart is empty. 484 |
485 |