Post

My Journey within the Embedded Domain part 9

My Journey within the Embedded Domain part 9

2025

Overview

This year, 2025, I took it upon myself to complete the hardware design and manufacturing setup for a stealth project that I had been working on since 2022. After at least 7 PCBA revisions of the design, which included designs for USB-UART, DC-DC buck converter, RTC, Temperature sensor, SMD Buzzer, and Dot Matrix LED ordered from JLCPCB, I finalized my KiCad design.

To accompany this hardware, an e-commerce website and a learning management system website had to be created. I decided to create them myself using Laravel with the help of some Udemy courses. I’ll be parking my learning notes from my Laravel journey over here (had some help from chatgpt to get these notes).

This content is for my recollection and reference. The concepts and ideas may be wrong/inaccurate. Viewer discretion is advised.

Laravel

Routing

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
1. Basic Routing

Routes live in routes/web.php (for web) and routes/api.php (for APIs).

// routes/web.php
use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return 'Hello, Laravel!';
});

Route::get()  responds only to GET requests.
Closure (callback) returns a response directly.
You can return strings, arrays, JSON, views, or even redirect.

Example returning a Blade view:
Route::get('/welcome', function () {
    return view('welcome');
});

2. Route Parameters
You can capture parts of the URL.

Route::get('/users/{id}', function ($id) {
    return "User ID: $id";
});

{id} is a wildcard.
Laravel automatically injects it into the callback.

Optional parameters:
Route::get('/users/{name?}', function ($name = 'Guest') {
    return "Hello, $name!";
});

Regex constraints:
Route::get('/products/{id}', function ($id) {
    return "Product ID: $id";
})->whereNumber('id');

3. Named Routes
Give a route a name for easy referencing.

Route::get('/profile', function () {
    return 'Your Profile';
})->name('profile');

Now you can generate URLs without hardcoding:
// In controller or Blade
$url = route('profile');   // /profile

With parameters:
Route::get('/posts/{id}', function ($id) {
    return "Post $id";
})->name('posts.show');

// Generate link
route('posts.show', ['id' => 99]); // /posts/99

4. Route Groups
Group routes to avoid repetition.

Route::prefix('admin')->group(function () {
    Route::get('/dashboard', fn() => 'Admin Dashboard');
    Route::get('/users', fn() => 'Admin Users');
});

Routes become /admin/dashboard, /admin/users.
Useful for prefixes, namespaces, middleware.

Middleware example:
Route::middleware('auth')->group(function () {
    Route::get('/account', fn() => 'Your Account');
    Route::get('/settings', fn() => 'Your Settings');
});

5. Route Methods
Routes can respond to different HTTP verbs.

Route::post('/form', fn() => 'Form submitted');
Route::put('/profile', fn() => 'Profile updated');
Route::delete('/profile', fn() => 'Profile deleted');

Match multiple methods:
Route::match(['get', 'post'], '/search', fn() => 'Search page');

Any method:
Route::any('/catch', fn() => 'Handles all verbs');

6. Fallback Routes
Catch-all for undefined routes (useful for 404 pages).

Route::fallback(function () {
    return response('Oops, page not found!', 404);
});

7: Controller Routing (real-world)
Instead of closures, routes usually point to controllers:

// routes/web.php
use App\Http\Controllers\UserController;

Route::get('/users/{id}', [UserController::class, 'show']);

// app/Http/Controllers/UserController.php
namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    public function show($id)
    {
        return "User from controller: $id";
    }
}

Blade Templates & Views in Laravel

1. Introduction to Laravel Blade Views

Blade is Laravel’s templating engine — it lets you write HTML + PHP with super clean syntax.

Create a simple Blade file:

<!-- resources/views/hello.blade.php -->
<!DOCTYPE html>
<html>
<head>
    <title>Hello</title>
</head>
<body>
    <h1>Hello, </h1>
</body>
</html>

Route to render it:
Route::get('/hello', function () {
    return view('hello', ['name' => 'Laravel']);
});

 → Blade echo (auto-escaped for XSS protection).

2. Create Views via CLI
Instead of manually creating a file:

php artisan make:view hello

This creates resources/views/hello.blade.php.

3. Blade Directives
Blade comes with directives (shortcuts for PHP code).

Examples:@if($user->isAdmin())
    <p>Welcome, Admin!</p>
@else
    <p>Welcome, User!</p>
@endif@foreach($users as $user)
    <li></li>
@endforeach

Other useful ones:
@csrf → adds hidden CSRF token for forms
@auth / @guest → check auth state
@php ... @endphp → write raw PHP if needed

4. Passing Data to Blade
From route/controller:
Route::get('/profile', function () {
    return view('profile', [
        'name' => 'John',
        'age' => 30,
    ]);
});

In profile.blade.php:
<h1> ()</h1>

Pass arrays, objects, or Eloquent models — Blade handles it.

5. Extending Blade (Layouts)
Use a master layout to avoid repeating headers/footers.

resources/views/layouts/app.blade.php:
<!DOCTYPE html>
<html>
<head>
    <title>@yield('title')</title>
</head>
<body>
    <header>My App Header</header>

    <main>
        @yield('content')
    </main>

    <footer>Footer text</footer>
</body>
</html>

Child view:
@extends('layouts.app')

@section('title', 'Home Page')

@section('content')
    <h1>Welcome Home</h1>
@endsection

6. Including Sub-views
Break large templates into smaller ones.

<!-- resources/views/components/navbar.blade.php -->
<nav>Navbar links</nav>

Include it anywhere:
@include('components.navbar')

7. Conditional Rendering in Blade
Blade has shortcuts:

