Laravel Tutorial

Laravel is a modern PHP framework for building clean, maintainable web applications. It gives you routing, controllers, Blade views, database migrations, Eloquent models, validation, authentication, queues, testing tools, and deployment-friendly structure.

What is Laravel?

Laravel helps you organize a PHP app using MVC: models hold data rules, views render HTML, and controllers handle request logic. It is a strong next step after learning PHP basics.

  • Routing: map URLs to closures, controllers, or API endpoints.
  • Blade: write reusable templates with layouts, sections, and components.
  • Eloquent: work with database tables using PHP classes.
  • Migrations: version-control database schema changes.
  • Artisan: run framework commands from the terminal.

Setup

You need PHP, Composer, and a database such as MySQL or SQLite. A local development stack such as XAMPP works well for practicing.

Terminal
# Create a new Laravel project
composer create-project laravel/laravel blog-app
cd blog-app

# Start the local development server
php artisan serve

# Create a controller, model, and migration
php artisan make:controller PostController
php artisan make:model Post -m

# Run migrations
php artisan migrate
Review PHP Basics

Project Structure

Laravel projects are organized by responsibility. You do not need to memorize every folder on day one, but these are the files you will touch most often.

Project Structure
app/
  Http/Controllers/      # controller classes
  Models/                # Eloquent models
database/
  migrations/            # table schema changes
  seeders/               # sample data
resources/
  views/                 # Blade templates
routes/
  web.php                # browser routes
  api.php                # API routes
public/
  index.php              # front controller
.env                     # local configuration

Routes

Routes define how URLs respond. Browser pages usually go in routes/web.php. JSON API endpoints usually go in routes/api.php.

Laravel Route
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostController;

Route::get('/', function () {
    return view('welcome');
});

Route::get('/posts', [PostController::class, 'index']);
Route::get('/posts/{post}', [PostController::class, 'show']);
Route::post('/posts', [PostController::class, 'store']);

// Named route
Route::get('/dashboard', function () {
    return view('dashboard');
})->name('dashboard');

Blade Templates

Blade is Laravel's template engine. It lets you create layouts, escape output by default, loop over data, and reuse partials.

Laravel Blade
<!-- resources/views/layouts/app.blade.php -->
<!DOCTYPE html>
<html lang="en">
<head>
  <title>@yield('title', 'Laravel App')</title>
</head>
<body>
  <main>
    @yield('content')
  </main>
</body>
</html>

<!-- resources/views/posts/index.blade.php -->
@extends('layouts.app')

@section('title', 'Posts')

@section('content')
  <h1>Posts</h1>

  @foreach ($posts as $post)
    <article>
      <h2>{{ $post->title }}</h2>
      <p>{{ $post->excerpt }}</p>
    </article>
  @endforeach
@endsection

Controllers

Controllers keep route files clean by moving request handling into classes.

Laravel Controller
namespace App\Http\Controllers;

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

class PostController extends Controller
{
    public function index()
    {
        $posts = Post::latest()->get();

        return view('posts.index', [
            'posts' => $posts,
        ]);
    }

    public function show(Post $post)
    {
        return view('posts.show', compact('post'));
    }
}

Requests

Use the request object to read form fields, query parameters, uploaded files, and authenticated users.

PHP
public function store(Request $request)
{
    $title = $request->input('title');
    $published = $request->boolean('published');
    $search = $request->query('search');

    return response()->json([
        'title' => $title,
        'published' => $published,
        'search' => $search,
    ]);
}

Validation

Validation protects your app from bad input. Keep rules close to form handling, or extract them into form request classes for larger apps.

PHP
public function store(Request $request)
{
    $validated = $request->validate([
        'title' => ['required', 'string', 'max:120'],
        'body' => ['required', 'string'],
        'published_at' => ['nullable', 'date'],
    ]);

    Post::create($validated);

    return redirect()->route('posts.index')
        ->with('status', 'Post created.');
}

