1. Introduction to Laravel

What is Laravel?

Laravel is a free, open-source PHP web framework designed for building web applications following the MVC (Model-View-Controller) architectural pattern.

Key Features:
  • Eloquent ORM for database operations
  • Blade templating engine
  • Artisan command-line interface
  • Built-in authentication and authorization
  • Database migrations and seeding

2. Install and Setup Laravel Environment

Install PHP the Easy Way

Visit php.new to install PHP 8.4 + Composer + Laravel with automatic PATH configuration:

php.new features:
  • Installs PHP 8.4 + Composer + Laravel
  • Configures your PATH automatically
  • Works on Windows, Mac, and Linux
  • No manual configuration needed

Install Node.js on Windows using NVM

# Download and install nvm-windows from the official repository:
https://github.com/coreybutler/nvm-windows/releases/download/1.2.2/nvm-setup.exe

# After installing nvm, open a new terminal and run:
nvm install lts
nvm use lts

# Verify Node.js and npm installation:
node -v
npm -v

Create New Laravel Project

laravel new bookstore

When prompted for starter kits or authentication scaffolding, choose None to start with a clean Laravel installation.

Install Laravel UI (Bootstrap Auth Scaffolding)

After creating your Laravel project, install Laravel UI for authentication scaffolding and build frontend assets:

composer require laravel/ui
php artisan ui bootstrap --auth
npm install
npm run build

Create Database

Create a new database named bookstore before configuring your environment. You can do this using the MySQL CLI or phpMyAdmin:

  • Using MySQL CLI:
    mysql -u root -p
    CREATE DATABASE bookstore;
  • Using phpMyAdmin:
    1. Log in to phpMyAdmin in your browser.
    2. Click New in the sidebar.
    3. Enter bookstore as the database name and click Create.

Configure Environment

Edit .env file for database configuration:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=bookstore
DB_USERNAME=root
DB_PASSWORD=your_password

Start Development Server

# Start the development server only
php artisan serve

Verify Installation

Visit http://localhost:8000 in your browser. You should see the Laravel welcome page.

3. MVC Pattern

Understanding MVC Pattern

Laravel follows the Model-View-Controller (MVC) architectural pattern, which separates the application into three main components:

MVC Components:
  • Model: Represents the data structure and business logic. Handles database operations and data validation.
  • View: Displays the data to users. Contains the presentation logic and user interface.
  • Controller: Processes user requests, interacts with models, and returns views. Acts as an intermediary between models and views.
app/
├── Models/           # Models (Data & Business Logic)
├── Http/
│   └── Controllers/  # Controllers (Request Processing)
└── resources/
└── views/        # Views (Presentation Layer)

4. Creating an App Using Laravel

Create Book Model, Migration, Resource Controller

php artisan make:model Book -mcr
php artisan make:model Order -mcr

The flags used are:
-m: Create a migration file for the model.
-c: Create a controller for the model.
-r: Create a resource controller for the model.

Define Book Migration

Edit database/migrations/xxxx_create_books_table.php:

public function up()
{
    Schema::create('books', function (Blueprint $table) {
        $table->id();
        $table->string('title');
        $table->string('author');
        $table->text('description');
        $table->decimal('price', 8, 2);
        $table->string('cover_image')->nullable();
        $table->integer('stock');
        $table->timestamps();
    });
}

Define Order Migration

Edit database/migrations/xxxx_create_orders_table.php:

public function up()
{
    Schema::create('orders', function (Blueprint $table) {
        $table->id();
        $table->foreignId('user_id')->constrained();
        $table->foreignId('book_id')->constrained();
        $table->unsignedInteger('quantity')->default(1);
        $table->string('customer_name');
        $table->string('customer_email');
        $table->string('customer_phone')->nullable();
        $table->string('address_line1');
        $table->string('address_line2')->nullable();
        $table->string('city');
        $table->string('state');
        $table->string('zip_code');
        $table->text('notes')->nullable();
        $table->decimal('total_price', 10, 2);
        $table->enum('status', ['pending', 'processing', 'shipped', 'delivered', 'cancelled'])->default('pending');
        $table->timestamps();
    });
}

Run Migration

php artisan migrate

Define Book Model

