Skip to content

Laravel CRUD in 50 minutes for Beginners from Scratch tutorial by Devtamin. From BASIC Laravel to more ADVANCED concepts! See README. Tutorial Github repo - https://github.com/devtamin/Laravel-CRUD-for-Beginners/tree/master.

Notifications You must be signed in to change notification settings

dialeleven/laravel-crud-in-50-minutes-for-beginners-from-scratch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 

Repository files navigation

With Devtamin's Laravel CRUD tutorial successfully completed going over the basics, we are going above and beyond the tutorial based on what I've built in native PHP in the past in the workplace (e.g. pagination, email functionality, image uploads and resizing, etc...).

The "basic" tutorial covers a fair amount including: routes, controllers, views, models, and dependency injection in the service container.

Beyond the basics, we delve into things like PHPUnit testing in Laravel, Tailwind CSS, Bootstrap, Laravel Vite, middleware authentication, sending email (plain text/HTML, attachments), exporting MySQL data to CSV, handling file/image uploads, pagination and sorting, REST API consumption, and exploring various Laravel Libraries. You can see a list of completed (and planned) additions to the project below.

For naming conventions and other Laravel best practices, Alexey Mezenin's GitHub repo for Laravel Best Practices (scoll down to view the README.md) is an excellent resource.

Expanding Completed Laravel CRUD tutorial (marked as a 1.0 release). What's Next?

