Przejdź do treściMDS CloudNOWOŚĆWypróbuj mdscloud.pl
Backend

Laravel - A Complete Guide to the Most Popular PHP Framework

Published on:
·5 min read·Author: MDS Software Solutions Group

Laravel Complete Guide

backend

Laravel - A Complete Guide to the Most Popular PHP Framework

Laravel is the PHP framework that revolutionized web application development. Since its release in 2011 by Taylor Otwell, it has grown into the most popular framework in the PHP ecosystem. Its elegant syntax and rich toolset attract both beginners and experienced developers alike. In this guide, we will walk through the core elements of Laravel - from MVC architecture and Eloquent ORM to advanced queuing mechanisms and testing strategies.

Laravel stands out among PHP frameworks with several key features:

  • Elegant, expressive syntax - code that is readable and enjoyable to maintain
  • Massive ecosystem - from admin panels to cloud deployment
  • Active community - thousands of packages, Laracasts, Laracon conferences
  • Excellent documentation - among the best in the open-source world
  • Rapid prototyping - from idea to MVP in record time
  • Built-in security - CSRF, XSS, and SQL injection protection out of the box

According to the Stack Overflow survey, Laravel consistently ranks among the most used backend frameworks worldwide, and it has over 75,000 stars on GitHub.

MVC Architecture in Laravel#

Laravel implements the Model-View-Controller (MVC) pattern, which separates business logic from the presentation layer and HTTP request handling.

Model#

Models represent data and business logic. In Laravel, each model corresponds to a database table:

// app/Models/Article.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;

class Article extends Model
{
    use HasFactory, SoftDeletes;

    protected $fillable = [
        'title',
        'slug',
        'content',
        'excerpt',
        'published_at',
        'user_id',
        'category_id',
    ];

    protected $casts = [
        'published_at' => 'datetime',
    ];

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

    public function category()
    {
        return $this->belongsTo(Category::class);
    }

    public function tags()
    {
        return $this->belongsToMany(Tag::class);
    }

    public function scopePublished($query)
    {
        return $query->whereNotNull('published_at')
                     ->where('published_at', '<=', now());
    }
}

View (Blade)#

Views are responsible for presenting data to the user. Laravel uses the Blade templating engine, which we will cover in more detail later in this article.

Controller#

Controllers process HTTP requests and coordinate the interaction between the model and the view:

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

use App\Models\Article;
use App\Http\Requests\StoreArticleRequest;
use Illuminate\Http\Request;

class ArticleController extends Controller
{
    public function index(Request $request)
    {
        $articles = Article::published()
            ->with(['author', 'category', 'tags'])
            ->when($request->search, function ($query, $search) {
                $query->where('title', 'like', "%{$search}%");
            })
            ->latest('published_at')
            ->paginate(15);

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

    public function show(Article $article)
    {
        $article->load(['author', 'category', 'tags']);

        return view('articles.show', compact('article'));
    }

    public function store(StoreArticleRequest $request)
    {
        $article = $request->user()->articles()->create(
            $request->validated()
        );

        return redirect()
            ->route('articles.show', $article)
            ->with('success', 'Article published successfully.');
    }
}

Eloquent ORM - A Powerful Database Management System#

Eloquent is the ORM (Object-Relational Mapping) built into Laravel that enables elegant database interactions through PHP models. It is one of the framework's most important components.

Relationships in Eloquent#

Eloquent supports all standard database relationship types:

// One to Many
class User extends Model
{
    public function articles()
    {
        return $this->hasMany(Article::class);
    }

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

// Many to Many with pivot table
class Article extends Model
{
    public function tags()
    {
        return $this->belongsToMany(Tag::class)
                    ->withPivot('order')
                    ->withTimestamps();
    }
}

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

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

Advanced Queries#

The Eloquent Query Builder allows you to construct complex queries in an elegant manner:

// Advanced filtering with eager loading
$articles = Article::query()
    ->with(['author:id,name,avatar', 'tags:id,name,slug'])
    ->withCount('comments')
    ->where('category_id', $categoryId)
    ->whereHas('tags', function ($query) use ($tagSlug) {
        $query->where('slug', $tagSlug);
    })
    ->when($sortBy === 'popular', function ($query) {
        $query->orderByDesc('comments_count');
    }, function ($query) {
        $query->latest('published_at');
    })
    ->paginate(20);

// Aggregation and grouping
$stats = Article::query()
    ->selectRaw('category_id, COUNT(*) as total, AVG(views) as avg_views')
    ->where('published_at', '>=', now()->subYear())
    ->groupBy('category_id')
    ->having('total', '>', 5)
    ->get();

// Bulk operations
Article::where('published_at', '<', now()->subYears(2))
    ->update(['archived' => true]);

// Upsert - insert or update
Article::upsert(
    [
        ['slug' => 'laravel-guide', 'title' => 'Laravel Guide', 'views' => 1],
        ['slug' => 'php-tips', 'title' => 'PHP Tips', 'views' => 1],
    ],
    uniqueBy: ['slug'],
    update: ['title']
);

Migrations and Seeders#

Laravel manages database schemas through migrations:

// database/migrations/2025_03_10_create_articles_table.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('articles', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->foreignId('category_id')->constrained();
            $table->string('title');
            $table->string('slug')->unique();
            $table->text('excerpt')->nullable();
            $table->longText('content');
            $table->unsignedInteger('views')->default(0);
            $table->timestamp('published_at')->nullable()->index();
            $table->softDeletes();
            $table->timestamps();

