Bilal Ünal

Laravel 5.5 Kullanıcı-Rol İlişkisi

Lisans eğitimimin 3. senesinde aldığım “Veri tabanı sistemleri” dersi için bir proje geliştirmem gerekiyordu. Arkadaşımla beraber nasıl bir şey yapalım, ne kullanalım diye düşünürken bir otomasyon projesi geliştirmeye karar verdik. Backend kısmında RoR ve Laravel arasında gidip geldik ve Laravelde karar kıldık. Projenin içerisinde bir rol sistemi olması gerekiyordu. Her kullanıcının bir rolü olacak ve rol bilgisini programın çeşitli yerlerinde kullanacaktık. Bunu nasıl yapabilirim diye araştırırken Laravelin Middleware özelliğini keşfettim. Bir kaç deneme yaptım ve projeye uygun bir rol yapısı ekledim. Öncelikle middleware özelliğinden bahsedeceğim.

Laravel Middleware

Middlewarenin tanımı Laravel dökümanında şu şekilde yapılmış;

Middleware, uygulamanıza giren HTTP isteklerini filtrelemek için uygun bir mekanizma sağlar. Örneğin Laravel, uygulamanızın kullanıcısının kimlik doğrulamasını doğrulayan bir ara katmanı içeriyor. Kullanıcı kimliği doğrulanmazsa, katman kullanıcının oturum açma ekranına yönlendirecektir. Bununla birlikte, kullanıcı kimliği doğrulanırsa, ara katman, isteğin uygulamanın ilerleyişine izin vermesine izin verir.

Özetlemek gerekirse Middleware mekanizması HTTP isteklerini filtreleyebildiğimiz bir ara katmandır diyebiliriz. Bir çok frameworkde bu yapı bulunuyor. Middleware konusunu, yazının ilerleyen kısımlarında örnekler ile anlatmak üzere burada yarım bırakıyorum.

User ve Roles Tablosu

Bizim projede kullandığımız yapıda her kullanıcı bir role ait(belongsTo). Bu sebeple “roles” tablosu ile “users” tablosu arasında buna göre bir ilişki kurmamız gerekiyor. Aşağıda bu yapının kodlarına ulaşabilirsiniz.

Migrations

UsersTableMigration

<?php
Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->string('email')->unique();
    $table->string('password');
    $table->integer('role_id')->unsigned();
    $table->timestamps();
});

Bu tabloda bulunan role_id alanı “Roles” tablosundaki “id” primary keyini işaret ediyor.

RolesTableMigration

<?php
Schema::create('roles', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->string('readable_name');
});

readable_name fieldini ekleyip eklememek size kalmış. Biz o alanı kullanıcının rolünü View katmanında gösterdiğimiz için kullandık.

Models

App\User

<?php
class User extends Authenticatable
{
    //İlişkimizi oluşturuyoruz.
    public function role() {
        return $this->belongsTo('App\Role');
    }

    //Oluşturacağımız middlewarede kullanacağımız metodumuz.
    public function hasRole($role) {
        return true ? $this->role->name == $role : false;
    }
}

App\Role

<?php
class Role extends Model
{
    //Roles tablosunun users tablosu ile olan ilişkisini tanımlıyoruz.
    public function users() {
    return $this->hasMany('App\User');
    }
}

Middleware & Routing

Migrationları ve modelleri oluşturduktan sonra bir middleware oluşturmamız gerekiyor. İsterseniz laravelin içerisinde gelen Auth middlewaresini de kullanabilirsiniz, yeni bir tane oluşturmanıza gerek yok. Ben bu yazıda yeni bir tane oluşturacağım.

Middleware

php artisan make:middleware CheckRole

Komutu ile “CheckRole” isminde app/Http/Middleware dizini altında yeni bir middleware oluşturduk. Bu middlewarei kullanarak kullanıcının gitmek istediği URL’e erişme yetkisinin olup olmadığını kontrol edeceğiz.

<?php
class CheckRole
{
    //Requesti handle ettiğimiz metod.
    //Bu metod middlewarei oluşturduğunuz zaman otomatik olarak gelir.
    //Bu metoda ek olarak argüman ekleyebilirsiniz. Ben $role argümanını ekledim.
    public function handle($request, Closure $next, $role)
    {
        //User modelinde yazmış olduğumuz checkRole metodunu çağırıyoruz.
        //Parametre olarak requestten gelen $role parametresini gönderiyoruz.
        if (!$request->user()->hasRole($role)) {
            return redirect('home');
        }
        //İş akışını devam ettiriyoruz.
        return $next($request);
    }
}

Kullanacağımız middlewarei oluşturduk. Şimdi Laravele, requesti filtrelemek için yeni bir middleware oluşturduğumuzu söylememiz gerekiyor. Bunun için /app/Http/Kernel.php dosyasına, oluşturmuş olduğumuz middlewarenin etiketiyle birlikte ekleme yapacağız.

<?php
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
    'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'role' => \App\Http\Middleware\CheckRole::class,
];

Ben etiket olarak “role” kelimesini seçtim. İstediğiniz değeri yazabilirsiniz. Etiketi middlewarei çağırmak için kullanacağız.

Routing

Gerekli her şeyi oluşturduk. Şimdi sıra oluşturduğumuz middlewarei kullamaya geldi. Burada örnek bir kaç senaryodan bahsedeyim.

/admin/* şeklinde bir route tanımınız var ve buraya sadece rolü “admin” olan kullanıcıların erişebilmesini istiyorsunuz. /exam/list route tanımınıza sadece “teacher” rolündeki kullanıcıların erişmesini istiyorsunuz. Örnek routes/web.php dosyası;

<?php
Route::get('/admin', 'AdminController@index')->middleware('role:admin');
Route::resource('/admin/user', 'UserController')->middleware('role:admin');
Route::get('/exam/list', 'ExamController@list')->middleware('role:teacher');

middleware metodunun kullanımı şu şekilde;

->middleware(middleware etiket adı:middlewareye gönderilecek parametre değeri)

Sırasıyla;

  1. Kullanıcı /admin sayfasına ulaşmak için istek gönderir.
  2. Laravel bu isteği filtrelemek için bizim yazmış olduğumuz CheckRole middlewaresini katman olarak araya sokar.
  3. CheckRole sınıfının handle metodu ‘admin’ parametresi ile çağrılır.
  4. CheckRole sınıfı User modelinin hasRole metodunu ‘admin’ parametresi ile çağırır.
  5. Kullanıcıya response döner.

Umarım faydalı olmuştur. İyi günler.