1402/02/28 375 کلمه 2 دقیقه

نقطه شروع : چه پکیجی خواهیم ساخت ؟

آموزش ساخت پکیج لاراول

از جایی شروع می‌کنیم که عملکرد ادیتور گرافیکی دسترسی‌ها را داخل پروژه خودمان نوشتیم. حال می‌خواهیم آن را قدم به قدم تبدیل به یک پکیج لاراول قابل استفاده بکنیم.

starting-point-package-functionality

starting-point-package-functionality2

در این پروژه از ساختار معمول MVC یعنی routes, controllers, views, and validation استفاده می‌کنیم.

routes/web.php:

Route::resource('roles', \App\Http\Controllers\RoleController::class);
Route::resource('permissions', \App\Http\Controllers\PermissionController::class);

app/Http/Controllers/RoleController.php:

namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
 
class RoleController extends Controller
{
    public function index()
    {
        $roles = Role::withCount('permissions')->get();
 
        return view('roles.index', compact('roles'));
    }
 
    public function create() {
        $permissions = Permission::pluck('name', 'id');
 
        return view('roles.create', compact('permissions'));
    }
 
    public function store(Request $request)
    {
        $request->validate([
            'name' => ['required', 'string', 'unique:roles'],
            'permissions' => ['array'],
        ]);
 
        $role = Role::create(['name' => $request->input('name')]);
 
        $role->givePermissionTo($request->input('permissions'));
 
        return redirect()->route('roles.index');
    }
 
    public function edit(Role $role)
    {
        $permissions = Permission::pluck('name', 'id');
 
        return view('roles.edit', compact('role', 'permissions'));
    }
 
    public function update(Request $request, Role $role)
    {
        $request->validate([
            'name' => ['required', 'string', 'unique:roles,name,' . $role->id],
            'permissions' => ['array'],
        ]);
 
        $role->update(['name' => $request->input('name')]);
 
        $role->syncPermissions($request->input('permissions'));
 
        return redirect()->route('roles.index');
    }
 
    public function destroy(Role $role)
    {
        $role->delete();
 
        return redirect()->route('roles.index');
    }
}

resources/views/roles/index.blade.php:

@extends('layouts.app')
 
@section('content')
    <h1 class="text-xl font-semibold text-gray-900">Roles</h1>
    <a href="{{ route('roles.create') }}">Add Role</a>
 
    <table class="min-w-full divide-y divide-gray-300">
        <thead class="bg-gray-50">
        <tr>
            <th>Name</th>
            <th>Permissions</th>
            <th scope="col"></th>
        </tr>
        </thead>
        <tbody class="divide-y divide-gray-200 bg-white">
        @forelse ($roles as $role)
            <tr>
                <td>{{ $role->name }}</td>
                <td>{{ $role->permissions_count }}</td>
                <td>
                    <a href="{{ route('roles.edit', $role) }}">Edit</a>
 
                    <form action="{{ route('roles.destroy', $role) }}"
                          method="POST"
                          onsubmit="return confirm('Are you sure?')"
                          class="inline-block">
                        @csrf
                        @method('DELETE')
                        <button type="submit">Delete</button>
                    </form>
                </td>
            </tr>
        @empty
            <tr>
                <td colspan="3">No roles found.</td>
            </tr>
        @endforelse
        </tbody>
    </table>
@endsection

در نمونه کد Blade بالا بعضی از <div> ها ساده‌سازی و کلاس‌های استایل css حذف شده اند تا شما روی ساختار پروژه تمرکز کنید نه روی اینکه ظاهر چگونه دیده می‌شود.

در زیر نمونه کدهای فرم ساخت نقش‌ها آورده شده است:

resources/views/roles/create.blade.php:

@extends('layouts.app')
 
@section('content')
    <h1 class="text-xl font-semibold text-gray-900">Create Role</h1>
 
    @if ($errors->any())
        <div class="text-red-500 text-sm mb-4">
            <ul>
                @foreach ($errors->all() as $error)
                    <li>{{ $error }}</li>
                @endforeach
            </ul>
        </div>
    @endif
 
    <form action="{{ route('roles.store') }}" method="POST">
        @csrf
        <div>
            <label for="name">Name</label>
            <input type="text" name="name" id="name" value="{{ old('name') }}" required autofocus>
        </div>
 
        @if ($permissions->count())
        <div class="mt-4">
            <label for="permissions">Permissions</label>
 
            @foreach ($permissions as $id => $name)
                <input type="checkbox" name="permissions[]" id="permission-{{ $id }}"
                       value="{{ $id }}" @checked(in_array($id, old('permissions', [])))>
                <label for="permission-{{ $id }}">{{ $name }}</label>
                <br />
            @endforeach
        </div>
        @endif
 
        <div class="mt-4">
            <button type="submit">Save</button>
        </div>
    </form>
@endsection

در نمونه بالا نیز برای ساده‌سازی بخش های اضافی حذف شده اند که در نتیجه نهایی و در درس‌های بعدی کم کم اضافه خواهند شد.

درنهایت، هدف از این درسنامه تبدیل عملکرد این دو Route Resource به پکیجی قابل استفاده مجدد است تا برنامه‌نویسان با استفاده از دستور composer require our/package پکیج ساخته شده توسط ما را در پروژه خود نصب کرده و به صورت گرافیکی نقش‌ها و دسترسی‌های پروژه خود را مدیریت کنند.

در حقیت پکیج ساخته شده ما یک لایه گرافیکی روی پکیج محبوب spatie/laravel-permission می‌باشد که در درس‌های بعدی نحوه افزودن وابستگی‌های بیرونی به پکیج را یاد خواهیم گرفت.