            $table->fullText(['title', 'content']);
        });
    }

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

Blade - The Templating Engine#

Blade is a lightweight yet powerful templating engine included with Laravel. It compiles templates into plain PHP code, so there is no additional performance overhead.

{{-- resources/views/articles/index.blade.php --}}
<x-app-layout>
    <x-slot name="header">
        <h1 class="text-2xl font-bold">{{ __('Articles') }}</h1>
    </x-slot>

    <div class="max-w-7xl mx-auto py-8">
        {{-- Search form --}}
        <form action="{{ route('articles.index') }}" method="GET" class="mb-6">
            <x-input
                name="search"
                value="{{ request('search') }}"
                placeholder="Search articles..."
            />
        </form>

        {{-- Article list --}}
        @forelse ($articles as $article)
            <article class="mb-6 p-6 bg-white rounded-lg shadow">
                <h2 class="text-xl font-semibold">
                    <a href="{{ route('articles.show', $article) }}">
                        {{ $article->title }}
                    </a>
                </h2>

                <div class="text-sm text-gray-500 mt-2">
                    {{ $article->published_at->format('F d, Y') }}
                    &middot; {{ $article->author->name }}
                </div>

                <p class="mt-3 text-gray-700">{{ $article->excerpt }}</p>

                <div class="mt-3 flex gap-2">
                    @foreach ($article->tags as $tag)
                        <x-badge>{{ $tag->name }}</x-badge>
                    @endforeach
                </div>
            </article>
        @empty
            <p class="text-gray-500">{{ __('No articles to display.') }}</p>
        @endforelse

        {{-- Pagination --}}
        <div class="mt-8">
            {{ $articles->withQueryString()->links() }}
        </div>
    </div>
</x-app-layout>

Blade Components#

Laravel enables the creation of reusable components:

// app/View/Components/Badge.php
namespace App\View\Components;

use Illuminate\View\Component;

class Badge extends Component
{
    public function __construct(
        public string $color = 'blue'
    ) {}

    public function render()
    {
        return view('components.badge');
    }
}
{{-- resources/views/components/badge.blade.php --}}
<span {{ $attributes->merge([
    'class' => "inline-flex items-center px-2.5 py-0.5 rounded-full text-xs
                font-medium bg-{$color}-100 text-{$color}-800"
]) }}>
    {{ $slot }}
</span>

Artisan CLI - The Command-Line Tool#

Artisan is the command-line interface shipped with Laravel. It provides dozens of useful commands that accelerate everyday development:

