# Laravel middleware ile isteklere ortak davranış eklemek

> Laravel'de middleware nedir, nasıl yazılır ve kimlik doğrulama gibi kesişen ihtiyaçları nasıl tek yerde toplarım anlattım.

- Yayın: 2015-10-04
- Kategori: Framework & Kütüphane
- Etiketler: Laravel
- Okuma süresi: 3 dk okuma
- Kaynak: https://www.muhammetsafak.com.tr/blog/laravel-middleware-ile-isteklere-ortak-davranis-eklemek/
- Dil: tr-TR
- Yazar: Muhammet Şafak

---
Bir Laravel projesinde belirli route'lara yalnızca giriş yapmış kullanıcıların erişebilmesini istiyorsunuz. Klasik yöntem her controller metoduna kontrol eklemek:

```php
public function panel()
{
    if (!Auth::check()) {
        return redirect('/giris');
    }

    // ... asıl kod
}
```

Bu çalışır. Ama beş controller ve yirmi metod olduğunda aynı kodu yirmi yerde tekrarlıyorsunuz. Bir şeyi değiştirmeniz gerektiğinde yirmi yeri güncellemeniz gerekiyor.

**Middleware**, bu tür kesişen ihtiyaçları — kimlik doğrulama, yetkilendirme, istek kaydı, dil belirleme gibi her istekte tekrarlanan davranışları — tek bir yerde toplamanın yoludur. HTTP isteği ile controller arasına giriyor, isteği inceleyip değiştirebiliyor ya da tamamen durdurabiliyor.

## Middleware nasıl çalışır?

Laravel'de bir istek geldiğinde middleware zincirinden geçer. Her middleware ya isteği bir sonraki adıma geçirir ya da yanıtı döndürerek zinciri keser. Bunu bir kapı dizisi gibi düşünebilirsiniz — her kapı isteği inceliyor.

[Laravel 5](/blog/laravel-5e-gecis-yeni-dizin-yapisi-ve-env) öntanımlı olarak birkaç middleware içeriyor: `Authenticate` (kimlik doğrulama), `VerifyCsrfToken` (CSRF koruması), `RedirectIfAuthenticated` (giriş yapmışsa yönlendir). Bunlar `app/Http/Middleware/` altında.

## Kendi middleware'inizi yazmak

```bash
php artisan make:middleware GirisKontrol
```

Bu komut `app/Http/Middleware/GirisKontrol.php` dosyasını oluşturuyor:

```php
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;

class GirisKontrol
{
    public function handle($request, Closure $next)
    {
        if (!Auth::check()) {
            return redirect('/giris');
        }

        return $next($request);
    }
}
```

`handle` metodu iki parametre alıyor: gelen istek ve `$next` adını verdiğimiz closure. `$next($request)` çağrısı isteği bir sonraki adıma geçiriyor. Koşul sağlanmadığında `$next` çağrılmıyor ve zincir kırılıyor.

## Middleware'i kaydetmek

Yazılan middleware'i kullanabilmek için `app/Http/Kernel.php` içine kaydetmek gerekiyor. Bir kısa ad (alias) atıyorsunuz:

```php
protected $routeMiddleware = [
    'auth'    => \App\Http\Middleware\Authenticate::class,
    'giris'   => \App\Http\Middleware\GirisKontrol::class,
    // ...
];
```

## Route'lara uygulamak

Tek bir route için:

```php
Route::get('/panel', 'PanelController@index')->middleware('giris');
```

Birden fazla route için grup:

```php
Route::group(['middleware' => 'giris'], function () {
    Route::get('/panel',    'PanelController@index');
    Route::get('/profil',   'ProfilController@index');
    Route::get('/ayarlar',  'AyarlarController@index');
});
```

Bu gruba eklenen her route otomatik olarak `giris` middleware'inden geçiyor. Gruba yeni route eklemek için kontrol kodu yazmak gerekmiyor.

## Controller constructor'da kullanmak

Middleware'i route yerine controller seviyesinde de belirtebiliyorsunuz:

```php
class PanelController extends Controller
{
    public function __construct()
    {
        $this->middleware('giris');
    }
}
```

Yalnızca belirli metodlara uygulamak istiyorsanız:

```php
$this->middleware('giris')->only(['index', 'goster']);
$this->middleware('giris')->except(['hakkinda']);
```

Controller constructor'da middleware tanımlamak ile route grubunda tanımlamak arasında ince bir fark var: controller seviyesindeki tanım, o controller'a ait tüm route'ları kapsıyor — route tanımında middleware'i unutsanız bile. Ama route grubuna yeni bir controller eklediğinizde middleware'i gruba dahil etmeyi hatırlamanız gerekiyor. Hangisinin daha güvenilir olduğu projenin yapısına göre değişiyor.

## Yanıt sonrası middleware

Middleware yalnızca istek öncesinde değil, yanıt döndükten sonra da çalışabilir. Bunun için `$next`'i çağırdıktan sonra yanıtı işleyin:

```php
public function handle($request, Closure $next)
{
    $yanit = $next($request);

    // Yanıta başlık ekle
    $yanit->headers->set('X-Uygulama', 'benimsite');

    return $yanit;
}
```

İstek günlüğü tutmak, yanıt başlıkları eklemek ya da performans ölçümü bu kalıbı kullanıyor.

## Parametreli middleware

Middleware'e parametre geçirmek de mümkün. Örneğin rol kontrolü:

```php
public function handle($request, Closure $next, $rol)
{
    if (!$request->user()->hasRole($rol)) {
        abort(403);
    }

    return $next($request);
}
```

Route'ta `middleware('rol:admin')` şeklinde kullanılıyor. Birden fazla parametre için virgülle ayırıyorsunuz: `middleware('rol:admin,editor')`. Handle metodunda bu parametreler ek argüman olarak geliyor.

## Birden fazla middleware zincirlemek

Bir route'a birden fazla middleware uygulanabilir:

```php
Route::get('/admin/panel', 'AdminController@index')
     ->middleware(['giris', 'rol:admin']);
```

Middleware'ler sırayla çalışıyor. `giris` kontrolü başarısız olursa `rol:admin` hiç çalışmıyor. Bu sıralama önemli: önce kimlik doğrulama, sonra yetkilendirme. Tersi durumda giriş yapmamış kullanıcı için `$request->user()` null dönebilir ve rol kontrolü hata üretebilir.

Middleware mantığını bir kez anlayınca her controller'da tekrarlanan kontrol kodlarını temizleme isteği uyanıyor. Kimlik doğrulama, dil belirleme, istek kayıt alma gibi davranışlar doğal olarak buraya taşınıyor. Controller metodları asıl işe odaklanabiliyor.