Edit app/Models/Book.php:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
    protected $fillable = [
        'title', 'author', 'description', 
        'price', 'cover_image', 'stock'
    ];
}

Define Order Model

Edit app/Models/Order.php:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Order extends Model
{
    protected $fillable = [
        'user_id', 'book_id', 'quantity', 'customer_name', 'customer_email', 
        'customer_phone', 'address_line1', 'address_line2', 'city', 'state', 
        'zip_code', 'notes', 'total_price', 'status'
    ];
}

5. App Design in Laravel

Understanding Blade Templates

Blade is Laravel's powerful templating engine that provides a clean, simple syntax for creating views. Blade templates are stored in the resources/views directory with a .blade.php extension.

Key Blade Features:
  • Template Inheritance: Use @extends and @section for layout inheritance
  • Data Display: Use {{ }} for escaped output and {!! !!} for unescaped HTML
  • Control Structures: @if, @foreach, @while for logic
  • Includes: @include to include other views
  • Components: Reusable UI components with @component
// Basic Blade syntax examples
{{ $variable }}                    // Escaped output
{!! $html !!}                     // Unescaped HTML
@if($condition) ... @endif        // Conditional
@foreach($items as $item) ... @endforeach  // Loops
@extends('layouts.app')           // Template inheritance
@section('content') ... @endsection  // Content sections

Blade Views Structure

resources/
└── views/
├── admin/
│   ├── books/
│   │   ├── index.blade.php
│   │   ├── create.blade.php
│   │   └── edit.blade.php
│   └── orders/
│       ├── index.blade.php
│       ├── edit.blade.php
├── books/
│   ├── index.blade.php
│   └── show.blade.php
├── orders/
│   ├── create.blade.php
│   └── index.blade.php
└── layouts/
└── app.blade.php

6. Creating Blade Views

Admin Books Create View

Create resources/views/admin/books/create.blade.php:

@extends('layouts.app')

@section('title', 'Admin - Add New Book')

@section('content')
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">Add New Book</div>
                <div class="card-body">
                    <form action="/" method="POST" enctype="multipart/form-data">
                        @csrf
                        <div class="mb-3">
                            <label for="title" class="form-label">Title</label>
                            <input type="text" class="form-control @error('title') is-invalid @enderror" id="title" name="title" value="{{ old('title') }}" required>
                            @error('title')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="mb-3">
                            <label for="author" class="form-label">Author</label>
                            <input type="text" class="form-control @error('author') is-invalid @enderror" id="author" name="author" value="{{ old('author') }}" required>
                            @error('author')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="mb-3">
                            <label for="description" class="form-label">Description</label>
                            <textarea class="form-control @error('description') is-invalid @enderror" id="description" name="description" rows="4" required>{{ old('description') }}</textarea>
                            @error('description')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="mb-3">
                            <label for="price" class="form-label">Price</label>
                            <input type="number" step="0.01" class="form-control @error('price') is-invalid @enderror" id="price" name="price" value="{{ old('price') }}" required>
                            @error('price')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="mb-3">
                            <label for="stock" class="form-label">Stock</label>
                            <input type="number" class="form-control @error('stock') is-invalid @enderror" id="stock" name="stock" value="{{ old('stock') }}" required>
                            @error('stock')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="mb-3">
                            <label for="cover_image" class="form-label">Cover Image</label>
                            <input type="file" class="form-control @error('cover_image') is-invalid @enderror" id="cover_image" name="cover_image">
                            @error('cover_image')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="d-flex justify-content-between">
                            <a href="/" class="btn btn-secondary">Cancel</a>
                            <button type="submit" class="btn btn-primary">Create Book</button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
@endsection

Admin Books Index View

Create resources/views/admin/books/index.blade.php:

@extends('layouts.app')

@section('title', 'Admin - Books')

@section('content')
    <div class="d-flex justify-content-between align-items-center mb-4">
        <h1>Manage Books</h1>
        <a href="/" class="btn btn-primary">Add New Book</a>
    </div>

    <div class="table-responsive">
        <table class="table table-striped">
            <thead>
                <tr>
                    <th>Title</th>
                    <th>Author</th>
                    <th>Price</th>
                    <th>Stock</th>
                    <th>Actions</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>The Great Gatsby</td>
                    <td>F. Scott Fitzgerald</td>
                    <td>$19.99</td>
                    <td>15</td>
                    <td>
                        <a href="/edit" class="btn btn-sm btn-warning">Edit</a>
                        <form action="/" method="POST" class="d-inline">
                            @csrf
                            @method('DELETE')
                            <button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Are you sure?')">Delete</button>
                        </form>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