# Code generation
php artisan make:model Article -mfsc    # Model + migration + factory + seeder + controller
php artisan make:request StoreArticleRequest
php artisan make:middleware EnsureArticleOwner
php artisan make:job ProcessArticleImages
php artisan make:event ArticlePublished
php artisan make:listener SendArticleNotification

# Migrations
php artisan migrate                     # Run migrations
php artisan migrate:rollback            # Roll back the last batch
php artisan migrate:fresh --seed        # Rebuild database and run seeders

# Cache and optimization
php artisan config:cache                # Cache configuration
php artisan route:cache                 # Cache routes
php artisan view:cache                  # Compile views
php artisan optimize                    # Production optimization

# Queues
php artisan queue:work --tries=3        # Queue worker
php artisan queue:failed                # Display failed jobs

# Interactive console
php artisan tinker                      # REPL for experimentation

You can also create custom Artisan commands:

// app/Console/Commands/GenerateSitemap.php
namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Models\Article;

class GenerateSitemap extends Command
{
    protected $signature = 'sitemap:generate
                            {--format=xml : Output format (xml|json)}';

    protected $description = 'Generate a sitemap based on published articles';

    public function handle(): int
    {
        $articles = Article::published()->get();

        $this->info("Generating sitemap for {$articles->count()} articles...");

        $bar = $this->output->createProgressBar($articles->count());

        foreach ($articles as $article) {
            // sitemap generation logic
            $bar->advance();
        }

        $bar->finish();
        $this->newLine();
        $this->info('Sitemap generated successfully!');

        return Command::SUCCESS;
    }
}

Routing and Middleware#

Laravel's routing system is intuitive and flexible:

// routes/web.php
use App\Http\Controllers\ArticleController;
use App\Http\Controllers\Api\ArticleApiController;

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

// Resource routing - generates 7 standard CRUD routes
Route::resource('articles', ArticleController::class);

// API routing with versioning
Route::prefix('api/v1')->middleware('auth:sanctum')->group(function () {
    Route::apiResource('articles', ArticleApiController::class);

    Route::post('articles/{article}/publish', [ArticleApiController::class, 'publish'])
        ->middleware('can:publish,article');
});

// Route grouping
Route::middleware(['auth', 'verified'])->prefix('admin')->name('admin.')->group(function () {
    Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard');
    Route::resource('users', UserController::class)->except(['show']);
});

Creating Middleware#

Middleware are filters that process HTTP requests:

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

use Closure;
use Illuminate\Http\Request;
use App\Models\PageView;

class TrackPageViews
{
    public function handle(Request $request, Closure $next)
    {
        $response = $next($request);

        if ($request->isMethod('GET') && !$request->ajax()) {
            PageView::create([
                'url' => $request->fullUrl(),
                'user_id' => $request->user()?->id,
                'ip_address' => $request->ip(),
                'user_agent' => $request->userAgent(),
            ]);
        }

        return $response;
    }
}

Authentication and Authorization#

Laravel offers several starter kits for authentication:

Laravel Breeze#

A minimal package with full implementation of login, registration, password reset, and email verification:

composer require laravel/breeze --dev
php artisan breeze:install blade   # or react, vue, api
php artisan migrate
npm install && npm run dev

Laravel Jetstream#

An advanced package with additional features:

  • Two-factor authentication (2FA)
  • Session management
  • Team management
  • API integration (Sanctum tokens)

Authorization Policies#

Laravel enables you to define authorization policies:

// app/Policies/ArticlePolicy.php
namespace App\Policies;

use App\Models\Article;
use App\Models\User;

class ArticlePolicy
{
    public function update(User $user, Article $article): bool
    {
        return $user->id === $article->user_id
            || $user->hasRole('editor');
    }

    public function delete(User $user, Article $article): bool
    {
        return $user->id === $article->user_id
            || $user->hasRole('admin');
    }

    public function publish(User $user, Article $article): bool
    {
        return $user->hasAnyRole(['editor', 'admin']);
    }
}

Usage in a controller:

public function update(StoreArticleRequest $request, Article $article)
{
    $this->authorize('update', $article);

    $article->update($request->validated());

    return redirect()->route('articles.show', $article);
}

Queues and Jobs#

