Laravel - kompletny przewodnik po najpopularniejszym frameworku PHP
Laravel kompletny przewodnik
backendLaravel - kompletny przewodnik po najpopularniejszym frameworku PHP
Laravel to framework PHP, który zrewolucjonizował sposób tworzenia aplikacji webowych. Od momentu premiery w 2011 roku, autorstwa Taylora Otwella, stał się najpopularniejszym frameworkiem w ekosystemie PHP, a jego elegancka składnia i bogaty zestaw narzędzi przyciągają zarówno początkujących, jak i doświadczonych programistów. W tym przewodniku omówimy kluczowe elementy Laravela - od architektury MVC, przez Eloquent ORM, aż po zaawansowane mechanizmy kolejkowania i testowania.
Dlaczego Laravel jest tak popularny?#
Laravel wyróżnia się na tle innych frameworków PHP kilkoma kluczowymi cechami:
- Elegancka, ekspresywna składnia - kod jest czytelny i przyjemny w utrzymaniu
- Ogromny ekosystem - od paneli administracyjnych po deployment w chmurze
- Aktywna społeczność - tysiące pakietów, Laracasts, konferencje Laracon
- Doskonała dokumentacja - jedna z najlepszych w świecie open-source
- Szybkie prototypowanie - od pomysłu do MVP w rekordowym czasie
- Wbudowane bezpieczeństwo - ochrona przed CSRF, XSS, SQL injection out-of-the-box
Według ankiety Stack Overflow, Laravel konsekwentnie plasuje się wśród najczęściej używanych frameworków backendowych na świecie, a na GitHubie posiada ponad 75 tysięcy gwiazdek.
Architektura MVC w Laravel#
Laravel implementuje wzorzec Model-View-Controller (MVC), który oddziela logikę biznesową od warstwy prezentacji i obsługi żądań HTTP.
Model#
Modele reprezentują dane i logikę biznesową. W Laravel każdy model odpowiada tabeli w bazie danych:
// 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)#
Widoki odpowiadają za prezentację danych użytkownikowi. Laravel wykorzystuje silnik szablonów Blade, o którym więcej powiemy w dalszej części artykułu.
Controller#
Kontrolery przetwarzają żądania HTTP i koordynują interakcję między modelem a widokiem:
// 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', 'Artykuł został opublikowany.');
}
}
Eloquent ORM - potężny system zarządzania bazą danych#
Eloquent to ORM (Object-Relational Mapping) wbudowany w Laravel, który umożliwia elegancką pracę z bazą danych za pomocą modeli PHP. Jest to jeden z najważniejszych elementów frameworka.
Relacje w Eloquent#
Eloquent obsługuje wszystkie standardowe typy relacji bazodanowych:
// Jeden do wielu (One to Many)
class User extends Model
{
public function articles()
{
return $this->hasMany(Article::class);
}
public function profile()
{
return $this->hasOne(Profile::class);
}
}
// Wiele do wielu (Many to Many) z tabelą pośrednią
class Article extends Model
{
public function tags()
{
return $this->belongsToMany(Tag::class)
->withPivot('order')
->withTimestamps();
}
}
// Relacja polimorficzna
class Comment extends Model
{
public function commentable()
{
return $this->morphTo();
}
}
class Article extends Model
{
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
}
Zaawansowane zapytania#
Eloquent Query Builder pozwala na budowanie skomplikowanych zapytań w elegancki sposób:
// Zaawansowane filtrowanie z 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);
// Agregacja i grupowanie
$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();
// Masowe operacje
Article::where('published_at', '<', now()->subYears(2))
->update(['archived' => true]);
// Upsert - wstaw lub zaktualizuj
Article::upsert(
[
['slug' => 'laravel-guide', 'title' => 'Laravel Guide', 'views' => 1],
['slug' => 'php-tips', 'title' => 'PHP Tips', 'views' => 1],
],
uniqueBy: ['slug'],
update: ['title']
);
Migracje i seedery#
Laravel zarządza schematem bazy danych za pomocą migracji:
// 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 - silnik szablonów#
Blade to lekki, ale niezwykle potężny silnik szablonów Laravela. Kompiluje szablony do czystego kodu PHP, więc nie narzuca dodatkowego narzutu wydajnościowego.
{{-- resources/views/articles/index.blade.php --}}
<x-app-layout>
<x-slot name="header">
<h1 class="text-2xl font-bold">{{ __('Artykuły') }}</h1>
</x-slot>
<div class="max-w-7xl mx-auto py-8">
{{-- Formularz wyszukiwania --}}
<form action="{{ route('articles.index') }}" method="GET" class="mb-6">
<x-input
name="search"
value="{{ request('search') }}"
placeholder="Szukaj artykułów..."
/>
</form>
{{-- Lista artykułów --}}
@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->translatedFormat('d F Y') }}
· {{ $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">{{ __('Brak artykułów do wyświetlenia.') }}</p>
@endforelse
{{-- Paginacja --}}
<div class="mt-8">
{{ $articles->withQueryString()->links() }}
</div>
</div>
</x-app-layout>
Komponenty Blade#
Laravel umożliwia tworzenie reużywalnych komponentów:
// 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 - narzędzie wiersza poleceń#
Artisan to interfejs wiersza poleceń dostarczany z Laravelem. Oferuje dziesiątki przydatnych komend przyspieszających codzienną pracę:
# Generowanie kodu
php artisan make:model Article -mfsc # Model + migracja + fabryka + seeder + kontroler
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
# Migracje
php artisan migrate # Uruchom migracje
php artisan migrate:rollback # Cofnij ostatni batch
php artisan migrate:fresh --seed # Odtwórz bazę i uruchom seedery
# Cache i optymalizacja
php artisan config:cache # Cache konfiguracji
php artisan route:cache # Cache tras
php artisan view:cache # Kompilacja widoków
php artisan optimize # Optymalizacja produkcyjna
# Kolejki
php artisan queue:work --tries=3 # Worker kolejki
php artisan queue:failed # Wyświetl nieudane zadania
# Konsola interaktywna
php artisan tinker # REPL do eksperymentowania
Możesz także tworzyć własne komendy Artisan:
// 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 : Format wyjściowy (xml|json)}';
protected $description = 'Generuje mapę strony na podstawie opublikowanych artykułów';
public function handle(): int
{
$articles = Article::published()->get();
$this->info("Generowanie mapy strony dla {$articles->count()} artykułów...");
$bar = $this->output->createProgressBar($articles->count());
foreach ($articles as $article) {
// logika generowania sitemap
$bar->advance();
}
$bar->finish();
$this->newLine();
$this->info('Mapa strony wygenerowana pomyślnie!');
return Command::SUCCESS;
}
}
Routing i middleware#
System routingu w Laravel jest intuicyjny i elastyczny:
// routes/web.php
use App\Http\Controllers\ArticleController;
use App\Http\Controllers\Api\ArticleApiController;
// Podstawowy routing
Route::get('/', function () {
return view('welcome');
});
// Resource routing - generuje 7 standardowych tras CRUD
Route::resource('articles', ArticleController::class);
// API routing z wersjonowaniem
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');
});
// Grupowanie tras
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']);
});
Tworzenie middleware#
Middleware to filtry przetwarzające żądania HTTP:
// 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;
}
}
Uwierzytelnianie i autoryzacja#
Laravel oferuje kilka gotowych pakietów startowych do uwierzytelniania:
Laravel Breeze#
Minimalistyczny pakiet z pełną implementacją logowania, rejestracji, resetowania hasła i weryfikacji e-mail:
composer require laravel/breeze --dev
php artisan breeze:install blade # lub react, vue, api
php artisan migrate
npm install && npm run dev
Laravel Jetstream#
Zaawansowany pakiet z dodatkowymi funkcjami:
- Uwierzytelnianie dwuskładnikowe (2FA)
- Zarządzanie sesjami
- Zarządzanie zespołami
- Integracja z API (tokeny Sanctum)
Polityki autoryzacji#
Laravel umożliwia definiowanie polityk autoryzacji:
// 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']);
}
}
Użycie w kontrolerze:
public function update(StoreArticleRequest $request, Article $article)
{
$this->authorize('update', $article);
$article->update($request->validated());
return redirect()->route('articles.show', $article);
}
Kolejki i zadania (Queues & Jobs)#
System kolejek Laravela pozwala na odroczenie czasochłonnych operacji, znacznie poprawiając czas odpowiedzi aplikacji:
// 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);
// Generuj miniaturę
$thumbnail = $image->fit(400, 300);
$thumbnailPath = 'thumbnails/' . basename($imageUrl);
Storage::disk('public')->put($thumbnailPath, $thumbnail->encode());
// Generuj wersję WebP
$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('Przetwarzanie obrazów nie powiodło się', [
'article_id' => $this->article->id,
'error' => $exception->getMessage(),
]);
}
}
Dispatch zadania:
// Dispatch do kolejki
ProcessArticleImages::dispatch($article);
// Dispatch z opóźnieniem
ProcessArticleImages::dispatch($article)->delay(now()->addMinutes(5));
// Łańcuch zadań
Bus::chain([
new ProcessArticleImages($article),
new GenerateArticleSummary($article),
new NotifySubscribers($article),
])->dispatch();
Laravel Sail - Docker dla Laravela#
Laravel Sail to lekkie narzędzie do zarządzania środowiskiem Docker dla projektów Laravel:
# Tworzenie nowego projektu z Sail
curl -s "https://laravel.build/my-project?with=mysql,redis,meilisearch" | bash
# Uruchomienie środowiska
cd my-project
./vendor/bin/sail up -d
# Komendy przez 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 dostarcza gotowe kontenary z PHP, MySQL/PostgreSQL, Redis, Meilisearch, Mailpit i innymi usługami, eliminując konieczność ręcznej konfiguracji środowiska deweloperskiego.
Testowanie z PHPUnit i Pest#
Laravel jest zbudowany z myślą o testowalności. Framework wspiera zarówno PHPUnit, jak i nowoczesny Pest:
Testy z 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' => 'Testowy artykuł',
'content' => 'Treść testowego artykułu',
'category_id' => Category::factory()->create()->id,
];
$this->actingAs($this->user)
->post(route('articles.store'), $articleData)
->assertRedirect();
$this->assertDatabaseHas('articles', [
'title' => 'Testowy artykuł',
'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']);
});
Testy HTTP API#
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'],
]);
});
Ekosystem Laravela#
Laravel to nie tylko framework - to cały ekosystem narzędzi:
Laravel Nova#
Panel administracyjny premium, który pozwala na szybkie tworzenie interfejsów CRUD:
// 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('Tytuł', 'title')->sortable()->rules('required'),
Slug::make('Slug')->from('title'),
Markdown::make('Treść', 'content')->rules('required'),
BelongsTo::make('Autor', 'author', User::class),
DateTime::make('Opublikowano', 'published_at'),
];
}
}
Laravel Forge#
Platforma do zarządzania serwerami - automatyzuje provisioning serwerów na DigitalOcean, AWS, Hetzner i innych. Konfiguruje Nginx, PHP, SSL, bazy danych i wiele więcej jednym kliknięciem.
Laravel Vapor#
Serverless deployment dla Laravela na AWS Lambda. Automatyczne skalowanie, zero zarządzania serwerami, integracja z SQS, S3, CloudFront i Aurora.
Inne narzędzia ekosystemu#
- Laravel Horizon - dashboard do monitorowania kolejek Redis
- Laravel Telescope - debugger i profiler dla środowiska deweloperskiego
- Laravel Pint - automatyczny code fixer oparty na PHP-CS-Fixer
- Laravel Pennant - feature flags
- Laravel Pulse - monitoring wydajności aplikacji w czasie rzeczywistym
- Laravel Reverb - serwer WebSocket pierwszej strony
Optymalizacja wydajności#
Kilka sprawdzonych technik optymalizacji aplikacji Laravel:
Eager Loading - eliminacja problemu N+1#
// Zamiast tego (N+1 problem):
$articles = Article::all();
foreach ($articles as $article) {
echo $article->author->name; // Dodatkowe zapytanie dla każdego artykułu
}
// Użyj eager loading:
$articles = Article::with('author')->get();
foreach ($articles as $article) {
echo $article->author->name; // Brak dodatkowych zapytań
}
// Zapobieganie N+1 w środowisku deweloperskim:
// AppServiceProvider.php
Model::preventLazyLoading(!app()->isProduction());
Cache'owanie danych#
use Illuminate\Support\Facades\Cache;
// Cache z TTL
$popularArticles = Cache::remember('popular_articles', 3600, function () {
return Article::published()
->withCount('comments')
->orderByDesc('comments_count')
->take(10)
->get();
});
// Cache tags (wymaga Redis lub Memcached)
Cache::tags(['articles', 'homepage'])->put('featured', $articles, 3600);
Cache::tags(['articles'])->flush(); // Wyczyść wszystkie cache artykułów
Komendy optymalizacyjne na produkcji#
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
Indeksy bazy danych#
// W migracji - dodawanie indeksów
Schema::table('articles', function (Blueprint $table) {
$table->index('published_at');
$table->index(['category_id', 'published_at']);
$table->fullText(['title', 'content']);
});
Podsumowanie#
Laravel to dojrzały, wszechstronny framework, który pozwala budować aplikacje każdej skali - od prostych stron internetowych po rozbudowane systemy enterprise. Jego elegancka składnia, potężny Eloquent ORM, rozbudowany ekosystem i aktywna społeczność sprawiają, że jest doskonałym wyborem zarówno dla startupów, jak i dużych organizacji.
Kluczowe atuty Laravela:
- Produktywność - gotowe rozwiązania dla typowych problemów webowych
- Skalowalność - kolejki, cache, serverless z Vapor
- Bezpieczeństwo - wbudowana ochrona przed najczęstszymi atakami
- Testowalność - łatwe pisanie testów z PHPUnit i Pest
- Ekosystem - od Nova po Forge, wszystko czego potrzebuje zespół
Potrzebujesz profesjonalnej aplikacji w Laravel?#
MDS Software Solutions Group specjalizuje się w tworzeniu wydajnych, skalowalnych aplikacji webowych z wykorzystaniem Laravel i nowoczesnych technologii backendowych. Nasz zespół doświadczonych programistów pomoże Ci zaprojektować, zbudować i wdrożyć rozwiązanie dopasowane do Twoich potrzeb biznesowych.
Oferujemy:
- Tworzenie aplikacji webowych od podstaw
- Modernizację i optymalizację istniejących systemów
- Integracje z zewnętrznymi API i usługami
- Wdrożenia w chmurze i DevOps
Skontaktuj się z nami i porozmawiajmy o Twoim projekcie.
Zespół ekspertów programistycznych specjalizujących się w nowoczesnych technologiach webowych.
