Skip to main content

Command Palette

Search for a command to run...

Laravel 11 Tutorial: PHP Framework for Modern Web Apps

Learn: Laravel 11 Tutorial: PHP Framework for Modern Web Apps

Updated
5 min readView as Markdown
T

Welcome to TopperBlog! 👋

I'm a tech content creator passionate about helping developers level up their careers and master cutting-edge technologies.

🎯 What I Write About: • AI/ML Engineering & LLMs • Web3 & Blockchain Development
• System Design & Architecture • Interview Preparation (FAANG) • Freelancing & Remote Work • Modern Tech Stacks (Next.js, React, Rust, TypeScript) • Performance Optimization & Best Practices

💼 Mission: Sharing practical, actionable insights that accelerate your tech career and maximize your earning potential.

📚 15+ In-Depth Guides covering everything from earning $10k/month as a freelancer to cracking FAANG interviews.

🌐 Let's connect and grow together in this amazing tech journey!

#TechBlogger #SoftwareEngineering #CareerGrowth #WebDevelopment #AIEngineering

Laravel 11 Tutorial: PHP Framework for Modern Web Apps

Why This Stack/Framework Matters

Laravel has revolutionized PHP development by making backend engineering enjoyable and productive. In 2024, Laravel 11 represents the framework's maturity—combining powerful features with elegant syntax that developers genuinely appreciate.

Why choose Laravel 11?

  • Developer Experience: Expressive syntax reduces boilerplate code by 40-60% compared to vanilla PHP
  • Built-in Features: Authentication, authorization, database migrations, and testing come standard
  • Performance: Optimized for modern applications with sub-100ms response times
  • Community: 2M+ developers actively contribute packages and solutions
  • Job Market: Laravel skills command 15-20% salary premiums in web development

Unlike older PHP frameworks or JavaScript-only stacks, Laravel balances power with simplicity. You're not fighting the framework—you're working with it.

Core Concepts Explained

1. MVC Architecture

Laravel follows Model-View-Controller separation:

  • Models: Represent database tables and business logic
  • Views: Render HTML templates with data
  • Controllers: Handle requests and orchestrate responses
// app/Models/Post.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $fillable = ['title', 'content', 'author_id'];

    public function author()
    {
        return $this->belongsTo(User::class);
    }
}

2. Eloquent ORM

Laravel's Object-Relational Mapping eliminates raw SQL for most operations:

// Retrieve all posts
$posts = Post::all();

// Find by ID
$post = Post::find(1);

// Query with conditions
$recent = Post::where('created_at', '>', now()->subDays(7))
    ->orderBy('created_at', 'desc')
    ->get();

// Create new record
$post = Post::create([
    'title' => 'My First Post',
    'content' => 'Hello World',
    'author_id' => 1
]);

3. Routing

Define application endpoints in routes/web.php:

use App\Http\Controllers\PostController;

Route::get('/posts', [PostController::class, 'index'])->name('posts.index');
Route::get('/posts/{id}', [PostController::class, 'show'])->name('posts.show');
Route::post('/posts', [PostController::class, 'store'])->name('posts.store');
Route::put('/posts/{id}', [PostController::class, 'update'])->name('posts.update');
Route::delete('/posts/{id}', [PostController::class, 'destroy'])->name('posts.destroy');

4. Middleware

Middleware acts as HTTP request filters:

// app/Http/Middleware/CheckAdmin.php
namespace App\Http\Middleware;

use Closure;

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

        return $next($request);
    }
}

Step-by-Step Setup

Prerequisites

  • PHP 8.2+ installed
  • Composer package manager
  • MySQL or PostgreSQL database
  • Terminal/command line access

Installation

Step 1: Create new Laravel project

composer create-project laravel/laravel my-app
cd my-app

Step 2: Configure environment

cp .env.example .env
php artisan key:generate

Edit .env with your database credentials:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my_app
DB_USERNAME=root
DB_PASSWORD=

Step 3: Run migrations

php artisan migrate

Step 4: Start development server

php artisan serve

Visit http://localhost:8000 in your browser.

Building Real Example: Blog Application

Let's build a complete blog with posts and comments.

Generate Models and Migrations

php artisan make:model Post -m
php artisan make:model Comment -m
php artisan make:controller PostController --resource

Define Database Schema

database/migrations/create_posts_table.php

Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('content');
    $table->foreignId('user_id')->constrained()->onDelete('cascade');
    $table->timestamps();
});

database/migrations/create_comments_table.php

Schema::create('comments', function (Blueprint $table) {
    $table->id();
    $table->text('body');
    $table->foreignId('post_id')->constrained()->onDelete('cascade');
    $table->foreignId('user_id')->constrained()->onDelete('cascade');
    $table->timestamps();
});

Define Model Relationships

// app/Models/Post.php
class Post extends Model
{
    protected $fillable = ['title', 'content', 'user_id'];

    public function author()
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}