Laravel's queue system allows you to defer time-consuming operations, significantly improving application response times:

// app/Jobs/ProcessArticleImages.php
namespace App\Jobs;

use App\Models\Article;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\Facades\Image;

class ProcessArticleImages implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public int $tries = 3;
    public int $backoff = 60;
    public int $timeout = 120;

    public function __construct(
        private Article $article
    ) {}

    public function handle(): void
    {
        $content = $this->article->content;

        preg_match_all('/<img[^>]+src="([^"]+)"/', $content, $matches);

        foreach ($matches[1] as $imageUrl) {
            $image = Image::make($imageUrl);

            // Generate thumbnail
            $thumbnail = $image->fit(400, 300);
            $thumbnailPath = 'thumbnails/' . basename($imageUrl);
            Storage::disk('public')->put($thumbnailPath, $thumbnail->encode());

            // Generate WebP version
            $webp = $image->encode('webp', 85);
            $webpPath = 'images/' . pathinfo(basename($imageUrl), PATHINFO_FILENAME) . '.webp';
            Storage::disk('public')->put($webpPath, $webp);
        }
    }

    public function failed(\Throwable $exception): void
    {
        logger()->error('Image processing failed', [
            'article_id' => $this->article->id,
            'error' => $exception->getMessage(),
        ]);
    }
}

Dispatching jobs:

// Dispatch to queue
ProcessArticleImages::dispatch($article);

// Dispatch with delay
ProcessArticleImages::dispatch($article)->delay(now()->addMinutes(5));

// Job chaining
Bus::chain([
    new ProcessArticleImages($article),
    new GenerateArticleSummary($article),
    new NotifySubscribers($article),
])->dispatch();

Laravel Sail - Docker for Laravel#

Laravel Sail is a lightweight tool for managing Docker environments in Laravel projects:

# Creating a new project with Sail
curl -s "https://laravel.build/my-project?with=mysql,redis,meilisearch" | bash

# Starting the environment
cd my-project
./vendor/bin/sail up -d

# Commands via Sail
./vendor/bin/sail artisan migrate
./vendor/bin/sail composer require laravel/sanctum
./vendor/bin/sail npm run dev
./vendor/bin/sail test
./vendor/bin/sail tinker

Sail provides ready-made containers with PHP, MySQL/PostgreSQL, Redis, Meilisearch, Mailpit, and other services, eliminating the need for manual development environment configuration.

Testing with PHPUnit and Pest#

Laravel is built with testability in mind. The framework supports both PHPUnit and the modern Pest testing framework:

Tests with Pest#

// tests/Feature/ArticleTest.php
use App\Models\Article;
use App\Models\User;

beforeEach(function () {
    $this->user = User::factory()->create();
});

it('displays published articles on the index page', function () {
    $articles = Article::factory()
        ->count(3)
        ->published()
        ->create();

    $this->get(route('articles.index'))
        ->assertOk()
        ->assertSee($articles->first()->title);
});

it('allows authenticated users to create articles', function () {
    $articleData = [
        'title' => 'Test Article',
        'content' => 'Content of the test article',
        'category_id' => Category::factory()->create()->id,
    ];

    $this->actingAs($this->user)
        ->post(route('articles.store'), $articleData)
        ->assertRedirect();

    $this->assertDatabaseHas('articles', [
        'title' => 'Test Article',
        'user_id' => $this->user->id,
    ]);
});

it('prevents guests from creating articles', function () {
    $this->post(route('articles.store'), [])
        ->assertRedirect(route('login'));
});

it('validates required fields when creating an article', function () {
    $this->actingAs($this->user)
        ->post(route('articles.store'), [])
        ->assertSessionHasErrors(['title', 'content', 'category_id']);
});

HTTP API Tests#

it('returns paginated articles from API', function () {
    Article::factory()->count(25)->published()->create();

    $response = $this->actingAs($this->user, 'sanctum')
        ->getJson('/api/v1/articles?page=1&per_page=10');

    $response->assertOk()
        ->assertJsonCount(10, 'data')
        ->assertJsonStructure([
            'data' => [['id', 'title', 'slug', 'excerpt', 'published_at']],
            'meta' => ['current_page', 'last_page', 'total'],
        ]);
});