@endsection

Admin Books Edit View

Create resources/views/admin/books/edit.blade.php:

@extends('layouts.app')

@section('title', 'Admin - Edit Book')

@section('content')
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">Edit Book</div>
                <div class="card-body">
                    <form action="/" method="POST" enctype="multipart/form-data">
                        @csrf
                        @method('PUT')
                        <div class="mb-3">
                            <label for="title" class="form-label">Title</label>
                            <input type="text" class="form-control @error('title') is-invalid @enderror" id="title" name="title" value="{{ old('title', 'The Great Gatsby') }}" required>
                            @error('title')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="mb-3">
                            <label for="author" class="form-label">Author</label>
                            <input type="text" class="form-control @error('author') is-invalid @enderror" id="author" name="author" value="{{ old('author', 'F. Scott Fitzgerald') }}" required>
                            @error('author')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="mb-3">
                            <label for="description" class="form-label">Description</label>
                            <textarea class="form-control @error('description') is-invalid @enderror" id="description" name="description" rows="4" required>{{ old('description', 'A classic American novel about the Jazz Age and the American Dream.') }}</textarea>
                            @error('description')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="mb-3">
                            <label for="price" class="form-label">Price</label>
                            <input type="number" step="0.01" class="form-control @error('price') is-invalid @enderror" id="price" name="price" value="{{ old('price', '19.99') }}" required>
                            @error('price')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="mb-3">
                            <label for="stock" class="form-label">Stock</label>
                            <input type="number" class="form-control @error('stock') is-invalid @enderror" id="stock" name="stock" value="{{ old('stock', '15') }}" required>
                            @error('stock')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="mb-3">
                            <label for="cover_image" class="form-label">Cover Image</label>
                            <input type="file" class="form-control @error('cover_image') is-invalid @enderror" id="cover_image" name="cover_image">
                            <div class="mt-2">
                                <img src="{{ asset('storage/covers/great-gatsby.jpg') }}" alt="Current cover" style="max-width: 200px;">
                            </div>
                            @error('cover_image')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="d-flex justify-content-between">
                            <a href="/" class="btn btn-secondary">Cancel</a>
                            <button type="submit" class="btn btn-primary">Update Book</button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
@endsection

User Books Index View

Create resources/views/books/index.blade.php:

@extends('layouts.app')

@section('title', 'Bookstore - All Books')

@section('content')
    <div class="container">
        <h1 class="mb-4">Our Book Collection</h1>

        <div class="row">
            <div class="col-md-4 mb-4">
                <div class="card h-100">
                    <div class="card-img-top bg-light d-flex align-items-center justify-content-center" style="height: 300px;">
                        <i class="fas fa-book fa-3x text-muted"></i>
                        <img src="https://dummyimage.com/400" class="h-100 w-100 object-fit-cover"/>
                    </div>
                    <div class="card-body">
                        <h5 class="card-title">The Great Gatsby</h5>
                        <p class="card-text text-muted">by F. Scott Fitzgerald</p>
                        <p class="card-text">A classic American novel about the Jazz Age and the American Dream.</p>
                        <div class="d-flex justify-content-between align-items-center">
                            <span class="h5 text-primary mb-0">$19.99</span>
                            <a href="/" class="btn btn-outline-primary">View Details</a>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
@endsection

User Books Show View

Create resources/views/books/show.blade.php:

@extends('layouts.app')

@section('title', 'The Great Gatsby')