@auth
    <p>Welcome </p>
@endauth

@guest
    <p>Please login</p>
@endguest

Or more complex:
@isset($records)
    <p>Found  records</p>
@endisset

@empty($cart)
    <p>Your cart is empty</p>
@endempty

8. Stacks
Let child views inject scripts or styles into the layout.

In layout:
<html>
<head>
    @stack('styles')
</head>
<body>
    @yield('content')
    @stack('scripts')
</body>
</html>

In child view:
@push('styles')
    <link rel="stylesheet" href="/custom.css">
@endpush

@section('content')
    <h1>Dashboard</h1>
@endsection

@push('scripts')
    <script src="/custom.js"></script>
@endpush

9. More Useful Blade Directives
Some handy ones:@switch($role)
    @case('admin')
        <p>Admin panel</p>
        @break
    @case('editor')
        <p>Editor tools</p>
        @break
    @default
        <p>User dashboard</p>
@endswitch@foreach($items as $item)
    <p>. </p>
@endforeach

Controllers in Laravel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
1. Introduction to Controllers
Instead of putting logic inside routes/web.php, you put it in a controller class.

Controllers live in app/Http/Controllers.

Example without controller:
// routes/web.php
Route::get('/users/{id}', function ($id) {
    return "User ID: $id";
});

With controller:
use App\Http\Controllers\UserController;

Route::get('/users/{id}', [UserController::class, 'show']);

2. Basic Controllers
Generate a controller:
php artisan make:controller UserController

This creates app/Http/Controllers/UserController.php:

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    public function show($id)
    {
        return "User ID from controller: $id";
    }
}

Now your route is clean, and logic lives in a proper class.

3. Single Action Controllers
Sometimes a controller only needs one method. Instead of creating multiple methods, you use __invoke.

Generate it:
php artisan make:controller ContactController --invokable

app/Http/Controllers/ContactController.php:
namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ContactController extends Controller
{
    public function __invoke(Request $request)
    {
        return "This is a single action controller!";
    }
}

Route:
use App\Http\Controllers\ContactController;

Route::get('/contact', ContactController::class);

Now the class itself is callable.

4. Resource Controllers
For CRUD-heavy models, Laravel provides Route::resource.

Generate:
php artisan make:controller PostController --resource

This creates a controller with 7 RESTful methods:

public function index()   // GET /posts - list
public function create()  // GET /posts/create - form
public function store()   // POST /posts - save
public function show($id) // GET /posts/{id} - single post
public function edit($id) // GET /posts/{id}/edit - form
public function update(Request $r, $id) // PUT/PATCH /posts/{id}
public function destroy($id) // DELETE /posts/{id}

Register in routes:
use App\Http\Controllers\PostController;

Route::resource('posts', PostController::class);

This automatically generates all CRUD routes:

GET      /posts           -> index
GET      /posts/create    -> create
POST     /posts           -> store
GET      /posts/{id}      -> show
GET      /posts/{id}/edit -> edit
PUT/PATCH /posts/{id}     -> update
DELETE   /posts/{id}      -> destroy

Laravel + MySQL: Models, Migrations & Seeders

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
30. Setting up Laravel Database Connection
Edit your .env file:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_app
DB_USERNAME=root
DB_PASSWORD=secret

Confirm config/database.php uses MySQL driver.
Test connection:
php artisan migrate

If no errors  connection works.

31. Migrations
Migrations are version control for DB schema.

Create migration:
php artisan make:migration create_posts_table

This creates a file in database/migrations/:

public function up(): void
{
    Schema::create('posts', function (Blueprint $table) {
        $table->id(); // BIGINT AUTO_INCREMENT PRIMARY KEY
        $table->string('title'); // VARCHAR(255)
        $table->text('body'); // TEXT
        $table->timestamps(); // created_at & updated_at
    });
}

public function down(): void
{
    Schema::dropIfExists('posts');
}

Run:
php artisan migrate

Check MySQL:
SHOW TABLES;
DESCRIBE posts;

32. Table Data Types (MySQL specific)
Laravel  MySQL type mapping:

$table->string('name', 100);   // VARCHAR(100)
$table->text('bio');           // TEXT
$table->integer('age');        // INT
$table->unsignedBigInteger('views'); // UNSIGNED BIGINT
$table->decimal('price', 8, 2); // DECIMAL(8,2)
$table->boolean('is_active');  // TINYINT(1)
$table->date('birth_date');    // DATE
$table->dateTime('published'); // DATETIME
$table->json('options');       // JSON

Laravel abstracts, but under the hood its MySQL types.

33. Important Migration Commands
php artisan migrate            # Run pending migrations
php artisan migrate:rollback   # Rollback last batch
php artisan migrate:reset      # Rollback all
php artisan migrate:refresh    # Reset & re-run
php artisan migrate:fresh      # Drop all & re-run

Useful with seeding:
php artisan migrate:fresh --seed

34. Model
Create a model:
php artisan make:model Post

This creates app/Models/Post.php:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $fillable = ['title', 'body'];
}

Use it in Tinker:
php artisan tinker
>>> Post::create(['title' => 'Hello', 'body' => 'MySQL test']);
>>> Post::all();

This inserts/queries directly in MySQL.

35. Model with Custom Table Name
By default, Post  posts. Override:

class BlogEntry extends Model
{
    protected $table = 'my_custom_posts';
}

Check MySQL:
SELECT * FROM my_custom_posts;

36. Seeder
Seeders populate data for dev/testing.

Create:
php artisan make:seeder PostSeeder

database/seeders/PostSeeder.php:

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\Post;

