Laravel 11 Kullanıcı Rolleri ve İzinler Eğitimi

L

Bu eğitimde, Laravel 11 uygulamasında spatie/laravel-permission paketini kullanarak kullanıcı rolleri ve izinlerini nasıl yöneteceğinizi paylaşacağım.

Laravel 11 uygulamasında roller ve izinler için Spatie GitHub paketini kullanıyoruz. Aşağıdaki adımları takip ederek Laravel 11'de ACL (Erişim Kontrol Listesi) oluşturabilirsiniz.

Spatie role permission composer paketi, Laravel 11'de ACL oluşturmanın bir yolunu sağlar. Bu paket, bir kullanıcıya nasıl rol atanacağını, bir kullanıcıya nasıl izin verileceğini ve rollere nasıl izin atanacağını açıklar. Laravel 11 uygulamasında adım adım rol ve izin oluşturmayı anlatacağım.

Roller ve izinler, farklı roller ve izinlerle birden fazla kullanıcı türü oluşturmanıza olanak tanır. Örneğin, bazı kullanıcılar yalnızca ürün modülünün listesini görebilirken, diğerleri ürün modülünü düzenleyebilir ve silebilir.

Bu örnekte, aşağıda listelenen üç modül oluşturuldu:

  • Kullanıcı Yönetimi
  • Rol Yönetimi
  • Ürün Yönetimi

Bir kullanıcı kaydettikten sonra, herhangi bir rolünüz olmayacaktır. Bu yüzden Kullanıcı Yönetimi modülünden detaylarınızı düzenleyerek kendinize admin rolü atayabilirsiniz. Ardından, rol-list, rol-create, rol-edit, rol-delete, ürün-list, ürün-create, ürün-edit, ürün-delete gibi izinlere sahip kendi rolünüzü oluşturabilirsiniz. Yeni bir kullanıcı atayıp bu durumu test edebilirsiniz.

Adım 1: Laravel 11'i Kurun

İlk olarak, sıfırdan başlıyoruz ve Laravel 11'in yeni bir sürümünü elde etmemiz gerekiyor. Bunun için aşağıdaki komutu kullanarak bir Laravel 11 uygulaması kuracağız. Terminal ya da komut istemcinizi açın ve şu komutu çalıştırın:

composer create-project laravel/laravel example-app

Adım 2: spatie/laravel-permission Paketini Kurun

Şimdi, ACL (Erişim Kontrol Listesi) için Spatie paketini kurmamız gerekiyor; bu şekilde paketin sunduğu yöntemleri kullanabiliriz. Ayrıca, form koleksiyon paketini de kuracağız. Terminalinizi açın ve aşağıdaki komutu çalıştırın:

composer require spatie/laravel-permission

Spatie paketi üzerinde özelleştirmeler yapabiliriz. Eğer siz de değişiklikler yapmak istiyorsanız, aşağıdaki komutu çalıştırarak yapılandırma dosyasını config/permission.php konumuna ve migration (göç) dosyalarını projeye ekleyebilirsiniz:

php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"

Şimdi, permission.php dosyasını ve bir migration dosyasını görebilirsiniz. Migration dosyalarını çalıştırmak için şu komutu kullanın:

php artisan migrate

Adım 3: Ürünler İçin Migration Oluşturma

Bu adımda, products (ürünler) tablosu için migration dosyasını oluşturacağız. Aşağıdaki komutu kullanarak bir migration oluşturabilirsiniz:

php artisan make:migration create_products_table

Açılan migration dosyasına aşağıdaki kodu ekleyin:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Migration'ları çalıştır.
     *
     * @return void
     */
    public function up(): void
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->text('detail');
            $table->timestamps();
        });
    }

    /**
     * Migration'ları geri al.
     *
     * @return void
     */
    public function down(): void
    {
        Schema::dropIfExists('products');
    }
};

Migration'ı çalıştırarak ürünler tablosunu oluşturun:

php artisan migrate

Adım 4: Modelleri Oluşturma

Bu adımda, User ve Product tabloları için modelleri oluşturacağız. Laravel'de yeni bir proje başlattığınızda, User modeli zaten gelir. Bu yüzden sadece kodu güncelleyeceğiz. Product modeli için ise yeni bir model oluşturmanız gerekecek.

1. User Modeli