@section('content')
    <div class="container">
        <nav aria-label="breadcrumb">
            <ol class="breadcrumb">
                <li class="breadcrumb-item"><a href="/">Books</a></li>
                <li class="breadcrumb-item active" aria-current="page">The Great Gatsby</li>
            </ol>
        </nav>

        <div class="row">
            <div class="col-md-4">
                <div class="bg-light rounded d-flex align-items-center justify-content-center" style="height: 400px;">
                    <i class="fas fa-book fa-5x text-muted"></i>
                    <img src="https://dummyimage.com/400" class="h-100 w-100 object-fit-cover"/>
                </div>
            </div>
            <div class="col-md-8">
                <h1 class="mb-3">The Great Gatsby</h1>
                <p class="text-muted h5 mb-3">by F. Scott Fitzgerald</p>
                <p class="mb-4">A classic American novel about the Jazz Age and the American Dream.</p>

                <div class="row mb-4">
                    <div class="col-md-6">
                        <div class="card">
                            <div class="card-body text-center">
                                <h3 class="text-primary mb-0">$19.99</h3>
                                <p class="text-muted mb-0">Price</p>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-6">
                        <div class="card">
                            <div class="card-body text-center">
                                <h3 class="text-success mb-0">15</h3>
                                <p class="text-muted mb-0">In Stock</p>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="d-flex gap-2">
                    <a href="/" class="btn btn-outline-secondary">Back to Books</a>
                    <button class="btn btn-primary">Add to Cart</button>
                </div>
            </div>
        </div>
    </div>
@endsection

Order Create View

Create resources/views/orders/create.blade.php for the order placement form:

@extends('layouts.app')

@section('title', 'Place Order')