class PostSeeder extends Seeder
{
    public function run(): void
    {
        Post::create([
            'title' => 'Seeder Example',
            'body' => 'Inserted via seeder into MySQL'
        ]);
    }
}

Run:
php artisan db:seed --class=PostSeeder

37. Factories
Factories generate fake data (great for MySQL dev DBs).

Create:
php artisan make:factory PostFactory --model=Post

database/factories/PostFactory.php:

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

class PostFactory extends Factory
{
    public function definition(): array
    {
        return [
            'title' => fake()->sentence(),
            'body' => fake()->paragraph(),
        ];
    }
}

Use it in seeder:
Post::factory()->count(10)->create();

Run:
php artisan db:seed --class=PostSeeder

Check in MySQL:
SELECT COUNT(*) FROM posts;

38. Adding New Columns to Existing Tables
Create a new migration:
php artisan make:migration add_published_to_posts_table --table=posts

Migration file:

public function up(): void
{
    Schema::table('posts', function (Blueprint $table) {
        $table->boolean('published')->default(false);
    });
}

public function down(): void
{
    Schema::table('posts', function (Blueprint $table) {
        $table->dropColumn('published');
    });
}

Run:
php artisan migrate

Check MySQL:
DESCRIBE posts;

Laravel Query Builder (with MySQL)

All examples assume you have a users table with columns:

id, name, email, age, created_at, updated_at.

You use the DB facade:

1
use Illuminate\Support\Facades\DB;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
39. Introduction to Query Builder
Basic SELECT:
$users = DB::table('users')->get();

This runs:
SELECT * FROM users;

Get one row:
$user = DB::table('users')->where('id', 1)->first();

Get a single value:
$email = DB::table('users')->where('id', 1)->value('email');

40. Creating New Data
Insert into MySQL:
DB::table('users')->insert([
    'name' => 'Alice',
    'email' => 'alice@example.com',
    'age' => 25,
]);

Insert and get ID:
$id = DB::table('users')->insertGetId([
    'name' => 'Bob',
    'email' => 'bob@example.com',
    'age' => 30,
]);

MySQL equivalent:
INSERT INTO users (name, email, age) VALUES ('Alice','alice@example.com',25);

41. Retrieving Data from DB
Get all:
$users = DB::table('users')->get();

Filter:
$adults = DB::table('users')->where('age', '>=', 18)->get();

Ordering:
$users = DB::table('users')
    ->orderBy('age', 'desc')
    ->limit(5)
    ->get();

Equivalent MySQL:
SELECT * FROM users WHERE age >= 18 ORDER BY age DESC LIMIT 5;

42. Updating Data
Update a record:
DB::table('users')
    ->where('id', 1)
    ->update(['age' => 35]);

MySQL:
UPDATE users SET age = 35 WHERE id = 1;

43. Deleting Data
Delete:
DB::table('users')->where('id', 2)->delete();

Truncate table:
DB::table('users')->truncate();

MySQL:
DELETE FROM users WHERE id = 2;
TRUNCATE TABLE users;

44. Retrieving a List of Column Values
Get only one column:
$emails = DB::table('users')->pluck('email');

Result:
["alice@example.com", "bob@example.com", ...]

Get key-value pairs:
$users = DB::table('users')->pluck('email', 'id');

Equivalent MySQL:
SELECT id, email FROM users;

45. Aggregates
Query Builder supports SQL aggregate functions:

$count = DB::table('users')->count();     // SELECT COUNT(*) FROM users;
$max   = DB::table('users')->max('age');  // SELECT MAX(age) FROM users;
$min   = DB::table('users')->min('age');  // SELECT MIN(age) FROM users;
$avg   = DB::table('users')->avg('age');  // SELECT AVG(age) FROM users;
$sum   = DB::table('users')->sum('age');  // SELECT SUM(age) FROM users;

Laravel Eloquent ORM

Assume we have a users table and a matching model:

1
2
3
4
5
6
7
8
9
10
11
php artisan make:model User

app/Models/User.php:
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $fillable = ['name', 'email', 'age'];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
46. Introduction to Eloquent ORM
Each model  one MySQL table (pluralized by default).
Each row  one model instance.
CRUD without SQL.

Example:
User::all();       // SELECT * FROM users;
User::find(1);     // SELECT * FROM users WHERE id = 1;

47. Eloquent - Creating New Data
Two ways:

Using create() (mass assignment):
User::create([
    'name' => 'Alice',
    'email' => 'alice@example.com',
    'age' => 25
]);

Using object save():
$user = new User;
$user->name = 'Bob';
$user->email = 'bob@example.com';
$user->age = 30;
$user->save();

SQL behind the scenes:
INSERT INTO users (name, email, age) VALUES ('Alice', 'alice@example.com', 25);

48. Eloquent - Retrieving Data
User::all();                        // all users
User::find(1);                      // by primary key
User::where('age', '>', 18)->get(); // filter
User::first();                      // first row
User::orderBy('age', 'desc')->take(5)->get();

MySQL equivalent:
SELECT * FROM users WHERE age > 18 ORDER BY age DESC LIMIT 5;

49. Eloquent - Updating Data
$user = User::find(1);
$user->age = 35;
$user->save();

Or bulk update:
User::where('age', '<', 18)->update(['age' => 18]);

SQL:
UPDATE users SET age = 35 WHERE id = 1;

50. Eloquent - Deleting Data
$user = User::find(2);
$user->delete();

Bulk delete:
User::where('age', '<', 18)->delete();

SQL:
DELETE FROM users WHERE id = 2;

51. Eloquent - Fillable and Mass Assignment
Prevent unwanted columns being mass-assigned (security).