Migrations

Migrations describe database structure in code. This makes schema changes repeatable across development, staging, and production.

PHP
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('body');
            $table->timestamp('published_at')->nullable();
            $table->timestamps();
        });
    }

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

Eloquent ORM

Eloquent maps database rows to model objects. Define fillable fields, query records, create rows, and update data using expressive PHP methods.

PHP
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

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

// Common queries
$posts = Post::latest()->get();
$post = Post::findOrFail($id);

Post::create([
    'title' => 'Getting Started with Laravel',
    'body' => 'Laravel makes PHP apps easier to structure.',
]);

$post->update(['title' => 'Updated title']);
$post->delete();

Relationships

Relationships connect models. A user can have many posts, and each post belongs to one user.

PHP
// app/Models/User.php
public function posts()
{
    return $this->hasMany(Post::class);
}

// app/Models/Post.php
public function user()
{
    return $this->belongsTo(User::class);
}

// Use relationships
$user = User::with('posts')->findOrFail(1);

foreach ($user->posts as $post) {
    echo $post->title;
}

Seeders

Seeders add sample data so your app has content while you build features.

Terminal / PHP
php artisan make:seeder PostSeeder

// database/seeders/PostSeeder.php
public function run(): void
{
    Post::create([
        'title' => 'First Laravel Post',
        'body' => 'This post was created by a seeder.',
    ]);
}

php artisan db:seed --class=PostSeeder

Authentication

Laravel can protect routes and read the currently signed-in user. Starter kits can scaffold login and registration flows, but the core idea is simple: guard routes with auth middleware.

PHP
Route::middleware('auth')->group(function () {
    Route::get('/dashboard', DashboardController::class)
        ->name('dashboard');

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

public function dashboard(Request $request)
{
    $user = $request->user();

    return view('dashboard', compact('user'));
}

Middleware

Middleware runs before or after a request. Use it for authentication, authorization, rate limiting, localization, and request checks.

PHP
public function handle($request, Closure $next)
{
    if (! $request->user()?->is_admin) {
        abort(403);
    }

    return $next($request);
}

Route::middleware(['auth', 'admin'])->group(function () {
    Route::get('/admin', AdminController::class);
});

APIs

Laravel can return JSON for front-end apps, mobile apps, and third-party integrations.

PHP
Route::get('/api/posts', function () {
    return Post::latest()
        ->select('id', 'title', 'created_at')
        ->paginate(10);
});

Route::post('/api/posts', function (Request $request) {
    $post = Post::create($request->validate([
        'title' => ['required', 'max:120'],
        'body' => ['required'],
    ]));

    return response()->json($post, 201);
});

Queues and Jobs

Jobs move slow work out of the request cycle. Examples include sending mail, processing images, syncing APIs, and generating reports.

Terminal / PHP
php artisan make:job SendWelcomeEmail

SendWelcomeEmail::dispatch($user);

// Run queued jobs locally
php artisan queue:work

Testing

Laravel supports feature tests for HTTP behavior and unit tests for small isolated logic.

PHP
public function test_home_page_loads(): void
{
    $response = $this->get('/');

    $response->assertStatus(200);
}

public function test_post_can_be_created(): void
{
    $response = $this->post('/posts', [
        'title' => 'Test Post',
        'body' => 'This is a test.',
    ]);

    $response->assertRedirect('/posts');
    $this->assertDatabaseHas('posts', ['title' => 'Test Post']);
}

Deployment Checklist

Before deploying a Laravel app, make sure production configuration and performance settings are ready.

  • Set APP_ENV=production and APP_DEBUG=false.
  • Configure database, mail, cache, queue, and storage values in .env.
  • Run composer install --no-dev --optimize-autoloader.
  • Run migrations with php artisan migrate --force.
  • Cache config, routes, and views when appropriate.
  • Point the web server document root to the public directory.