@section('content')
    <div class="container">
        <nav aria-label="breadcrumb">
            <ol class="breadcrumb">
                <li class="breadcrumb-item"><a href="/">Books</a></li>
                <li class="breadcrumb-item"><a href="/books/book">Book</a></li>
                <li class="breadcrumb-item active" aria-current="page">Place Order</li>
            </ol>
        </nav>

        <div class="row">
            <div class="col-lg-8">
                <div class="card">
                    <div class="card-header">
                        <h4 class="mb-0">Order Information</h4>
                    </div>
                    <div class="card-body">
                        <form method="get" action="/orders">
                            @csrf

                            <!-- Customer Information -->
                            <div class="mb-4">
                                <h5 class="border-bottom pb-2">Customer Information</h5>
                                <div class="row">
                                    <div class="col-md-6 mb-3">
                                        <label for="first_name" class="form-label">First Name *</label>
                                        <input type="text" class="form-control @error('first_name') is-invalid @enderror"
                                               id="first_name" name="first_name" value="{{ old('first_name') }}" required>
                                        @error('first_name')
                                            <div class="invalid-feedback">{{ $message }}</div>
                                        @enderror
                                    </div>
                                    <div class="col-md-6 mb-3">
                                        <label for="last_name" class="form-label">Last Name *</label>
                                        <input type="text" class="form-control @error('last_name') is-invalid @enderror"
                                               id="last_name" name="last_name" value="{{ old('last_name') }}" required>
                                        @error('last_name')
                                            <div class="invalid-feedback">{{ $message }}</div>
                                        @enderror
                                    </div>
                                </div>
                                <div class="mb-3">
                                    <label for="email" class="form-label">Email Address *</label>
                                    <input type="email" class="form-control @error('email') is-invalid @enderror"
                                           id="email" name="email" value="{{ old('email') }}" required>
                                    @error('email')
                                        <div class="invalid-feedback">{{ $message }}</div>
                                    @enderror
                                </div>
                                <div class="mb-3">
                                    <label for="phone" class="form-label">Phone Number</label>
                                    <input type="tel" class="form-control @error('phone') is-invalid @enderror"
                                           id="phone" name="phone" value="{{ old('phone') }}">
                                    @error('phone')
                                        <div class="invalid-feedback">{{ $message }}</div>
                                    @enderror
                                </div>
                            </div>

                            <!-- Shipping Address -->
                            <div class="mb-4">
                                <h5 class="border-bottom pb-2">Shipping Address</h5>
                                <div class="mb-3">
                                    <label for="address_line1" class="form-label">Address Line 1 *</label>
                                    <input type="text" class="form-control @error('address_line1') is-invalid @enderror"
                                           id="address_line1" name="address_line1" value="{{ old('address_line1') }}" required>
                                    @error('address_line1')
                                        <div class="invalid-feedback">{{ $message }}</div>
                                    @enderror
                                </div>
                                <div class="mb-3">
                                    <label for="address_line2" class="form-label">Address Line 2</label>
                                    <input type="text" class="form-control @error('address_line2') is-invalid @enderror"
                                           id="address_line2" name="address_line2" value="{{ old('address_line2') }}">
                                    @error('address_line2')
                                        <div class="invalid-feedback">{{ $message }}</div>
                                    @enderror
                                </div>
                                <div class="row">
                                    <div class="col-md-6 mb-3">
                                        <label for="city" class="form-label">City *</label>
                                        <input type="text" class="form-control @error('city') is-invalid @enderror"
                                               id="city" name="city" value="{{ old('city') }}" required>
                                        @error('city')
                                            <div class="invalid-feedback">{{ $message }}</div>
                                        @enderror
                                    </div>
                                    <div class="col-md-3 mb-3">
                                        <label for="state" class="form-label">State *</label>
                                        <input type="text" class="form-control @error('state') is-invalid @enderror"
                                               id="state" name="state" value="{{ old('state') }}" required>
                                        @error('state')
                                            <div class="invalid-feedback">{{ $message }}</div>
                                        @enderror
                                    </div>
                                    <div class="col-md-3 mb-3">
                                        <label for="zip_code" class="form-label">ZIP Code *</label>
                                        <input type="text" class="form-control @error('zip_code') is-invalid @enderror"
                                               id="zip_code" name="zip_code" value="{{ old('zip_code') }}" required>
                                        @error('zip_code')
                                            <div class="invalid-feedback">{{ $message }}</div>
                                        @enderror
                                    </div>
                                </div>
                            </div>

                            <!-- Order Notes -->
                            <div class="mb-4">
                                <label for="notes" class="form-label">Order Notes (Optional)</label>
                                <textarea class="form-control @error('notes') is-invalid @enderror" id="notes" name="notes" rows="3"
                                          placeholder="Any special instructions or notes for your order...">{{ old('notes') }}</textarea>
                                @error('notes')
                                    <div class="invalid-feedback">{{ $message }}</div>
                                @enderror
                            </div>

                            <div class="d-flex justify-content-end">
                                <button type="submit" class="btn btn-primary btn-lg">Make Payment</button>
                            </div>
                        </form>
                    </div>
                </div>
            </div>

            <div class="col-lg-4">
                <div class="card">
                    <div class="card-header">
                        <h5 class="mb-0">Order Summary</h5>
                    </div>
                    <div class="card-body">
                        <!-- Sample order items - in real app, this would come from session/cart -->
                        <div class="d-flex justify-content-between align-items-center mb-2">
                            <div class="d-flex align-items-center gap-2">
                                <img src="https://dummyimage.com/40x60" alt="The Great Gatsby" class="rounded"
                                     style="width: 40px; height: 60px; object-fit: cover;">
                                <div>
                                    <span>The Great Gatsby</span>
                                    <div class="d-flex align-items-center gap-2 mt-1">
                                        <button type="button" class="btn btn-sm btn-outline-secondary"
                                                onclick="updateQuantity(-1)">-</button>
                                        <span class="quantity-display">1</span>
                                        <button type="button" class="btn btn-sm btn-outline-secondary"
                                                onclick="updateQuantity(1)">+</button>
                                    </div>
                                </div>
                            </div>
                            <span class="price-display">$19.99</span>
                        </div>

                        <hr>

                        <div class="d-flex justify-content-between mb-2">
                            <span>Subtotal</span>
                            <span class="subtotal-amount">$19.99</span>
                        </div>
                        <div class="d-flex justify-content-between mb-2">
                            <span>Shipping</span>
                            <span>$5.99</span>
                        </div>
                        <div class="d-flex justify-content-between mb-2">
                            <span>Tax</span>
                            <span class="tax-amount">$2.00</span>
                        </div>

                        <hr>

                        <div class="d-flex justify-content-between fw-bold">
                            <span>Total</span>
                            <span class="total-amount">$27.98</span>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
        let quantity = 1;
        const basePrice = 19.99;

        function updateQuantity(change) {
            const newQuantity = quantity + change;
            if (newQuantity >= 1) {
                quantity = newQuantity;
                document.querySelector('.quantity-display').textContent = quantity;

                const totalPrice = (basePrice * quantity).toFixed(2);
                document.querySelector('.price-display').textContent = `$${totalPrice}`;

                // Update subtotal
                const subtotal = (basePrice * quantity).toFixed(2);
                document.querySelector('.subtotal-amount').textContent = `$${subtotal}`;

                // Update tax (assuming 10% tax rate)
                const tax = (basePrice * quantity * 0.1).toFixed(2);
                document.querySelector('.tax-amount').textContent = `$${tax}`;

                // Update total
                const shipping = 5.99;
                const total = (parseFloat(subtotal) + parseFloat(tax) + shipping).toFixed(2);
                document.querySelector('.total-amount').textContent = `$${total}`;
            }
        }
    </script>