In model:
protected $fillable = ['name', 'email', 'age'];

Now:
User::create(['name' => 'Eve', 'email' => 'eve@example.com', 'age' => 22]);

Works, only whitelisted fields get filled.

52. Eloquent - Conditional Clause
Eloquent uses the same conditions as Query Builder:

User::where('age', '>', 18)->get();
User::where('email', 'like', '%@gmail.com')->get();
User::whereBetween('age', [20, 30])->get();
User::whereIn('id', [1, 2, 3])->get();

Chain conditions:
User::where('active', true)->where('age', '>', 21)->get();

53. Eloquent - Query Scopes
Scopes = reusable query snippets.

In model:
public function scopeAdults($query)
{
    return $query->where('age', '>=', 18);
}

Usage:
User::adults()->get();

SQL:
SELECT * FROM users WHERE age >= 18;

54. Eloquent - Soft Deleting
Instead of deleting rows permanently, mark them as deleted.

Migration:
$table->softDeletes(); // adds deleted_at column (nullable)

Model:
use Illuminate\Database\Eloquent\SoftDeletes;

class User extends Model
{
    use SoftDeletes;
}

Now:
User::find(1)->delete();

Doesnt remove row, just sets deleted_at.

SQL:
UPDATE users SET deleted_at = NOW() WHERE id = 1;

55. Eloquent - Restore Trashed Data or Delete Permanently
Restore:
User::withTrashed()->where('id', 1)->restore();

Force delete:
User::withTrashed()->where('id', 1)->forceDelete();

Laravel Forms & Validation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
56. Form Markup
Create a form in Blade:

<form action="" method="POST">
    @csrf
    <label>Name:</label>
    <input type="text" name="name">

    <label>Email:</label>
    <input type="email" name="email">

    <label>Age:</label>
    <input type="number" name="age">

    <button type="submit">Submit</button>
</form>

@csrf  Protects against Cross-Site Request Forgery.
action=""  Sends data to controller.

57. Form Submitting and CSRF
Every POST/PUT/DELETE form must include:
@csrf

This generates a hidden input:
<input type="hidden" name="_token" value="random_csrf_token">

Laravel verifies this on submission. If missing  419 Page Expired.

58. Accessing Form Contents from Method
In Controller:
public function store(Request $request)
{
    // Access inputs
    $name = $request->input('name');
    $email = $request->email; // shortcut
    $age = $request->get('age');

    return "Name: $name, Email: $email, Age: $age";
}

59. Input Field Validation
Laravel makes validation super easy:

public function store(Request $request)
{
    $validated = $request->validate([
        'name'  => 'required|min:3',
        'email' => 'required|email|unique:users',
        'age'   => 'required|integer|min:18'
    ]);

    User::create($validated);
    return redirect()->back()->with('success', 'User created!');
}

Example errors returned if validation fails:
"name" is required
"email" must be unique
"age" must be at least 18

60. Custom Validation Message
$request->validate([
    'name' => 'required|min:3',
    'age'  => 'min:18'
], [
    'name.required' => 'Name cannot be empty!',
    'age.min'       => 'You must be at least 18 years old.'
]);

61. Custom Request Classes
Instead of writing validation rules in controllers  use a Form Request class:

php artisan make:request StoreUserRequest

In StoreUserRequest.php:
public function rules()
{
    return [
        'name'  => 'required|min:3',
        'email' => 'required|email|unique:users',
        'age'   => 'required|integer|min:18'
    ];
}

Controller:
public function store(StoreUserRequest $request)
{
    User::create($request->validated());
}

62. More Validation Rules
Laravel supports tons of rules:

max:255
confirmed (password & password_confirmation)
url
date
exists:table,column
in:admin,user,guest

Example:
$request->validate([
    'role' => 'required|in:admin,user'
]);

63. Populating Form Data
For edit forms, pass model data:

Controller:
$user = User::find($id);
return view('users.edit', compact('user'));

Blade:
<input type="text" name="name" value="">
<input type="email" name="email" value="">

old() keeps input if validation fails.

64. Saving Form Data
Final step: saving into MySQL.

public function store(Request $request)
{
    $validated = $request->validate([
        'name'  => 'required|min:3',
        'email' => 'required|email|unique:users',
        'age'   => 'required|integer|min:18'
    ]);

    User::create($validated);

    return redirect()->route('users.index')
                     ->with('success', 'User saved!');
}

SQL executed:
INSERT INTO users (name, email, age) VALUES ('Alice', 'alice@example.com', 22);

Query Builder Joins

We’ll assume two tables:

users
id | name | email
1 | Alice | alice@mail.com
2 | Bob | bob@mail.com
3 | Eve | eve@mail.com

posts
id | user_id | title
1 | 1 | “Alice Post 1”
2 | 1 | “Alice Post 2”
3 | 2 | “Bob’s Post”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
89. Joins  Introduction
In SQL, joins combine rows from two tables.

Laravels syntax:
DB::table('users')
    ->join('posts', 'users.id', '=', 'posts.user_id')
    ->get();

Equivalent SQL:
SELECT * FROM users
INNER JOIN posts ON users.id = posts.user_id;

90. Joins  Making Database Ready
Seed some test data:

User::insert([
    ['id' => 1, 'name' => 'Alice', 'email' => 'alice@mail.com'],
    ['id' => 2, 'name' => 'Bob',   'email' => 'bob@mail.com'],
    ['id' => 3, 'name' => 'Eve',   'email' => 'eve@mail.com'],
]);

Post::insert([
    ['id' => 1, 'user_id' => 1, 'title' => 'Alice Post 1'],
    ['id' => 2, 'user_id' => 1, 'title' => 'Alice Post 2'],
    ['id' => 3, 'user_id' => 2, 'title' => 'Bob’s Post'],
]);