// app/Models/Comment.php
class Comment extends Model
{
    protected $fillable = ['body', 'post_id', 'user_id'];

    public function post()
    {
        return $this->belongsTo(Post::class);
    }

    public function author()
    {
        return $this->belongsTo(User::class, 'user_id');
    }
}

Create Controller Logic

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

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

class PostController extends Controller
{
    public function index()
    {
        $posts = Post::with('author', 'comments')
            ->latest()
            ->paginate(10);

        return view('posts.index', compact('posts'));
    }

    public function show(Post $post)
    {
        $post->load('author', 'comments.author');
        return view('posts.show', compact('post'));
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'title' => 'required|string|max:255',
            'content' => 'required|string|min:10',
        ]);

        $post = auth()->user()->posts()->create($validated);

        return redirect()->route('posts.show', $post)
            ->with('success', 'Post created successfully!');
    }
}

Create Views

resources/views/posts/index.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <h1>Blog Posts</h1>

    @forelse($posts as $post)
        <article class="post-card">
            <h2>{{ $post->title }}</h2>
            <p class="meta">By {{ $post->author->name }} on {{ $post->created_at->format('M d, Y') }}</p>
            <p>{{ Str::limit($post->content, 150) }}</p>
            <a href="{{ route('posts.show', $post) }}">Read More →</a>
        </article>
    @empty
        <p>No posts found.</p>
    @endforelse

    {{ $posts->links() }}
</div>
@endsection

Best Practices

1. Use Eloquent Relationships Properly

// ✅ Good: Eager load to prevent N+1 queries
$posts = Post::with('author', 'comments.author')->get();

// ❌ Bad: Causes N+1 query problem
$posts = Post::all();
foreach ($posts as $post) {
    echo $post->author->name; // Extra query per post
}

2. Validate Input Consistently

// Use Form Requests for complex validation
php artisan make:request StorePostRequest

// app/Http/Requests/StorePostRequest.php
public function rules()
{
    return [
        'title' => 'required|string|max:255|unique:posts',
        'content' => 'required|string|min:10',
        'tags' => 'array|max:5',
    ];
}

3. Implement Proper Authentication

// Laravel Breeze provides scaffolding
php artisan breeze:install

// Protect routes
Route::middleware('auth')->group(function () {
    Route::post('/posts', [PostController::class, 'store']);
    Route::delete('/posts/{id}', [PostController::class, 'destroy']);
});

4. Use Database Transactions

use Illuminate\Support\Facades\DB;

DB::transaction(function () {
    $post = Post::create($data);
    $post->tags()->attach($tagIds);
    // Both operations succeed or both rollback
});

Common Issues & Fixes

Issue 1: "Class not found" Error

Cause: Autoloader not updated after creating new files

Fix:

composer dump-autoload

Issue 2: CSRF Token Mismatch

Cause: Missing CSRF token in forms

Fix:

<form method="POST" action="/posts">
    @csrf
    <!-- form fields -->
</form>

Issue 3: Slow Queries

Cause: N+1 query problem or missing indexes

Fix:

// Use eager loading
Post::with('author', 'comments')->get();

// Add database indexes
Schema::table('posts', function (Blueprint $table) {
    $table->index('user_id');
    $table->index('created_at');
});

Issue 4: Permission Denied on Storage

Cause: Incorrect file permissions

Fix:

chmod -R 775 storage bootstrap/cache

Production Tips

1. Optimize for Performance

# Cache configuration
php artisan config:cache

# Cache routes
php artisan route:cache

# Optimize autoloader
composer install --optimize-autoloader --no-dev

2. Set Up Proper Logging

// config/logging.php
'channels' => [
    'stack' => [
        'driver' => 'stack',
        'channels' => ['single', 'slack'],
    ],
]

3. Use Environment Variables

# .env
APP_ENV=production
APP_DEBUG=false
LOG_CHANNEL=stack
CACHE_DRIVER=redis

4. Implement Queue Jobs

// Send emails asynchronously
Mail::to($user)->queue(new WelcomeEmail());

// Process heavy tasks in background
dispatch(new ProcessLargeDataset($data));

5. Database Backups

# Automated backups with Laravel Backup
php artisan backup:run

Resources

Official Documentation

Learning Platforms

  • Laracasts (video tutorials)
  • Laravel News (community updates)
  • Spatie Packages (community tools)

Tools & Packages

  • Laravel Tinker (REPL)
  • Laravel Debugbar (debugging)
  • Laravel Telescope (monitoring)
  • Pest (testing framework)

Community

  • Laravel Discord
  • Stack Overflow laravel tag
  • GitHub Discussions

Conclusion

Laravel 11 empowers developers to build modern web applications efficiently. Its elegant syntax, comprehensive features, and supportive community make it the ideal choice for projects ranging from small blogs to enterprise applications. Start with the fundamentals, practice with real projects, and gradually master advanced patterns.

Happy coding! 🚀