✔️ Completed Additions

  • Laravel DB operations: add column to table
  • Style UI: CSS
  • Image upload: Full-size image
  • Image upload: preserve user's image file name
  • Image upload: Generate thumbnail using Intervention Image library (using v3.6.3)
  • Delete product: delete image/thumbnail
  • Create/edit product: link form submission error messages to form field
  • Edit product: image upload field (update -> view/controller) + delete old image/thumbnail
  • Product index: pagination and basic Tailwind CSS styling
  • Export product list to CSV
  • Styling with Tailwind CSS: Product index, Create product, Edit product
  • Common includes with Blade view partials (header/footer) - no longer used in favor of @extends, @section+@yields, @push+@stack unless include is needed
  • Templating using @extends, @section+@yields, @push+@stack, @parent (not used... yet)
  • Add meta tags (description, keywords) and use @section @yield
  • Dashboard UI - responsive, mobile hamburger menu
  • Edit/delete operations: send user back to same paginated page they were on after edit/delete operation instead of page 1 automatically
  • Login: controller, view
  • Organize admin site views into /views/admin/SUBFOLDER (update /routes/web.php accordingly)
  • Create migrations (admins, adminroles) and Models
  • Admin site user admin module (✔️index, ✔️create, ✔️edit, ✔️ delete)
  • Admin Users - Create/Edit - password requirements (min character limit, 1 number, 1 special char)
  • Admin Users - Create/Edit - Password requirement error message output: combine into single error message (currently multiple error messages can be output in list items)
  • Authentication for CRUD app (✔️login form, ✔️login form submission logic, ✔️user logged in check (web.php), ✔️logout
  • Login check for entire CRUD app (check out Laravel Breeze for authentication starter kit?)
  • One public site view/controller/model (/products - public listing of products)
  • Pagination - sorting (asc/desc)
  • Admin site: INNER JOIN query
  • Email functionality in XAMPP/Laravel with Gmail
    • Email with attachement
    • Email - HTML format
    • Email multiple attachments
    • Check if file exists when attaching file and log error if file does not exist
  • API integration: Weather
  • Calendar picker form input
  • PHPUnit testing
    • Products: ✔️Product.index route
    • Forgot/Reset Password: ✔️ Send password reset link
  • Products index - delete product (adjust page user is redirected to if record being deleted is the only product on that page - e.g deleting the only product on page 3 should redirect to page 2)
  • Move records per page pagination value to 'config/app.php'
  • Admin site: Forgot password/reset password
  • Admin login: remember me checkbox (update controller/view)
  • Install Laravel Telescope - Debugging
  • Admin users index/edit/create (output user roles from 'admin_roles' table)
  • Add logged in user's name in sidebar (auth()->user()->name)
  • Restrict adminusers to admins and superadmins
  • Dashboard index page
  • Laravel Libraries
  • SVG nav icon animations (scale up)
  • Truncate long usernames in left nav with ellipses
  • Configure PHPUnit to use separate database for running tests (keep db tables in sync running migrations as needed using php artisan migrate --database=mysql_testing)
  • Refactor email routes into EmailController for separation of concerns/readability of /routes/web.php
  • Laravel Cashier (Stripe) - subscription billing/payment services
    • Stripe integration (tip add 'stripe' => [ 'secret' => env('STRIPE_SECRET'), ], to your /config/services.php file)
      • Stripe Product Catalog output on home page
      • Purchase item link > go to checkout (handle one-time 'payment' vs. 'subscription')

đź“‹ Additional Features To Do

  • Deploy project in Docker
  • Deploy project to Oracle Cloud or similar
  • Redis
    • Configure/connect to Redis locally and using Redis Cloud
    • Redis CRUD
    • Search
    • Advanced
      • Caching, Session Storage - set Laravel cache/session driver
      • Handling more complex data structures and operations
      • Monitor and maintain a Redis instance
  • PHPUnit testing
    • Authenticate admin user
    • Products
    • Forgot/Reset Password: password.reset, password.update
  • Email CC/BCC - ensure CC/BCC list is not visible in email/header (using Mailtrap.io example )
  • Email functionality with Mailtrap.io?
  • Products: search functionality (search for product name, description, price - slider(?), description)
  • "You are here" sidebar nav indicator
  • Breadcrumb links?
  • Style UI: Frameworks (e.g. ✔️Tailwind CSS, ✔️Bootstrap, Vue, Vueform, react-hook-form)
  • Hover over thumbnail to show full size image
  • Check out Laravel Libraries

Redis Installation Notes

You can either install Redis locally or use their free 30MB Redis Cloud database as of this writing (June 2024) (limit of 1 DB it seems?). Be aware some free offerings could change to paid only in the future. I went for the free Redis Cloud DB to get started quickerat first. After I tried a local Redis on Windows install outlined below.

Install Redis on Windows

  1. To install Redis on Windows, you'll first need to enable WSL2 (Windows Subsystem for Linux). WSL2 lets you run Linux binaries natively on Windows. For this method to work, you'll need to be running Windows 10 version 2004 and higher or Windows 11.

  2. Next you can Install Redis on Windows following these instructions.

Wasn't bad at all. I chose to install Ubuntu for WSL. Started up the redis server through by Ubuntu WSL command line:

sudo service redis-server start

Then tested the 'ping' command which should return the following:

127.0.0.1:6379> ping
PONG

Install the Redis PHP extension

  • Download the Redis PHP extension at https://pecl.php.net/package/redis (I'm using XAMPP on Windows 11, so Windows users select the DLL link. Usually the thread safe (TS) version.)
  • Copy the php_redis.dll to your PHP ext dir (e.g. c:\xampp\php\ext). I copied the php_redis.pdb to ext just in case.
  • Restart Apache

Install the Laravel Redis Library

composer require predis/predis ensure there is no error output at the beginning of the composer command execution. Easy to miss if your're in VS Code terminal and the window pane is small (happened to me).

Run a test route for Redis

Example:

// Redis test route
Route::get('/redis', function () {
    #Redis::set('key', 'value');
    
    $redis = app()->make('redis');
    $redis->set('foo', 'bar');
    return $redis->get('foo');
});

This should retun 'foo' if successful!

Redis Insight

Redis Insight is a handy tool for browsing/viewing your Redis databases, CLI tool, Command Helper, etc. I'd recommend installing this after you get Redis on Windows and it configured in your Laravel app (.env, /config/database.php).

Laravel Cashier - Installation/Usage

Should be no issues running the commands.

Copy/paste your Stripe API keys from the Stripe dashboard developer section (https://dashboard.stripe.com/test/apikeys - note that the URL may change in the future - Log into your account and look under "Developers" and API keys) and add the Stripe API key/secrets in your Laravel .env file:

STRIPE_KEY=your-stripe-key
STRIPE_SECRET=your-stripe-secret
STRIPE_WEBHOOK_SECRET=your-stripe-webhook-secret

Update Your APP_URL in .env

If you haven't changed the APP_URL in your .env file, it probably looks like:

APP_URL=http://localhost

Change it to whatever localhost URL you have configured in your environment. I'm using XAMPP and Apache and I adjusted my APP_URL to:

APP_URL=https://laravelcrud.test

For local development testing, you'll probably need the Stripe CLI tool (https://github.com/stripe/stripe-cli). Instructions are available on the GitHub repo. Windows install instructions are below for stripe-cli.

Install Scoop for Windows - https://scoop.sh/

Open a PowerShell terminal (version 5.1 or later) and from the PS C:> prompt, run:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression

Install Stripe CLI via Scoop Package Manager

scoop bucket add stripe https://github.com/stripe/scoop-stripe-cli.git
scoop install stripe

Create Laravel Cashier Stripe Webook

php artisan cashier:webhook

You should see something like:

 INFO  The Stripe webhook was created successfully. Retrieve the webhook secret in your Stripe dashboard and define it as an environment variable.

Follow the configuration steps for #Billable Model.

On to the Quickstart (finally!).

Run the Stripe CLI command to send all Stripe events in test mode to your local webhook endpoint. Adjust your --forward-to URL according to your local dev environment.

stripe listen --forward-to http://laravelcrud.test

Create your views for /checkout/success, /checkout/cancel. Create routes for /checkout, /checkout/success, and /checkout/cancel, then test!

Sample route for /checkout

Route::get('/checkout', function (Request $request) {
      $stripePriceId = 'price_1PQjb7P3S64d6hFr5zeIVmjU'; // adjust this value according to your Stripe product id (Dashaboard > Product catalogue > Add product. Click on product name > click on '...' to the right of the price > Copy price ID (this will look like 'price_abcdefg'_
      $quantity = 1;
  
      Stripe::setApiKey(env('STRIPE_SECRET'));
  
      try {
          $session = Session::create([
              'payment_method_types' => ['card'],
              'line_items' => [[
                  'price' => $stripePriceId,
                  /*
                  'price_data' => [
                      'currency' => 'usd',
                      'unit_amount' => $quantity * 1000,
                      'product_data' => [
                          'name' => 'Deluxe Album',
                      ],
                  ],
                  */
                  'quantity' => $quantity,
              ]],
              'mode' => 'payment',
              'success_url' => route('checkout-success'),
              'cancel_url' => route('checkout-cancel'),
          ]);
  
          return new RedirectResponse($session->url);
      } catch (\Exception $e) {
          return back()->withErrors(['error' => $e->getMessage()]);
      }
})->name('checkout');

How to Install Intervention Image Library

Install Intervention Image with Composer by running the following command. $ composer require intervention/image

How To Use Intervention Image

Code Example from https://image.intervention.io/v3

use Intervention\Image\ImageManager;
use Intervention\Image\Drivers\Gd\Driver;

// create image manager with desired driver
$manager = new ImageManager(new Driver());

// read image from file system
$image = $manager->read('images/example.jpg');

// resize image proportionally to 300px width
$image->scale(width: 300);

// insert watermark
$image->place('images/watermark.png');

// save modified image in new format 
$image->toPng()->save('images/foo.png');

Setting Up This Project Locally

This project currently runs on XAMPP 8.2.4 (PHP 8.2.4) and Laravel 11.8).

Clone the repository

git clone https://github.com/dialeleven/laravel-crud-in-50-minutes-for-beginners-from-scratch

Navigate To Project Directory

cd app-crud

Install Dependencies (including Tailwind CSS)

npm install

Install Required '/vendor' Dependencies (install composer if not already installed)

composer update

Copy '.env.example' as '.env'

Adjust your MySQL details in your new .env file now or after the next two steps.

Run 'php artisan key:generate'

php artisan key:generate If trying to access the application via browser first, you may get a 'ERROR: No application encryption key has been specified. {"exception":"[object] (Illuminate\Encryption\MissingAppKeyException(code: 0): No application encryption key has been specified. at G:\...\\vendor\laravel\framework\src\Illuminate\Encryption\EncryptionServiceProvider.php:83)' message. The above command should help resolve the issue.

Create MySQL Database 'app-crud'

Use mysql command line, phpMyAdmin, HeidiSQL, etc to create the database.

Update .env with MySQL Details (Adjust Below Accordingly)

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306 # Ensure your port is correct! With multiple XAMPP installs (PHP 5.6 and PHP 8.2), I had to run XAMPP PHP 8.2 with MySQL on port 3308!)
DB_DATABASE=app-crud
DB_USERNAME=root
DB_PASSWORD=

Create Link from 'public/storage' to 'storage/app/public' (if it doesn't already exist)

cd /path/to/your/laravel/project
Artisan::call('storage:link');

A return code of zero (0) indicates the command executed successfully and the link should have been created which you can check in your file manager.

Test Accessing The Home Page '/' and 'products/' (e.g. http://localhost/products or http://laravel.localhost/products)

If you get any 500 server errors, check 'storage/logs/laravel.log' or your Apache error_log. Once any error(s) are resolved, you should be up and running!

Update Tailwind CSS/JS If Adding New TW Classes

Run npm run build within the 'app-crud' directory.

If Using PHPUnit To Run Tests, Create MySQL DB for Tests Only

Some PHPUnit tests use use RefreshDatabase; which will remove existing DB table data, but configured to use a different PHPUnit test database to avoid this. This project uses the databases app-crud and app-crud-phpunit-tests.

See the following files for values to customize if needed:

  • .env.example (DB_TEST_* fields)
  • /config/database.php ('mysql_testing' entry)
  • phpunit.xml (<env name="DB_CONNECTION" value="mysql_testing"/>)