91. Inner Join
Returns rows where there is a match in both tables.

$results = DB::table('users')
    ->join('posts', 'users.id', '=', 'posts.user_id')
    ->select('users.name', 'posts.title')
    ->get();

Output:
Alice | Alice Post 1
Alice | Alice Post 2
Bob   | Bobs Post

Eve has no posts, so shes excluded.

92. Left Join
Returns all rows from left table (users) + matches from right table (posts).

$results = DB::table('users')
    ->leftJoin('posts', 'users.id', '=', 'posts.user_id')
    ->select('users.name', 'posts.title')
    ->get();

Output:
Alice | Alice Post 1
Alice | Alice Post 2
Bob   | Bobs Post
Eve   | null

Eve appears even though she has no post (with null).

93. Right Join
Returns all rows from right table (posts) + matches from left (users).

$results = DB::table('users')
    ->rightJoin('posts', 'users.id', '=', 'posts.user_id')
    ->select('users.name', 'posts.title')
    ->get();

Output:
Alice | Alice Post 1
Alice | Alice Post 2
Bob   | Bobs Post

(Eve disappears since she has no post).

94. Full Join (Simulated)
MySQL doesnt support FULL OUTER JOIN directly.
Laravel lets you simulate with union:

$left = DB::table('users')
    ->leftJoin('posts', 'users.id', '=', 'posts.user_id')
    ->select('users.name', 'posts.title');

$right = DB::table('users')
    ->rightJoin('posts', 'users.id', '=', 'posts.user_id')
    ->select('users.name', 'posts.title');

$results = $left->union($right)->get();

Output:
Alice | Alice Post 1
Alice | Alice Post 2
Bob   | Bobs Post
Eve   | null

Eloquent ORM Relationships

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
95. Introduction
Eloquent makes relationships first-class citizens.

Example:
class User extends Model {
    public function posts() {
        return $this->hasMany(Post::class);
    }
}

Now you can just call:
$posts = User::find(1)->posts;

Instead of writing joins.

96. One-to-One  hasOne()
Each User has one Profile.

users table
id | name
---|-------
1  | Alice
2  | Bob

profiles table
id | user_id | bio
---|---------|-----------
1  | 1       | "Developer"
2  | 2       | "Designer"

Model setup:
class User extends Model {
    public function profile() {
        return $this->hasOne(Profile::class);
    }
}

class Profile extends Model {
    public function user() {
        return $this->belongsTo(User::class);
    }
}

Usage:
$user = User::find(1);
echo $user->profile->bio;  // Developer

97. One-to-One  belongsTo()
Inverse of above:
$profile = Profile::find(1);
echo $profile->user->name;  // Alice

98. One-to-Many  hasMany()
A User has many Posts.

posts table
id | user_id | title
---|---------|---------------
1  | 1       | "Alice Post 1"
2  | 1       | "Alice Post 2"
3  | 2       | "Bob’s Post"

Model:
class User extends Model {
    public function posts() {
        return $this->hasMany(Post::class);
    }
}

Usage:
$user = User::find(1);
foreach ($user->posts as $post) {
    echo $post->title;
}

99. Many-to-Many  belongsToMany()
Users can belong to many roles, and roles can belong to many users.

users
id | name
---|------
1  | Alice
2  | Bob

roles
id | name
---|------
1  | Admin
2  | Editor

role_user (pivot table)
user_id | role_id
--------|--------
1       | 1
1       | 2
2       | 2

Model:
class User extends Model {
    public function roles() {
        return $this->belongsToMany(Role::class);
    }
}
class Role extends Model {
    public function users() {
        return $this->belongsToMany(User::class);
    }
}

Usage:
$roles = User::find(1)->roles; // [Admin, Editor]
$users = Role::find(2)->users; // [Alice, Bob]

100. Has-Many-Through
A shortcut for nested relationships.
Example: Country  Users  Posts

A Country has many Posts through Users.

class Country extends Model {
    public function posts() {
        return $this->hasManyThrough(Post::class, User::class);
    }
}

Now:
$posts = Country::find(1)->posts;

Instead of chaining two queries.

101. Polymorphic Relationships
Polymorphism = one model can belong to multiple other models.

Example: Comments can belong to both Posts and Videos.

comments table
id | body      | commentable_id | commentable_type
---|-----------|----------------|-------------------
1  | "Nice!"   | 1              | App\Models\Post
2  | "Cool!"   | 2              | App\Models\Video

Model:
class Comment extends Model {
    public function commentable() {
        return $this->morphTo();
    }
}