@endsection

Order Index View

Create resources/views/orders/index.blade.php for displaying order history:

@extends('layouts.app')

@section('title', 'Order History')

@section('content')
    <div class="container mt-4">
        <div class="row">
            <div class="col-12">
                <h2>Order History</h2>
                <p class="text-muted">Your book orders</p>
            </div>
        </div>

        <!-- Order 1 -->
        <div class="row mb-3">
            <div class="col-12">
                <div class="card">
                    <div class="card-body">
                        <div class="row">
                            <div class="col-md-8">
                                <div class="d-flex align-items-center mb-2">
                                    <span class="badge bg-success me-2">Delivered</span>
                                    <small class="text-muted">Order #ORD-2024-001</small>
                                </div>
                                <h5>The Great Gatsby</h5>
                                <p class="text-muted mb-1">F. Scott Fitzgerald</p>
                                <p class="text-muted mb-0">Paperback • 180 pages</p>
                            </div>
                            <div class="col-md-4">
                                <div class="text-end">
                                    <p class="mb-1"><strong>$12.99</strong></p>
                                    <p class="text-muted small mb-2">Ordered: Dec 15, 2024</p>
                                    <p class="text-muted small mb-3">Delivered: Dec 18, 2024</p>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Pagination -->
        <div class="row">
            <div class="col-12">
                <nav>
                    <ul class="pagination justify-content-center">
                        <li class="page-item disabled">
                            <a class="page-link" href="#">Previous</a>
                        </li>
                        <li class="page-item active"><a class="page-link" href="#">1</a></li>
                        <li class="page-item"><a class="page-link" href="#">2</a></li>
                        <li class="page-item"><a class="page-link" href="#">3</a></li>
                        <li class="page-item">
                            <a class="page-link" href="#">Next</a>
                        </li>
                    </ul>
                </nav>
            </div>
        </div>
    </div>
@endsection

7. Navigation and Routing

How Routes Work in Laravel

Routes in Laravel define the URL patterns and map them to controller actions. The routes/web.php file contains all web routes for your application.

// Basic route structure
Route::method('url', [Controller::class, 'action']);

// Examples:
Route::view('/', 'home');
Route::post('/users', [UserController::class, 'store']);
Route::put('/users/{id}', [UserController::class, 'update']);
Route::delete('/users/{id}', [UserController::class, 'destroy']);

// Define named route
Route::get('/books/{id}', [BookController::class, 'show'])->name('books.show');

Resource Routes

Laravel provides resource routes that automatically create all CRUD routes for a resource:

// Creates all resource routes
Route::resource('books', BookController::class);

// This creates the following routes:
// GET    /books              → index()   (list all books)
// GET    /books/create       → create()  (show create form)
// POST   /books              → store()   (save new book)
// GET    /books/{id}         → show()    (show specific book)
// GET    /books/{id}/edit    → edit()    (show edit form)
// PUT    /books/{id}         → update()  (update book)
// DELETE /books/{id}         → destroy() (delete book)

Middleware in Routes

Middleware can be applied to routes to filter HTTP requests:

// Apply middleware to single route
Route::get('/admin', [AdminController::class, 'index'])->middleware('auth');

// Apply multiple middleware
Route::get('/admin', [AdminController::class, 'index'])
    ->middleware(['auth', 'admin']);

// Apply to route group
Route::middleware(['auth', 'verified'])->group(function () {
    Route::get('/profile', [ProfileController::class, 'show']);
    Route::put('/profile', [ProfileController::class, 'update']);
});

8. Controllers in Laravel

BookController

Create app/Http/Controllers/BookController.php:

<?php

namespace App\Http\Controllers;

use App\Models\Book;