The Laravel Ecosystem#

Laravel is not just a framework - it is an entire ecosystem of tools:

Laravel Nova#

A premium admin panel that enables rapid creation of CRUD interfaces:

// app/Nova/Article.php
class Article extends Resource
{
    public static $model = \App\Models\Article::class;

    public function fields(Request $request)
    {
        return [
            ID::make()->sortable(),
            Text::make('Title', 'title')->sortable()->rules('required'),
            Slug::make('Slug')->from('title'),
            Markdown::make('Content', 'content')->rules('required'),
            BelongsTo::make('Author', 'author', User::class),
            DateTime::make('Published At', 'published_at'),
        ];
    }
}

Laravel Forge#

A server management platform that automates server provisioning on DigitalOcean, AWS, Hetzner, and others. It configures Nginx, PHP, SSL, databases, and much more with a single click.

Laravel Vapor#

Serverless deployment for Laravel on AWS Lambda. Automatic scaling, zero server management, integration with SQS, S3, CloudFront, and Aurora.

Other Ecosystem Tools#

  • Laravel Horizon - a dashboard for monitoring Redis queues
  • Laravel Telescope - a debugger and profiler for development environments
  • Laravel Pint - an automatic code fixer based on PHP-CS-Fixer
  • Laravel Pennant - feature flags
  • Laravel Pulse - real-time application performance monitoring
  • Laravel Reverb - first-party WebSocket server

Performance Optimization#

Here are several proven techniques for optimizing Laravel applications:

Eager Loading - Eliminating the N+1 Problem#

// Instead of this (N+1 problem):
$articles = Article::all();
foreach ($articles as $article) {
    echo $article->author->name; // Additional query for each article
}

// Use eager loading:
$articles = Article::with('author')->get();
foreach ($articles as $article) {
    echo $article->author->name; // No additional queries
}

// Prevent N+1 in development:
// AppServiceProvider.php
Model::preventLazyLoading(!app()->isProduction());

Data Caching#

use Illuminate\Support\Facades\Cache;

// Cache with TTL
$popularArticles = Cache::remember('popular_articles', 3600, function () {
    return Article::published()
        ->withCount('comments')
        ->orderByDesc('comments_count')
        ->take(10)
        ->get();
});

// Cache tags (requires Redis or Memcached)
Cache::tags(['articles', 'homepage'])->put('featured', $articles, 3600);
Cache::tags(['articles'])->flush(); // Clear all article caches

Production Optimization Commands#

php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache
php artisan optimize
composer install --optimize-autoloader --no-dev

Database Indexes#

// In a migration - adding indexes
Schema::table('articles', function (Blueprint $table) {
    $table->index('published_at');
    $table->index(['category_id', 'published_at']);
    $table->fullText(['title', 'content']);
});

Conclusion#

Laravel is a mature, versatile framework that allows you to build applications of any scale - from simple websites to complex enterprise systems. Its elegant syntax, powerful Eloquent ORM, extensive ecosystem, and active community make it an excellent choice for startups and large organizations alike.

Key strengths of Laravel:

  • Productivity - ready-made solutions for common web problems
  • Scalability - queues, caching, serverless with Vapor
  • Security - built-in protection against the most common attacks
  • Testability - easy test writing with PHPUnit and Pest
  • Ecosystem - from Nova to Forge, everything a team needs

Need a Professional Laravel Application?#

MDS Software Solutions Group specializes in building high-performance, scalable web applications using Laravel and modern backend technologies. Our team of experienced developers will help you design, build, and deploy a solution tailored to your business needs.

We offer:

  • Custom web application development from scratch
  • Modernization and optimization of existing systems
  • Integration with third-party APIs and services
  • Cloud deployment and DevOps

Get in touch with us and let's discuss your project.

Author
MDS Software Solutions Group

Team of programming experts specializing in modern web technologies.

Laravel - A Complete Guide to the Most Popular PHP Framework | MDS Software Solutions Group | MDS Software Solutions Group