app/Models/User.php dosyasını şu şekilde güncelleyin:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use HasFactory, Notifiable, HasRoles;

    /**
     * Kitle atama için uygun olan özellikler.
     *
     * @var array
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * Serileştirme için gizli tutulacak özellikler.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * Dönüştürülmesi gereken özellikler.
     *
     * @return array
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
        ];
    }
}

2. Product Modeli

Yeni bir model oluşturmak için şu komutu çalıştırabilirsiniz:

php artisan make:model Product

Oluşan app/Models/Product.php dosyasını şu şekilde düzenleyin:

<?php

namespace App\Models;

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

class Product extends Model
{
    use HasFactory;

    /**
     * Kitle atama için uygun olan özellikler.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'detail'
    ];
}

Adım 5: Middleware Ekleme

Spatie paketi, kendi yerleşik middleware'lerini sağlar. Bu middleware'ler şu şekildedir:

  • role
  • permission

Bu middleware'leri kullanabilmek için, app.php dosyasına eklememiz gerekiyor. Aşağıdaki şekilde bootstrap/app.php dosyasını güncelleyebilirsiniz:

<?php

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->alias([
            'role' => \Spatie\Permission\Middleware\RoleMiddleware::class,
            'permission' => \Spatie\Permission\Middleware\PermissionMiddleware::class,
            'role_or_permission' => \Spatie\Permission\Middleware\RoleOrPermissionMiddleware::class,
        ]);
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();

Bu adımda, role, permission ve role_or_permission middleware'lerini projeye ekledik. Artık bu middleware'leri route (yönlendirme) veya controller düzeyinde kullanabilirsiniz.

Adım 6: Kimlik Doğrulama Oluşturma

Laravel 11 uygulamanıza kimlik doğrulama (auth) eklemek için birkaç adımı takip etmelisiniz.

1. Laravel UI Paketini Yükleyin

Öncelikle, kimlik doğrulama işlevselliğini sağlayacak olan laravel/ui paketini yüklemeniz gerekiyor. Terminalinizde şu komutu çalıştırın:

composer require laravel/ui

2. Auth Scaffolding Oluşturma

Kimlik doğrulama arayüzünü ve gerekli bileşenleri oluşturmak için Laravel UI komutunu kullanacağız. Aşağıdaki komutu çalıştırarak kimlik doğrulama scaffolding'ini oluşturun:

php artisan ui bootstrap --auth

Bu komut, giriş (login) ve kayıt (register) sayfalarının yanı sıra, logout, parola sıfırlama gibi diğer kimlik doğrulama özelliklerini sağlar.

3. NPM Kurulumu

Oluşturulan kimlik doğrulama arayüzünün daha düzgün bir şekilde görüntülenebilmesi için npm komutlarını çalıştırmamız gerekiyor. İlk olarak, npm'yi yüklemek için şu komutu çalıştırın:

npm install

4. NPM Build Çalıştırma

Son olarak, npm run build komutunu çalıştırarak kaynak dosyaları derleyin ve daha iyi bir layout görünümü elde edin:

npm run build

Bu işlemler tamamlandığında, Laravel 11 uygulamanızda kimlik doğrulama işlemi başarılı bir şekilde oluşturulmuş olacaktır.

Adım 7: Rotaları (Routes) Oluşturma

Bu adımda, kullanıcılar, ürünler ve roller modülleri için gerekli rotaları ekleyeceğiz. Bu rotalarda, roller ve ürünler için yetkilendirme kontrollerini içeren middleware kullanacağız. Aşağıda, routes/web.php dosyasına eklemeniz gereken rotalar bulunmaktadır:

<?php

use Illuminate\Support\Facades\Route;

use App\Http\Controllers\HomeController;
use App\Http\Controllers\RoleController;
use App\Http\Controllers\UserController;
use App\Http\Controllers\ProductController;

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

Auth::routes();

Route::get('/home', [HomeController::class, 'index'])->name('home');

// Auth middleware ile korunan rotalar
Route::group(['middleware' => ['auth']], function() {
    Route::resource('roles', RoleController::class);
    Route::resource('users', UserController::class);
    Route::resource('products', ProductController::class);
});

Açıklamalar:

  1. Auth Rotaları: Auth::routes(); komutu ile kimlik doğrulama için Laravel'in varsayılan rotalarını ekledik. Bu rotalar giriş, kayıt ve şifre sıfırlama gibi işlevleri içerir.

  2. Ana Sayfa Rotası: /home rotası, kimlik doğrulaması başarılı olduğunda kullanıcıyı ana sayfaya yönlendirir.

  3. Role, User ve Product Rotaları: Bu rotalar, RoleController, UserController ve ProductController'ı kullanarak CRUD işlemlerini gerçekleştirir. auth middleware'i ile korunmuştur, yani bu rotalara sadece giriş yapmış kullanıcılar erişebilir.

Bu rotalarla birlikte kullanıcılar, roller ve ürünler için tam yetkilendirilmiş bir yönetim sistemi oluşturmuş olacaksınız.

Adım 8: Controller'ları Ekleme

Bu adımda, kullanıcılar, ürünler ve roller için üç ayrı controller oluşturacağız. Aşağıda, her bir modül için controller kodları bulunmaktadır:

1. UserController

Bu controller, kullanıcı yönetimi işlemlerini (listeleme, ekleme, düzenleme, silme) gerçekleştirir.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\User;
use Spatie\Permission\Models\Role;
use DB;
use Hash;
use Illuminate\Support\Arr;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;

class UserController extends Controller
{
    public function index(Request $request): View
    {
        $data = User::latest()->paginate(5);
        return view('users.index',compact('data'))
               ->with('i', ($request->input('page', 1) - 1) * 5);
    }

    public function create(): View
    {
        $roles = Role::pluck('name','name')->all();
        return view('users.create',compact('roles'));
    }

    public function store(Request $request): RedirectResponse
    {
        $this->validate($request, [
            'name' => 'required',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|same:confirm-password',
            'roles' => 'required'
        ]);

        $input = $request->all();
        $input['password'] = Hash::make($input['password']);

        $user = User::create($input);
        $user->assignRole($request->input('roles'));

        return redirect()->route('users.index')
                         ->with('success', 'User created successfully');
    }

    public function show($id): View
    {
        $user = User::find($id);
        return view('users.show',compact('user'));
    }

    public function edit($id): View
    {
        $user = User::find($id);
        $roles = Role::pluck('name','name')->all();
        $userRole = $user->roles->pluck('name','name')->all();
        return view('users.edit',compact('user','roles','userRole'));
    }

    public function update(Request $request, $id): RedirectResponse
    {
        $this->validate($request, [
            'name' => 'required',
            'email' => 'required|email|unique:users,email,'.$id,
            'password' => 'same:confirm-password',
            'roles' => 'required'
        ]);

        $input = $request->all();
        if (!empty($input['password'])) { 
            $input['password'] = Hash::make($input['password']);
        } else {
            $input = Arr::except($input,array('password'));    
        }

        $user = User::find($id);
        $user->update($input);
        DB::table('model_has_roles')->where('model_id',$id)->delete();

        $user->assignRole($request->input('roles'));

        return redirect()->route('users.index')
                         ->with('success', 'User updated successfully');
    }

    public function destroy($id): RedirectResponse
    {
        User::find($id)->delete();
        return redirect()->route('users.index')
                         ->with('success', 'User deleted successfully');
    }
}

2. ProductController

Bu controller, ürün yönetimi işlemlerini gerçekleştirir (listeleme, ekleme, düzenleme, silme) ve Spatie Permission ile yetkilendirme kullanır.

<?php

namespace App\Http\Controllers;

use App\Models\Product;
use Illuminate\Http\Request;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;

class ProductController extends Controller
{ 
    function __construct()
    {
         $this->middleware('permission:product-list|product-create|product-edit|product-delete', ['only' => ['index','show']]);
         $this->middleware('permission:product-create', ['only' => ['create','store']]);
         $this->middleware('permission:product-edit', ['only' => ['edit','update']]);
         $this->middleware('permission:product-delete', ['only' => ['destroy']]);
    }

    public function index(): View
    {
        $products = Product::latest()->paginate(5);
        return view('products.index',compact('products'))
               ->with('i', (request()->input('page', 1) - 1) * 5);
    }

    public function create(): View
    {
        return view('products.create');
    }

    public function store(Request $request): RedirectResponse
    {
        request()->validate([
            'name' => 'required',
            'detail' => 'required',
        ]);

        Product::create($request->all());
        return redirect()->route('products.index')
                         ->with('success', 'Product created successfully.');
    }

    public function show(Product $product): View
    {
        return view('products.show',compact('product'));
    }

    public function edit(Product $product): View
    {
        return view('products.edit',compact('product'));
    }

    public function update(Request $request, Product $product): RedirectResponse
    {
        request()->validate([
            'name' => 'required',
            'detail' => 'required',
        ]);

        $product->update($request->all());
        return redirect()->route('products.index')
                         ->with('success', 'Product updated successfully');
    }

    public function destroy(Product $product): RedirectResponse
    {
        $product->delete();
        return redirect()->route('products.index')
                         ->with('success', 'Product deleted successfully');
    }
}

2. RoleController

Aşağıda, RoleController için tamamlayıcı kod örneği bulunmaktadır. Bu controller, kullanıcı rolleri ile ilgili işlemleri (listeleme, ekleme, düzenleme, silme) yönetir ve Spatie/Permission paketini kullanarak yetkilendirme işlemleri gerçekleştirir.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
use DB;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;

class RoleController extends Controller
{
    // Middleware'lar, gerekli izinlere göre yönlendirmeler yapar.
    function __construct()
    {
         $this->middleware('permission:role-list|role-create|role-edit|role-delete', ['only' => ['index','store']]);
         $this->middleware('permission:role-create', ['only' => ['create','store']]);
         $this->middleware('permission:role-edit', ['only' => ['edit','update']]);
         $this->middleware('permission:role-delete', ['only' => ['destroy']]);
    }

    // Roller listesini görüntüleme
    public function index(Request $request): View
    {
        $roles = Role::orderBy('id', 'DESC')->paginate(5);
        return view('roles.index', compact('roles'))
            ->with('i', ($request->input('page', 1) - 1) * 5);
    }

    // Yeni rol oluşturma formunu gösterme
    public function create(): View
    {
        $permission = Permission::get();
        return view('roles.create', compact('permission'));
    }

    // Yeni rolü veritabanına kaydetme
    public function store(Request $request): RedirectResponse
    {
        $this->validate($request, [
            'name' => 'required|unique:roles,name',
            'permission' => 'required',
        ]);

        $permissionsID = array_map(
            function ($value) { return (int)$value; },
            $request->input('permission')
        );

        $role = Role::create(['name' => $request->input('name')]);
        $role->syncPermissions($permissionsID);

        return redirect()->route('roles.index')
                         ->with('success', 'Role created successfully');
    }

    // Belirtilen rolü görüntüleme
    public function show($id): View
    {
        $role = Role::find($id);
        $rolePermissions = Permission::join("role_has_permissions", "role_has_permissions.permission_id", "=", "permissions.id")
            ->where("role_has_permissions.role_id", $id)
            ->get();

        return view('roles.show', compact('role', 'rolePermissions'));
    }

    // Mevcut rolü düzenleme formunu gösterme
    public function edit($id): View
    {
        $role = Role::find($id);
        $permission = Permission::get();
        $rolePermissions = DB::table("role_has_permissions")->where("role_has_permissions.role_id", $id)
            ->pluck('role_has_permissions.permission_id', 'role_has_permissions.permission_id')
            ->all();

        return view('roles.edit', compact('role', 'permission', 'rolePermissions'));
    }

    // Rolü güncelleme
    public function update(Request $request, $id): RedirectResponse
    {
        $this->validate($request, [
            'name' => 'required',
            'permission' => 'required',
        ]);

        $role = Role::find($id);
        $role->name = $request->input('name');
        $role->save();

        $permissionsID = array_map(
            function ($value) { return (int)$value; },
            $request->input('permission')
        );

        $role->syncPermissions($permissionsID);

        return redirect()->route('roles.index')
                         ->with('success', 'Role updated successfully');
    }

    // Belirtilen rolü silme
    public function destroy($id): RedirectResponse
    {
        DB::table("roles")->where('id', $id)->delete();
        return redirect()->route('roles.index')
                         ->with('success', 'Role deleted successfully');
    }
}

Açıklama

  • Middleware Kullanımı: Bu controller, belirli yollar için izinleri kontrol etmek için middleware kullanır. Bu, kullanıcının yalnızca yetkili olduğu eylemleri gerçekleştirmesine izin verir.

  • CRUD İşlemleri: Rol oluşturma, listeleme, güncelleme ve silme işlemleri, uygun doğrulama ve izin kontrolleriyle gerçekleştirilir.

  • Permission Yönetimi: Rol oluşturulurken veya güncellenirken, kullanıcının izinleri de senkronize edilir.

Bu controller'ı kullanarak uygulamanızda rollerle ilgili yönetim işlevselliğini tamamlamış olursunuz.

Adım 9: Blade Dosyalarını Ekle

Bu adımda aşağıdaki dosyaları oluşturacağız:

Tema Düzeni

resources/views/layouts/app.blade.php

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>{{ config('app.name', 'Laravel') }}</title>

    <!-- Fontlar -->
    <link rel="dns-prefetch" href="//fonts.bunny.net">
    <link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet">

    <!-- Scriptler -->
    @vite(['resources/sass/app.scss', 'resources/js/app.js'])
    
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
</head>
<body>
    <div id="app">
        <nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
            <div class="container">
                <a class="navbar-brand" href="{{ url('/') }}">
                    Laravel 11 Kullanıcı Rolleri ve İzinleri Eğitimi
                </a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
                    <span class="navbar-toggler-icon"></span>
                </button>

                <div class="collapse navbar-collapse" id="navbarSupportedContent">
                    <!-- Sol Taraf Menü -->
                    <ul class="navbar-nav me-auto">

                    </ul>

                    <!-- Sağ Taraf Menü -->
                    <ul class="navbar-nav ms-auto">
                        <!-- Kimlik Doğrulama Bağlantıları -->
                        @guest
                            @if (Route::has('login'))
                                <li class="nav-item">
                                    <a class="nav-link" href="{{ route('login') }}">{{ __('Giriş Yap') }}</a>
                                </li>
                            @endif

                            @if (Route::has('register'))
                                <li class="nav-item">
                                    <a class="nav-link" href="{{ route('register') }}">{{ __('Kayıt Ol') }}</a>
                                </li>
                            @endif
                        @else
                            <li><a class="nav-link" href="{{ route('users.index') }}">Kullanıcıları Yönet</a></li>
                            <li><a class="nav-link" href="{{ route('roles.index') }}">Rolleri Yönet</a></li>
                            <li><a class="nav-link" href="{{ route('products.index') }}">Ürünleri Yönet</a></li>
                            <li class="nav-item dropdown">
                                <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
                                    {{ Auth::user()->name }}
                                </a>

                                <div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
                                    <a class="dropdown-item" href="{{ route('logout') }}"
                                       onclick="event.preventDefault();
                                                     document.getElementById('logout-form').submit();">
                                        {{ __('Çıkış Yap') }}
                                    </a>

                                    <form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
                                        @csrf
                                    </form>
                                </div>
                            </li>
                        @endguest
                    </ul>
                </div>
            </div>
        </nav>

        <main class="py-4">
            <div class="container">
                <div class="row justify-content-center">
                    <div class="col-md-12">
                        <div class="card">
                            <div class="card-body">
                                @yield('content')
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </main>
        
    </div>
</body>
</html>

Kullanıcı Modülü

resources/views/users/index.blade.php

@extends('layouts.app')

@section('content')
<div class="row">
    <div class="col-lg-12 margin-tb">
        <div class="pull-left">
            <h2>Kullanıcı Yönetimi</h2>
        </div>
        <div class="pull-right">
            <a class="btn btn-success mb-2" href="{{ route('users.create') }}"><i class="fa fa-plus"></i> Yeni Kullanıcı Oluştur</a>
        </div>
    </div>
</div>

@session('success')
    <div class="alert alert-success" role="alert"> 
        {{ $value }}
    </div>
@endsession

<table class="table table-bordered">
   <tr>
       <th>No</th>
       <th>İsim</th>
       <th>Email</th>
       <th>Roller</th>
       <th width="280px">İşlem</th>
   </tr>
   @foreach ($data as $key => $user)
    <tr>
        <td>{{ ++$i }}</td>
        <td>{{ $user->name }}</td>
        <td>{{ $user->email }}</td>
        <td>
          @if(!empty($user->getRoleNames()))
            @foreach($user->getRoleNames() as $v)
               <label class="badge bg-success">{{ $v }}</label>
            @endforeach
          @endif
        </td>
        <td>
             <a class="btn btn-info btn-sm" href="{{ route('users.show',$user->id) }}"><i class="fa-solid fa-list"></i> Göster</a>
             <a class="btn btn-primary btn-sm" href="{{ route('users.edit',$user->id) }}"><i class="fa-solid fa-pen-to-square"></i> Düzenle</a>
              <form method="POST" action="{{ route('users.destroy', $user->id) }}" style="display:inline">
                  @csrf
                  @method('DELETE')

                  <button type="submit" class="btn btn-danger btn-sm"><i class="fa-solid fa-trash"></i> Sil</button>
              </form>
        </td>
    </tr>
 @endforeach
</table>

{!! $data->links('pagination::bootstrap-5') !!}

@endsection

resources/views/users/show.blade.php

@extends('layouts.app')

@section('content')
<div class="row">
    <div class="col-lg-12 margin-tb">
        <div class="pull-left">
            <h2>Yeni Kullanıcı Oluştur</h2>
        </div>
        <div class="pull-right">
            <a class="btn btn-primary btn-sm mb-2" href="{{ route('users.index') }}"><i class="fa fa-arrow-left"></i> Geri</a>
        </div>
    </div>
</div>

@if (count($errors) > 0)
    <div class="alert alert-danger">
      <strong>Kimlik Hatası!</strong> Girdiğiniz bilgileri kontrol edin.<br><br>
      <ul>
         @foreach ($errors->all() as $error)
           <li>{{ $error }}</li>
         @endforeach
      </ul>
    </div>
@endif

<form method="POST" action="{{ route('users.store') }}">
    @csrf
    <div class="row">
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group">
                <strong>İsim:</strong>
                <input type="text" name="name" placeholder="İsim" class="form-control">
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group">
                <strong>E-posta:</strong>
                <input type="email" name="email" placeholder="E-posta" class="form-control">
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group">
                <strong>Şifre:</strong>
                <input type="password" name="password" placeholder="Şifre" class="form-control">
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group">
                <strong>Şifreyi Onayla:</strong>
                <input type="password" name="confirm-password" placeholder="Şifreyi Onayla" class="form-control">
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group">
                <strong>Rol:</strong>
                <select name="roles[]" class="form-control" multiple="multiple">
                    @foreach ($roles as $value => $label)
                        <option value="{{ $value }}">
                            {{ $label }}
                        </option>
                     @endforeach
                </select>
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12 text-center">
            <button type="submit" class="btn btn-primary btn-sm mt-2 mb-3"><i class="fa-solid fa-floppy-disk"></i> Gönder</button>
        </div>
    </div>
</form>

@endsection

resources/views/users/edit.blade.php

@extends('layouts.app')

@section('content')
<div class="row">
    <div class="col-lg-12 margin-tb">
        <div class="pull-left">
            <h2>Kullanıcıyı Düzenle</h2>
        </div>
        <div class="pull-right">
            <a class="btn btn-primary btn-sm mb-2" href="{{ route('users.index') }}"><i class="fa fa-arrow-left"></i> Geri</a>
        </div>
    </div>
</div>

@if (count($errors) > 0)
    <div class="alert alert-danger">
      <strong>Kimlik Hatası!</strong> Girdiğiniz bilgileri kontrol edin.<br><br>
      <ul>
         @foreach ($errors->all() as $error)
           <li>{{ $error }}</li>
         @endforeach
      </ul>
    </div>
@endif

<form method="POST" action="{{ route('users.update', $user->id) }}">
    @csrf
    @method('PUT')

    <div class="row">
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group">
                <strong>İsim:</strong>
                <input type="text" name="name" placeholder="İsim" class="form-control" value="{{ $user->name }}">
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group">
                <strong>E-posta:</strong>
                <input type="email" name="email" placeholder="E-posta" class="form-control" value="{{ $user->email }}">
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group">
                <strong>Şifre:</strong>
                <input type="password" name="password" placeholder="Şifre" class="form-control">
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group">
                <strong>Şifreyi Onayla:</strong>
                <input type="password" name="confirm-password" placeholder="Şifreyi Onayla" class="form-control">
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group">
                <strong>Rol:</strong>
                <select name="roles[]" class="form-control" multiple="multiple">
                    @foreach ($roles as $value => $label)
                        <option value="{{ $value }}" {{ isset($userRole[$value]) ? 'selected' : ''}}>
                            {{ $label }}
                        </option>
                     @endforeach
                </select>
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12 text-center">
            <button type="submit" class="btn btn-primary btn-sm mt-2 mb-3"><i class="fa-solid fa-floppy-disk"></i> Gönder</button>
        </div>
    </div>
</form>

@endsection

resources/views/users/show.blade.php

@extends('layouts.app')

@section('content')
<div class="row">
    <div class="col-lg-12 margin-tb">
        <div class="pull-left">
            <h2>Kullanıcıyı Göster</h2>
        </div>
        <div class="pull-right">
            <a class="btn btn-primary" href="{{ route('users.index') }}"> Geri</a>
        </div>
    </div>
</div>

<div class="row">
    <div class="col-xs-12 col-sm-12 col-md-12">
        <div class="form-group">
            <strong>İsim:</strong>
            {{ $user->name }}
        </div>
    </div>
    <div class="col-xs-12 col-sm-12 col-md-12">
        <div class="form-group">
            <strong>E-posta:</strong>
            {{ $user->email }}
        </div>
    </div>
    <div class="col-xs-12 col-sm-12 col-md-12">
        <div class="form-group">
            <strong>Roller:</strong>
            @if(!empty($user->getRoleNames()))
                @foreach($user->getRoleNames() as $v)
                    <label class="badge badge-success">{{ $v }}</label>
                @endforeach
            @endif
        </div>
    </div>
</div>
@endsection

resources/views/roles/index.blade.php

@extends('layouts.app')

@section('content')
<div class="row">
    <div class="col-lg-12 margin-tb">
        <div class="pull-left">
            <h2>Rol Yönetimi</h2>
        </div>
        <div class="pull-right">
        @can('role-create')
            <a class="btn btn-success btn-sm mb-2" href="{{ route('roles.create') }}"><i class="fa fa-plus"></i> Yeni Rol Oluştur</a>
            @endcan
        </div>
    </div>
</div>

@session('success')
    <div class="alert alert-success" role="alert"> 
        {{ $value }}
    </div>
@endsession

<table class="table table-bordered">
  <tr>
     <th width="100px">No</th>
     <th>İsim</th>
     <th width="280px">Eylem</th>
  </tr>
    @foreach ($roles as $key => $role)
    <tr>
        <td>{{ ++$i }}</td>
        <td>{{ $role->name }}</td>
        <td>
            <a class="btn btn-info btn-sm" href="{{ route('roles.show',$role->id) }}"><i class="fa-solid fa-list"></i> Göster</a>
            @can('role-edit')
                <a class="btn btn-primary btn-sm" href="{{ route('roles.edit',$role->id) }}"><i class="fa-solid fa-pen-to-square"></i> Düzenle</a>
            @endcan

            @can('role-delete')
            <form method="POST" action="{{ route('roles.destroy', $role->id) }}" style="display:inline">
                @csrf
                @method('DELETE')

                <button type="submit" class="btn btn-danger btn-sm"><i class="fa-solid fa-trash"></i> Sil</button>
            </form>
            @endcan
        </td>
    </tr>
    @endforeach
</table>

{!! $roles->links('pagination::bootstrap-5') !!}

@endsection

resources/views/roles/create.blade.php

@extends('layouts.app')

@section('content')
<div class="row">
    <div class="col-lg-12 margin-tb">
        <div class="pull-left">
            <h2>Yeni Rol Oluştur</h2>
        </div>
        <div class="pull-right">
            <a class="btn btn-primary btn-sm mb-2" href="{{ route('roles.index') }}"><i class="fa fa-arrow-left"></i> Geri</a>
        </div>
    </div>
</div>

@if (count($errors) > 0)
    <div class="alert alert-danger">
        <strong>Kimlik Hatası!</strong> Girdiğiniz bilgileri kontrol edin.<br><br>
        <ul>
        @foreach ($errors->all() as $error)
            <li>{{ $error }}</li>
        @endforeach
        </ul>
    </div>
@endif

<form method="POST" action="{{ route('roles.store') }}">
    @csrf
    <div class="row">
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group">
                <strong>İsim:</strong>
                <input type="text" name="name" placeholder="İsim" class="form-control">
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group">
                <strong>İzinler:</strong>
                <br/>
                @foreach($permission as $value)
                    <label><input type="checkbox" name="permission[{{$value->id}}]" value="{{$value->id}}" class="name">
                    {{ $value->name }}</label>
                <br/>
                @endforeach
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12 text-center">
            <button type="submit" class="btn btn-primary btn-sm mb-3"><i class="fa-solid fa-floppy-disk"></i> Gönder</button>
        </div>
    </div>
</form>

@endsection

resources/views/roles/edit.blade.php

@extends('layouts.app')

@section('content')
<div class="row">
    <div class="col-lg-12 margin-tb">
        <div class="pull-left">
            <h2>Rolü Düzenle</h2>
        </div>
        <div class="pull-right">
            <a class="btn btn-primary btn-sm mb-2" href="{{ route('roles.index') }}"><i class="fa fa-arrow-left"></i> Geri</a>
        </div>
    </div>
</div>

@if (count($errors) > 0)
    <div class="alert alert-danger">
        <strong>Kimlik Hatası!</strong> Girdiğiniz bilgileri kontrol edin.<br><br>
        <ul>
        @foreach ($errors->all() as $error)
            <li>{{ $error }}</li>
        @endforeach
        </ul>
    </div>
@endif

<form method="POST" action="{{ route('roles.update', $role->id) }}">
    @csrf
    @method('PUT')

    <div class="row">
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group">
                <strong>İsim:</strong>
                <input type="text" name="name" placeholder="İsim" class="form-control" value="{{ $role->name }}">
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group">
                <strong>İzinler:</strong>
                <br/>
                @foreach($permission as $value)
                    <label><input type="checkbox" name="permission[{{$value->id}}]" value="{{$value->id}}" class="name" {{ in_array($value->id, $rolePermissions) ? 'checked' : ''}}>
                    {{ $value->name }}</label>
                <br/>
                @endforeach
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12 text-center">
            <button type="submit" class="btn btn-primary btn-sm mb-3"><i class="fa-solid fa-floppy-disk"></i> Gönder</button>
        </div>
    </div>
</form>

@endsection

resources/views/roles/show.blade.php

@extends('layouts.app')

@section('content')
<div class="row">
    <div class="col-lg-12 margin-tb">
        <div class="pull-left">
            <h2>Rolü Göster</h2>
        </div>
        <div class="pull-right">
            <a class="btn btn-primary" href="{{ route('roles.index') }}"> Geri</a>
        </div>
    </div>
</div>

<div class="row">
    <div class="col-xs-12 col-sm-12 col-md-12">
        <div class="form-group">
            <strong>İsim:</strong>
            {{ $role->name }}
        </div>
    </div>
    <div class="col-xs-12 col-sm-12 col-md-12">
        <div class="form-group">
            <strong>İzinler:</strong>
            @if(!empty($rolePermissions))
                @foreach($rolePermissions as $v)
                    <label class="label label-success">{{ $v->name }},</label>
                @endforeach
            @endif
        </div>
    </div>
</div>
@endsection

resources/views/products/index.blade.php

@extends('layouts.app')

@section('content')
<div class="row">
    <div class="col-lg-12 margin-tb">
        <div class="pull-left">
            <h2>Ürünler</h2>
        </div>
        <div class="pull-right">
            @can('product-create')
            <a class="btn btn-success btn-sm mb-2" href="{{ route('products.create') }}"><i class="fa fa-plus"></i> Yeni Ürün Oluştur</a>
            @endcan
        </div>
    </div>
</div>

@session('success')
    <div class="alert alert-success" role="alert"> 
        {{ $value }}
    </div>
@endsession

<table class="table table-bordered">
    <tr>
        <th>No</th>
        <th>İsim</th>
        <th>Ayrıntılar</th>
        <th width="280px">Eylem</th>
    </tr>
    @foreach ($products as $product)
    <tr>
        <td>{{ ++$i }}</td>
        <td>{{ $product->name }}</td>
        <td>{{ $product->detail }}</td>
        <td>
            <form action="{{ route('products.destroy',$product->id) }}" method="POST">
                <a class="btn btn-info btn-sm" href="{{ route('products.show',$product->id) }}"><i class="fa-solid fa-list"></i> Göster</a>
                @can('product-edit')
                <a class="btn btn-primary btn-sm" href="{{ route('products.edit',$product->id) }}"><i class="fa-solid fa-pen-to-square"></i> Düzenle</a>
                @endcan

                @csrf
                @method('DELETE')

                @can('product-delete')
                <button type="submit" class="btn btn-danger btn-sm"><i class="fa-solid fa-trash"></i> Sil</button>
                @endcan
            </form>
        </td>
    </tr>
    @endforeach
</table>

{!! $products->links() !!}

@endsection

resources/views/products/create.blade.php

@extends('layouts.app')

@section('content')
<div class="row">
    <div class="col-lg-12 margin-tb">
        <div class="pull-left">
            <h2>Yeni Ürün Ekle</h2>
        </div>
        <div class="pull-right">
            <a class="btn btn-primary btn-sm" href="{{ route('products.index') }}"><i class="fa fa-arrow-left"></i> Geri</a>
        </div>
    </div>
</div>

@if ($errors->any())
    <div class="alert alert-danger">
        <strong>Kimlik Hatası!</strong> Girdiğiniz bilgileri kontrol edin.<br><br>
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

<form action="{{ route('products.store') }}" method="POST">
    @csrf

    <div class="row">
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group">
                <strong>İsim:</strong>
                <input type="text" name="name" class="form-control" placeholder="İsim">
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group">
                <strong>Ayrıntılar:</strong>
                <textarea class="form-control" style="height:150px" name="detail" placeholder="Ayrıntılar"></textarea>
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12 text-center">
            <button type="submit" class="btn btn-primary btn-sm mb-3 mt-2"><i class="fa-solid fa-floppy-disk"></i> Gönder</button>
        </div>
    </div>
</form>

@endsection

resources/views/products/edit.blade.php

@extends('layouts.app')

@section('content')
<div class="row">
    <div class="col-lg-12 margin-tb">
        <div class="pull-left">
            <h2>Ürünü Düzenle</h2>
        </div>
        <div class="pull-right">
            <a class="btn btn-primary btn-sm mb-2" href="{{ route('products.index') }}"><i class="fa fa-arrow-left"></i> Geri</a>
        </div>
    </div>
</div>

@if ($errors->any())
    <div class="alert alert-danger">
        <strong>Kimlik Hatası!</strong> Girdiğiniz bilgileri kontrol edin.<br><br>
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

<form action="{{ route('products.update',$product->id) }}" method="POST">
    @csrf
    @method('PUT')

    <div class="row">
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group">
                <strong>İsim:</strong>
                <input type="text" name="name" value="{{ $product->name }}" class="form-control" placeholder="İsim">
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group">
                <strong>Ayrıntılar:</strong>
                <textarea class="form-control" style="height:150px" name="detail" placeholder="Ayrıntılar">{{ $product->detail }}</textarea>
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12 text-center">
            <button type="submit" class="btn btn-primary btn-sm mb-2 mt-2"><i class="fa-solid fa-floppy-disk"></i> Gönder</button>
        </div>
    </div>
</form>

@endsection

resources/views/products/show.blade.php

@extends('layouts.app')

@section('content')
<div class="row">
    <div class="col-lg-12 margin-tb">
        <div class="pull-left">
            <h2>Ürünü Göster</h2>
        </div>
        <div class="pull-right">
            <a class="btn btn-primary" href="{{ route('products.index') }}"> Geri</a>
        </div>
    </div>
</div>

<div class="row">
    <div class="col-xs-12 col-sm-12 col-md-12">
        <div class="form-group">
            <strong>İsim:</strong>
            {{ $product->name }}
        </div>
    </div>
    <div class="col-xs-12 col-sm-12 col-md-12">
        <div class="form-group">
            <strong>Ayrıntılar:</strong>
            {{ $product->detail }}
        </div>
    </div>
</div>

@endsection

Adım 10: İzinler ve Admin Kullanıcısı için Seeder Oluşturma

Bu adımda, izinler için bir seeder oluşturacağız. Şu anda sabit izinlerimiz var, bu nedenle aşağıda listelenen izinleri bir seeder kullanarak oluşturacağız. Ancak, isterseniz daha fazla izin de ekleyebilirsiniz.

  1. role-list

  2. role-create

  3. role-edit

  4. role-delete

  5. product-list

  6. product-create

  7. product-edit

  8. product-delete

Öncelikle aşağıdaki komutla bir seeder oluşturun:

php artisan make:seeder PermissionTableSeeder

Aşağıdaki kodu PermissionTableSeeder seeder'ına yerleştirin:

database/seeders/PermissionTableSeeder.php

<?php
  
namespace Database\Seeders;
  
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Permission;
  
class PermissionTableSeeder extends Seeder
{
    /**
     * Veritabanı seed işlemlerini çalıştır.
     */
    public function run(): void
    {
        $permissions = [
           'role-list',
           'role-create',
           'role-edit',
           'role-delete',
           'product-list',
           'product-create',
           'product-edit',
           'product-delete'
        ];
        
        foreach ($permissions as $permission) {
             Permission::create(['name' => $permission]);
        }
    }
}