class BookController extends Controller
{
    public function index()
    {
        $books = Book::all();
        return view('books.index', compact('books'));
    }

    public function show(Book $book)
    {
        return view('books.show', compact('book'));
    }
}

AdminBookController

Create app/Http/Controllers/AdminBookController.php:

<?php

namespace App\Http\Controllers;

use App\Models\Book;
use Illuminate\Http\Request;

class AdminBookController extends Controller
{
    public function index()
    {
        $books = Book::all();
        return view('admin.books.index', compact('books'));
    }

    public function create()
    {
        return view('admin.books.create');
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'title' => 'required|string|max:255',
            'author' => 'required|string|max:255',
            'description' => 'required|string',
            'price' => 'required|numeric|min:0',
            'stock' => 'required|integer|min:0',
            'cover_image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048'
        ]);

        Book::create($validated);
        return redirect()->route('admin.books.index');
    }

    public function edit(Book $book)
    {
        return view('admin.books.edit', compact('book'));
    }

    public function update(Request $request, Book $book)
    {
        $validated = $request->validate([
            'title' => 'required|string|max|max:255',
            'author' => 'required|string|max:255',
            'description' => 'required|string',
            'price' => 'required|numeric|min:0',
            'stock' => 'required|integer|min:0',
            'cover_image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048'
        ]);

        if ($request->hasFile('cover_image')) {
            // Delete old image if exists
            if ($book->cover_image) {
                Storage::disk('public')->delete($book->cover_image);
            }
            $path = $request->file('cover_image')->store('covers', 'public');
            $validated['cover_image'] = $path;
        }

        $book->update($validated);
        return redirect()->route('admin.books.index');
    }

    public function destroy(Book $book)
    {
        $book->delete();
        return redirect()->route('admin.books.index');
    }
}

OrderController

Create app/Http/Controllers/OrderController.php:

<?php

namespace App\Http\Controllers;

use App\Models\Order;
use Illuminate\Http\Request;

class OrderController extends Controller
{
    public function create()
    {
        return view('orders.create');
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'book_id' => 'required|exists:books,id',
            'quantity' => 'required|integer|min:1'
        ]);

        Order::create($validated);
        return redirect()->route('orders.index');
    }
}

AdminOrderController

Create app/Http/Controllers/AdminOrderController.php:

<?php

namespace App\Http\Controllers;

use App\Models\Order;

class AdminOrderController extends Controller
{
    public function index()
    {
        $orders = Order::with('book')->get();
        return view('admin.orders.index', compact('orders'));
    }

    public function show(Order $order)
    {
        return view('admin.orders.show', compact('order'));
    }
}

9. Deploying Your Laravel Application

Publish Project to GitHub

First, initialize a Git repository and push your project to GitHub:

# Initialize Git repository
git init

# Add all files to Git
git add .

# Create initial commit
git commit -m "Initial Laravel bookstore project"

# Add GitHub remote (replace with your repository URL)
git remote add origin https://github.com/yourusername/bookstore.git

# Push to GitHub
git push -u origin main
Before pushing to GitHub:
  • Make sure .env is in your .gitignore file
  • Create a .env.example file with sample configuration
  • Update APP_ENV=production in your production environment

Create Account at Laravel Cloud

Laravel Cloud is the fastest way to deploy and scale Laravel applications without managing servers:

# Visit Laravel Cloud
https://cloud.laravel.com

# Sign up for an account
# Connect your GitHub account
# No server management needed!
Laravel Cloud Features:
  • One-click autoscaling (2-4 replicas)
  • Built-in databases (MySQL & Serverless Postgres)
  • Redis-compatible caching
  • S3-compatible object storage
  • Automatic SSL certificates
  • DDoS protection and edge caching
  • Push-to-deploy from Git

Deploy Your Application

Deploy your Laravel application in under 60 seconds with Laravel Cloud:

# In Laravel Cloud dashboard:

# 1. Click "New application"
# 2. Select your GitHub repository
# 3. Choose your application name
# 4. Cloud automatically:
#    - Installs dependencies
#    - Runs migrations
#    - Sets up environment
#    - Deploys your app
# 5. Your app is live in seconds!

# For automatic deployments:
# Just push to your main branch
git push origin main
# Cloud automatically redeploys