class Post extends Model {
    public function comments() {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

class Video extends Model {
    public function comments() {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

Usage:
$post = Post::find(1);
$post->comments;  // All comments on post

$video = Video::find(2);
$video->comments; // All comments on video

Laravel Middleware

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
102. Introduction to Middleware
Middleware sits between the request and the response cycle.
It acts as a filter for HTTP requests.

Common uses:
Authentication
Logging
CSRF protection
Role-based access control
Request modification

Every incoming request in Laravel passes through a stack of middleware before hitting the controller.

Example:
Request  Middleware  Controller  Response

Built-in examples:
auth  checks if user is logged in
verified  ensures email is verified
throttle  limits request rate

103. Scenario  Why Middleware?
Imagine a system where only admins can access /dashboard.

Without middleware, youd check user roles in every controller  repetitive!

Instead, middleware lets you centralize that logic:
if ($user->isAdmin()) {
    return $next($request);
}
return redirect('home');

Now, all protected routes go through this filter.

104. Create Middleware
Command:
php artisan make:middleware CheckAdmin

It creates:
app/Http/Middleware/CheckAdmin.php

Example content:
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class CheckAdmin
{
    public function handle(Request $request, Closure $next)
    {
        if (!auth()->user() || !auth()->user()->is_admin) {
            return redirect('home');
        }

        return $next($request);
    }
}

This checks if the user is an admin before continuing the request.

105. Assign Middleware to a Route
You can attach middleware to individual routes:

Route::get('/dashboard', [DashboardController::class, 'index'])
    ->middleware('check.admin');

But first, you must register it in app/Http/Kernel.php:

protected $routeMiddleware = [
    'check.admin' => \App\Http\Middleware\CheckAdmin::class,
];

Now, only admins can access /dashboard.

106. Assign Middleware to a Route Group
Instead of repeating middleware on each route, group them:

Route::middleware(['auth', 'check.admin'])->group(function () {
    Route::get('/dashboard', [DashboardController::class, 'index']);
    Route::get('/reports', [ReportController::class, 'index']);
});

All routes inside this group must pass through both auth and check.admin middleware.

107. Controller Middleware
You can also assign middleware directly inside controllers:

class DashboardController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
        $this->middleware('check.admin')->only('index');
    }
}

This makes your routes cleaner while keeping logic tied to the controller.

108. Global Middleware
If you want middleware to apply to every request automatically,

register it in the $middleware array in app/Http/Kernel.php:

protected $middleware = [
    \App\Http\Middleware\TrustProxies::class,
    \Fruitcake\Cors\HandleCors::class,
    \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
    \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
    \App\Http\Middleware\TrimStrings::class,
    \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    // Add your own:
    \App\Http\Middleware\CheckSiteStatus::class,
];

Example:
If your app is under maintenance or has certain IP restrictions, global middleware ensures all requests are filtered.

Laravel Middleware (Part 2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
109. Middleware Groups
Middleware groups let you bundle multiple middleware into one keyword  perfect for different parts of your app like web and API routes.

Default Laravel Middleware Groups
In app/Http/Kernel.php:

protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],

    'api' => [
        'throttle:api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
];

The 'web' group handles:
Cookies
Session management
CSRF token validation

The 'api' group includes throttling and binding logic, optimized for APIs.

Applying Middleware Groups
You can use them directly in routes:

Route::middleware(['web'])->group(function () {
    Route::get('/', [HomeController::class, 'index']);
});

Or in route files (routes/web.php and routes/api.php):
Route::get('/users', [UserController::class, 'index'])->middleware('api');

So, instead of attaching 5+ middleware manually, you just use one group keyword.

110. Middleware Alias
Laravel 10.8+ introduced middleware aliasing (before, it was $routeMiddleware).

Aliases make your middleware short and readable  instead of using full class names.

Defining an Alias
In app/Http/Kernel.php:

protected $middlewareAliases = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'admin' => \App\Http\Middleware\CheckAdmin::class,
    'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];

Then in your routes:
Route::get('/dashboard', [DashboardController::class, 'index'])
     ->middleware(['auth', 'admin']);

This replaces $routeMiddleware from older versions and keeps your kernel clean.

111. Middleware Parameters
Middleware can also accept parameters, making them dynamic.

Example: Role-based Middleware
Create it:
php artisan make:middleware CheckRole

Edit it in app/Http/Middleware/CheckRole.php:
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class CheckRole
{
    public function handle(Request $request, Closure $next, $role)
    {
        if (!auth()->check() || auth()->user()->role !== $role) {
            return redirect('home');
        }

        return $next($request);
    }
}

Register in Kernel.php:
protected $middlewareAliases = [
    'role' => \App\Http\Middleware\CheckRole::class,
];

Use in routes:
Route::get('/admin', [AdminController::class, 'index'])->middleware('role:admin');
Route::get('/editor', [EditorController::class, 'index'])->middleware('role:editor');

Here, 'role:admin' passes "admin" as the $role parameter  dynamic and reusable middleware.

Authentication & Authorization in Laravel

PART 1: AUTHENTICATION

Authentication = verifying user identity (login, registration, etc.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
112. Authentication  Introduction
Laravel provides a full authentication system out-of-the-box.

It includes:
Login
Registration
Password reset
Email verification

In modern Laravel (10+), we use Breeze, Jetstream, or Fortify for scaffolding.

113. Installing Breeze Starter Kit
Install and configure Laravel Breeze  a lightweight starter kit with authentication views and routes.

composer require laravel/breeze --dev
php artisan breeze:install

Choose frontend stack:
php artisan breeze:install blade
# or: react / vue / inertia

Then migrate:
php artisan migrate
npm install && npm run dev

Breeze provides:
/register  registration
/login  login
/logout  logout
/dashboard  protected route

114. Redirect User to Specific Page
After login/registration, Laravel redirects users via HomeController or RouteServiceProvider.

In app/Providers/RouteServiceProvider.php:
public const HOME = '/dashboard';

Change this constant to redirect to your preferred page:
public const HOME = '/profile';

You can also customize in LoginController:
protected function authenticated(Request $request, $user)
{
    return redirect('/custom-page');
}

115. Retrieving the Authenticated User
You can access the logged-in user anywhere using:

use Illuminate\Support\Facades\Auth;

// Get current user
$user = Auth::user();

// Or helper
$user = auth()->user();

// Get ID
$userId = auth()->id();

Example in a controller:
public function profile()
{
    $user = auth()->user();
    return view('profile', compact('user'));
}

Blade syntax:
@if(Auth::check())
    Welcome, 
@endif

116. Recreating Logout Feature
You can implement logout manually:

use Illuminate\Support\Facades\Auth;

Route::post('/logout', function () {
    Auth::logout();
    return redirect('/login');
});

Or use built-in Breeze functionality (POST /logout).

117. Protecting Routes
You can protect routes using the auth middleware:

Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware('auth');

This ensures only logged-in users can access it.

You can also apply it to route groups:
Route::middleware(['auth'])->group(function () {
    Route::get('/profile', [ProfileController::class, 'index']);
});

If not logged in  redirected to /login.

118. Verifying Email
Laravel includes built-in email verification.

Enable it in your model:
class User extends Authenticatable implements MustVerifyEmail
{
    use Notifiable;
}

Protect routes using:
Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware(['auth', 'verified']);

Now, new users must verify their email before accessing the route.

You can resend verification:
auth()->user()->sendEmailVerificationNotification();

PART 2: AUTHORIZATION

Authorization = checking permissions or abilities after authentication.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
119. Authorization  Introduction
After the user is authenticated, we use authorization to decide what they can do.

Laravel provides two main tools:
Gates  single-action checks
Policies  structured authorization for models

120. Gates
Gates are simple closures that determine if a user can perform an action.

Define them in App\Providers\AuthServiceProvider:

use Illuminate\Support\Facades\Gate;

public function boot()
{
    Gate::define('edit-post', function ($user, $post) {
        return $user->id === $post->user_id;
    });
}

Use them:
if (Gate::allows('edit-post', $post)) {
    // User can edit
}

if (Gate::denies('edit-post', $post)) {
    abort(403);
}

Blade:
@can('edit-post', $post)
    <a href="/post//edit">Edit</a>
@endcan

121. Policies
Policies are classes that organize authorization logic for a model.

Create one:
php artisan make:policy PostPolicy --model=Post

This creates app/Policies/PostPolicy.php.

Example methods:
public function update(User $user, Post $post)
{
    return $user->id === $post->user_id;
}

public function delete(User $user, Post $post)
{
    return $user->id === $post->user_id;
}

Register in AuthServiceProvider:
protected $policies = [
    Post::class => PostPolicy::class,
];

Use it in controllers:
$this->authorize('update', $post);

Or Blade:
@can('update', $post)
    <button>Edit</button>
@endcan

122. Verifying Authorization in Blade
Blade directives make it simple:

@can('delete', $post)
    <button>Delete Post</button>
@endcan

@cannot('delete', $post)
    <p>You cannot delete this post.</p>
@endcannot

You can also check roles:
@role('admin')
    <a href="/admin">Admin Panel</a>
@endrole

(if using a role package like spatie/laravel-permission)

Example Flow (Full Integration)

routes/web.php
Route::middleware(['auth', 'verified'])->group(function () {
    Route::resource('posts', PostController::class);
});

PostPolicy.php
public function update(User $user, Post $post)
{
    return $user->id === $post->user_id;
}

PostController.php
public function update(Request $request, Post $post)
{
    $this->authorize('update', $post);
    $post->update($request->all());
    return redirect()->back();
}

Blade:
@can('update', $post)
    <a href="">Edit</a>
@endcan

Mail

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
Laravels Mail system gives a clean, object-oriented way to send emails using Markdown, HTML, file attachments, queues, and third-party drivers.

125. Setup Mailtrap Configuration
Mailtrap is a fake SMTP server that catches emails for testing  no real emails sent.

Set it up in .env:

MAIL_MAILER=smtp
MAIL_HOST=sandbox.smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=your_mailtrap_username
MAIL_PASSWORD=your_mailtrap_password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="noreply@yourapp.com"
MAIL_FROM_NAME="${APP_NAME}"

Confirm config/mail.php uses environment variables:

'mailers' => [
    'smtp' => [
        'transport' => 'smtp',
        'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
        'port' => env('MAIL_PORT', 587),
        'encryption' => env('MAIL_ENCRYPTION', 'tls'),
        'username' => env('MAIL_USERNAME'),
        'password' => env('MAIL_PASSWORD'),
    ],
],

Now Laravel knows where and how to send emails.

126. Send a Simple Email with Laravel
Create a new Mailable class:
php artisan make:mail WelcomeMail

This creates app/Mail/WelcomeMail.php.

Edit it:
namespace App\Mail;

use Illuminate\Mail\Mailable;

class WelcomeMail extends Mailable
{
    public function build()
    {
        return $this->subject('Welcome to MyApp')
                    ->text('emails.welcome'); // plain text view
    }
}

Create the view:
resources/views/emails/welcome.blade.php

Hello ,

Welcome to our Laravel App!

Send email from controller:
use App\Mail\WelcomeMail;
use Illuminate\Support\Facades\Mail;

Mail::to('user@example.com')->send(new WelcomeMail());

Check your Mailtrap inbox  youll see the test message.

127. Send HTML View as Mail Body
You can switch from text to HTML views:

return $this->subject('Welcome!')
            ->view('emails.welcome-html');

Example HTML view:
<!DOCTYPE html>
<html>
<body>
    <h1>Welcome, </h1>
    <p>Thanks for joining our platform.</p>
</body>
</html>

128. Attaching Files to Email
You can easily attach files:

return $this->subject('Invoice Ready')
            ->view('emails.invoice')
            ->attach(public_path('invoices/invoice1.pdf'));

Or attach dynamic files:
->attachData($pdfOutput, 'invoice.pdf', ['mime' => 'application/pdf'])

129. Queue Mail
Sending mail synchronously can slow responses.

Laravel lets you queue mail jobs so theyre sent in the background.

Update your WelcomeMail:
class WelcomeMail extends Mailable implements ShouldQueue
{
    use Queueable, SerializesModels;
}

Send it via queue:
Mail::to($user->email)->queue(new WelcomeMail());

Configure queue driver in .env:
QUEUE_CONNECTION=database

Then:
php artisan queue:table
php artisan migrate
php artisan queue:work

Now emails are processed asynchronously  great for production.

Blade Components

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
Blade Components are reusable, encapsulated chunks of HTML + logic  similar to React/Vue components but purely server-rendered.

130. Introduction to Blade Components
Blade components help you reuse markup across pages.

Think: <x-alert>, <x-button>, <x-layout>.

They live in:
resources/views/components/

and are rendered as:
<x-alert />

131. Creating Blade Components
Create one:
php artisan make:component Alert

Laravel creates:
Class  app/View/Components/Alert.php
View  resources/views/components/alert.blade.php

Class:
namespace App\View\Components;

use Illuminate\View\Component;

class Alert extends Component
{
    public function render()
    {
        return view('components.alert');
    }
}

View:
<div class="bg-red-100 text-red-700 p-3 rounded">
    
</div>

Usage in any view:
<x-alert>
    Something went wrong!
</x-alert>

132133. Passing Data to Components
Pass attributes just like HTML props:

<x-alert type="success" message="Profile updated successfully!" />

Update your component class:
class Alert extends Component
{
    public $type;
    public $message;

    public function __construct($type = 'info', $message = null)
    {
        $this->type = $type;
        $this->message = $message;
    }

    public function render()
    {
        return view('components.alert');
    }
}

View (components/alert.blade.php):
<div class="alert alert-">
    
</div>

You can pass both named props (type, message) and slot content.

134. Attributes
Blade Components automatically merge additional HTML attributes.

<x-button class="bg-blue-500">Save</x-button>

resources/views/components/button.blade.php
<button >
    
</button>

So adding class="bg-blue-500" merges seamlessly with defaults.

135. Component Slots
Slots let you define dynamic inner content.

Example layout component:
<!-- resources/views/components/layout.blade.php -->
<html>
<head><title></title></head>
<body>
    <header></header>

    <main></main>

    <footer>Copyright © 2025</footer>
</body>
</html>

Usage:
<x-layout title="Dashboard">
    <x-slot name="header">
        <h1>Welcome </h1>
    </x-slot>

    <p>Main content here...</p>
</x-layout>

Putting It Together (Mail + Components)
You can even use Blade components inside your emails!

resources/views/emails/welcome.blade.php
<x-mail::message>
# Welcome 

<x-mail::button :url="route('dashboard')">
Go to Dashboard
</x-mail::button>

Thanks,<br>

</x-mail::message>

Laravel will automatically use its built-in mail components.

Sessions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Session = per-user, short-lived, request-to-request state

Laravel sessions sit on top of HTTP, which is stateless by default.

136. Session  Introduction to HTTP Session
HTTP itself does not remember users between requests.

Laravel sessions solve this by:
Assigning a session ID (usually via cookie)
Storing session data on the server (file, DB, Redis, etc.)

Where sessions are configured
config/session.php

Common drivers:
SESSION_DRIVER=file     # default (local dev)
SESSION_DRIVER=database # production
SESSION_DRIVER=redis    # high scale

137. Storing Data in Session
Store simple values
session(['key' => 'value']);

or
session()->put('cart_count', 3);

Flash data (one request only)
session()->flash('success', 'Profile updated!');

Flash data is commonly used for:
Success messages
Error messages after redirects

138. Retrieving Data from Session
Get a value
$value = session('key');

With default:
$value = session('key', 'default');

Check if exists
if (session()->has('cart_count')) {
    //
}

Blade example
@if(session('success'))
    <div class="alert alert-success">
        
    </div>
@endif

139. Deleting Data from Session
Remove one key
session()->forget('cart_count');

Remove multiple keys
session()->forget(['cart_count', 'coupon']);

Clear entire session
session()->flush();

flush() logs out users because auth data lives in session

Caching

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
Cache = shared, fast, non-user-specific data

Caching is about performance, not state.

140. Caching  Introduction
Cache is:
Faster than DB
Shared across users
Short-lived or persistent

Common drivers:
CACHE_DRIVER=file
CACHE_DRIVER=redis
CACHE_DRIVER=memcached

Laravel abstracts caching so the same code works everywhere.

141. Difference Between Session and Cache
This is critical.

| Feature         | Session                | Cache                  |
|-----------------|------------------------|------------------------|
| User-specific   | Yes                    | No                     |
| Short-lived     | Yes                    | Can be long-lived      |
| Stored per user | Yes                    | Shared                 |
| Typical use     | Auth data              | Query results, config  |

Never store auth or user identity in cache
Never store expensive queries in session

142. Storing Data in Cache
Store permanently
Cache::put('site_name', 'My App');

Store with expiration
Cache::put('users_count', 100, now()->addMinutes(10));

Store forever
Cache::forever('config_data', $data);

143. Storing Data from DB and Retrieving
This is the real power of cache.

use Illuminate\Support\Facades\Cache;
use App\Models\Post;

$posts = Cache::remember('posts.all', 600, function () {
    return Post::all();
});

What happens:
Check cache
If exists  return cached data
If not  query DB and cache it

With dynamic keys
Cache::remember("user.{$id}", 600, function () use ($id) {
    return User::find($id);
});

144. Removing Data from Cache
Forget a key
Cache::forget('posts.all');

Clear everything
php artisan cache:clear

Clearing cache affects all users.

This post is licensed under CC BY 4.0 by the author.