Laravel 8 ile adım adım Middleware Oluşturmak

LARAVEL 8 ILE ADIM ADIM MIDDLEWARE OLUŞTURMAK

Bu yazımızda Laravel 8 ile kullanıcıların rolüne göre Middleware oluşturacağız ve çeşitli route ları koruyacağız. Bunun için;

  • Middleware oluşturup uygulamamıza ve route lara eklememiz,
  • Role isimli bir model ve bunu oluşturan bir migration oluşturmamız,
  • Uygulamada default olarak bulunan User model’e ve User oluşturan dosyaya yeni bir alan eklememiz,
  • Veritabanını baştan oluşturmamız gereklidir.

Mıddleware olusturma

Ben öncelikle middleware’i oluşturup uygulamaya ekledikten sonra üstte saydıklarıma geçeceğim. Bu adımlardan birinin eksik veya hatalı olması durumunda middleware çalışmayabilir, uygulama hata verebilir. Eksiksiz takip ettiğinizden emin olun, çalışan yapıdır.

Bir Middleware oluşturmak için aşağıdaki artisan komutunu kullanmamız gerekli, isim olarak ben “RoleMiddleware” ismini seçtim.

php artisan make:middleware RoleMiddleware

İçeriği aşağıdaki gibi olmalı;


class RoleMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next, string $role)
    {
        if ($role == 'admin' && auth()->user()->role_id != 2) {
            abort(403);
        }

        if ($role == 'member' && auth()->user()->role_id != 1) {
            abort(403);
        }

        return $next($request);
    }
}

Dikkat ettiyseniz bu middleware’in bir parametresi var, “string $role” bir middleware parametresi burada. Bu parametre yardımıyla request yapan kullanıcıyı alıp rolüne göre çeşitli işlemler yapabiliriz, ben yukarıda “auth()->user()” helper methodu ve “$role” isimli parametre yardımıyla “User” model’a eklediğim alanlara göre “abort(403)” hatası yani yetkiniz yok hatası döndürüyorum. Siz isterseniz farklı bir hata döndürebilirsiniz veya bir view’a yönlendirme yapabilirsiniz. Burada önemli olan “return $next($request)” kısmı, bunu unutmamalısınız.

Middleware’i oluşturduk şimdi ise eklememiz gerekiyor. Uygulamamızdaki “app/Http/Kernel.php” dosyasını açalım. Oluşturduğumuz middleware’i aşağıdaki kısma ekleyelim;

 protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,

    // alttaki satır oluşturduğumuz middleware'i uygulamaya eklemek içindir
        'role' => \App\Http\Middleware\RoleMiddleware::class,
    ];

Şimdi ise bir route grubuna bu middleware’i ve auth middleware’i ekleyelim, bunu yapmamız gerekiyor çünkü Laravel middleware’i uygulayacağımız route lara gelen request leri buna göre yönlendirecek. Bu middleware’in çalışması için uygulamada login olmuş bir User gerekiyor, bunu da route larımıza “auth” middleware’i ekleyerek yapıyoruz. Yani login olmamış bir request bu middleware’e ulaşamamalı.

// Bu route grubunda "role" ün ardından gelen kısıma dikkat edin, burası middleware'e parametresini verdiğimiz kısım, parametreyi burada "member" olarak veriyoruz.

Route::group(['middleware' => 'auth'], function () {

   // Bu route grubunda parametreyi "member" olarak veriyoruz.
   Route::group(['middleware' => 'role:member'], function () {
       // istediğiniz kadar route tanımlayabilirsiniz
        Route::get('...');
        Route::post('...');
        Route::delete('...');
    });

// Bu route grubunda ise parametreyi "admin" olarak veriyoruz.
Route::group(['middleware' => 'role:admin'], function () {

    // istediğiniz kadar route tanımlayabilirsiniz
        Route::get('...');
        Route::post('...');
        Route::delete('...');
    });
});

Role Model olusturma