Bundan sonra, PermissionTableSeeder seeder'ını çalıştırmak için aşağıdaki komutu çalıştırın:

php artisan db:seed --class=PermissionTableSeeder

Şimdi bir admin kullanıcısı oluşturmak için yeni bir seeder oluşturun.

php artisan make:seeder CreateAdminUserSeeder

database/seeders/CreateAdminUserSeeder.php

<?php
  
namespace Database\Seeders;
  
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\User;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
  
class CreateAdminUserSeeder extends Seeder
{
    /**
     * Veritabanı seed işlemlerini çalıştır.
     */
    public function run(): void
    {
        $user = User::create([
            'name' => 'Aydın Yağız', 
            'email' => 'admin@gmail.com',
            'password' => bcrypt('123456')
        ]);
        
        $role = Role::create(['name' => 'Admin']);
         
        $permissions = Permission::pluck('id','id')->all();
       
        $role->syncPermissions($permissions);
         
        $user->assignRole([$role->id]);
    }
}

Ardından, seeder'ı aşağıdaki komut ile çalıştırın:

php artisan db:seed --class=CreateAdminUserSeeder

Laravel Uygulamasını Çalıştırma:

Tüm gerekli adımlar tamamlandı, şimdi aşağıdaki komutu yazarak Laravel uygulamasını çalıştırın:

php artisan serve

Web tarayıcınıza gidin, verilen URL'yi yazın ve uygulamanın çıktısını görüntüleyin:

http://localhost:8000

Şimdi aşağıdaki kimlik bilgileri ile giriş yapabilirsiniz:

  • Email: admin@gmail.com
  • Password: 123456

Artık uygulamayı çalıştırıp kontrol edebilirsiniz.

By Aydın Yağız

Aydın Yağız

Teknolojiye olan tutkumla inovasyonu destekler, kullanıcı deneyimini önceliklerim arasına alırım. Kendi yeteneklerimi ve bilgilerimi paylaşarak, daha geniş bir topluluğun faydalanmasını sağlarım. İş birliği içinde hareket ederek, geleceğin teknoloji dünyasına katkıda bulunmayı hedeflerim. Sizi de bu heyecan verici yolculuğa davet ediyor, fikirlerinizi paylaşmaya ve teknolojiye dair sınırları zorlamaya teşvik ediyorum. Birlikte büyüyelim ve yeni ufuklara açılalım!

İletişime Geçin

Kodlama dünyasına adım atın ve deneyimlerinizi paylaşın. Siz de bu aktif topluluğa katılarak yeni bağlantılar kurun, fikir alışverişinde bulunun ve bilgi birikiminizi artırın.

Özelleştir

Farklı yazı tipleri ve renk seçenekleriyle stilinizi kişiselleştirin. Aşağıdaki örneklerden birini deneyerek sizin için en uygun olanı seçin.

Yazı Tipi Örnekleri

Renk Örnekleri