Şimdi de role tablosu için migration oluşturuyoruz ve “name” alanını ekliyoruz, middleware parametresi bu “name” isimli alandan gelecek;

php artisan make:migration CreateRolesTable
class CreateRolesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('roles', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('roles');
    }
}

Sırada ise Role model oluşturmak var;

php artisan make:model Role
class Role extends Model
{
    use HasFactory;

    protected $fillable = ['name'];
}

Ve şimdi de bu rol için seeder oluşturalım;

php artisan make:seeder RoleSeeder
use App\Models\Role;

class RoleSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        Role::create(['name' => 'member']);
        Role::create(['name' => 'admin']);
    }
}

User model duzenlemesi

User model’e eklememiz gereken alan “role_id” dir, User model’da $fillable isimli array’de bu alanın var olduğundan emin olalım.

protected $fillable = [
        'name',        
        'email',  
        'password',
        'role_id', // burada olmalı
    ];

Bu adımda ise yukarıdaki alanı ekleyen bir migration oluşturmamız gerekiyor;

php artisan make:migration AddNewFieldsToUser
class AddNewFieldsToUser extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {            
            $table->foreignId('role_id')->constrained();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('role_id');
        });

    }
}

Bu adımda “app/Actions/Fortify/CreateNewUser.php” isimli dosyayı açalım, içeriğini aşağıdaki gibi düzenleyelim, bu dosya uygulamaya User eklemekten sorumlu;

class CreateNewUser implements CreatesNewUsers
{
    use PasswordValidationRules;

    /**
     * Validate and create a newly registered user.
     *
     * @param  array  $input
     * @return \App\Models\User
     */
    public function create(array $input)
    {
        Validator::make($input, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],

            'role_id' => ['required'],
            'password' => $this->passwordRules(),
            'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['required', 'accepted'] : '',
        ])->validate();

        return User::create([
            'name' => $input['name'],
            'email' => $input['email'],
            'role_id' => $input['role_id'],
            'password' => Hash::make($input['password']),
        ]);
    }
}

Uygulamada default olarak bulunan “database/factories/UserFactory.php” yi de düzenlememiz gerekli;

use App\Models\Role;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

class UserFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = User::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'name' => $this->faker->name,
            'email' => $this->faker->unique()->safeEmail,       
            'email_verified_at' => now(),
            'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
            'remember_token' => Str::random(10),
           
           // yeni alan eklenmiş olmalı
            'role_id' => function () {    
                return Role::all('id')->random();
            },
        ];
    }

    /**
     * Indicate that the model's email address should be unverified.
     *
     * @return \Illuminate\Database\Eloquent\Factories\Factory
     */
    public function unverified()
    {
        return $this->state(function (array $attributes) {
            return [
                'email_verified_at' => null,
            ];
        });
    }
}

Seeder Ekleme

Seeder’i “DatabaseSeeder.php” isimli dosyaya eklemeyi ve iki tane de örnek User oluşturmayı unutmayın.

use App\Models\User;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {

// Rol seeder'i çağırıyoruz
        $this->call(RoleSeeder::class);

// İki tane örnek User oluşturmak için gerekli
        User::factory(2)->create();
        
    }
}

Şimdi ise migrationları baştan çalıştıralım, böylece veritabanımız en baştan oluşturulacak ve yeni alanlar da eklenmiş olacak;

php artisan migrate:fresh

Son olarak da veritabanını seed edelim;

php artisan db:seed

Şimdi ise route list’i görelim;

php artisan route:list

Middleware sütununda “RoleMiddleware” ismini gördüğünüz route lar bu middleware tarafından korunuyor, test etmek için oluşturduğumuz örnek User bilgileriyle login olup deneyebilirsiniz.

Eğer buraya kadar her şeyi eksiksiz yaptıysanız sorunsuz çalışıyor olmalı, tebrikler!

About the author

Yasin Sunguray

Add comment

Categories

Yasin Sunguray

Hi there,

I write about mostly backend development, you can browse posts about C++, Laravel, .NET, C#, SQL, Vue, React and a few other topics.