آموزش لاراول 7: آموزش controllers در لاراول

مقدمه

در این مقاله آموزش مفاهیم پایه ای لاراول، میخواهیم با یکی دیگر از مفاهیم laravel یعنی controller ها بیشتر آشنا شویم.
به جای اینکه تمام logic مدیریت درخواست را به عنوان Closure در فایل های route تعریف کنید ، می توانید این رفتار را با استفاده از کلاس های Controller سازماندهی کنید. Controller ها می توانند logic مربوط به request را در یک کلاس واحد گروه بندی کنند. Controller ها در دایرکتوری app/Http/Controllers ذخیره می شوند.

 Controller های اصلی

تعریف Controller ها

در زیر نمونه ای از basic controller class آورده شده است. توجه داشته باشید که کنترلر،base controller class موجود در لاراول را گسترش می دهد. base class چند متد راحت مانند متد middleware را ارائه می دهد که ممکن است برای پیوستن middleware به controller action استفاده شود:

‌<‌?php
    
    namespace App\Http\Controllers;
    
    use App\Http\Controllers\Controller;
    use App\User;
    
    class UserController extends Controller
    {
        /**
         * Show the profile for the given user.
         *
         * @param  int  $id
         * @return View
         */
        public function show($id)
        {
            return view('user.profile', ['user' =‌>‌ User::findOrFail($id)]);
        }
    }

می توانید روتی را برای این controller action تعریف کنید:

Route::get('user/{id}', '[email protected]');

اکنون ، هنگامی که درخواستی با route URI مشخص مطابقت دارد ، متد show در کلاس UserController اجرا می شود. پارامترهای روت نیز به متد ارسال می شوند.

برای گسترش base class بهController ها نیازی نیست.اگرچه ، شما به فیچرهایی مانند middleware ، validate و متد های dispatch دسترسی نخواهید داشت.

Controller ها و Namespace ها

توجه به این نکته بسیار مهم است که هنگام controller route نیازی به تعیین full controller namespace نیستیم. از آنجا که RouteServiceProvider فایل های روت شما را در یک route group که شامل namespace است لود می کند ، ما فقط بخشی از نام کلاس را که بعد از قسمت App\Http\Controllers از namespace می آید مشخص می کنیم.

اگر می خواهید کنترلرهای خود را بیشتر در دایرکتوری App\Http\Controllers قرار دهید، از class name خاص نسبت به App\Http\Controllers root namespace استفاده کنید. بنابراین ، اگر controller class شما App\Http\Controllers\Photos\AdminController است ، باید روت هایی را به سمت کنترلر رجیسترکنید:

Route::get('foo', 'Photos\[email protected]');

Single Action Controller ها

اگر می خواهید کنترلری تعریف کنید که فقط یک اکشن را کنترل کند ، می توانید یک متد __invoke روی کنترلر قرار دهید:

‌<‌?php
    
    namespace App\Http\Controllers;
    
    use App\Http\Controllers\Controller;
    use App\User;
    
    class ShowProfile extends Controller
    {
        /**
         * Show the profile for the given user.
         *
         * @param  int  $id
         * @return View
         */
        public function __invoke($id)
        {
            return view('user.profile', ['user' =‌>‌ User::findOrFail($id)]);
        }
    }

هنگام رجیستر روت ها برای action controller ها ، نیازی به تعیین متد ندارید:

Route::get('user/{id}', 'ShowProfile');

شما می توانید با استفاده از آپشن --invokable از دستور make:controller یک invokable controlle تولید کنید:

php artisan make:controller ShowProfile --invokable

Controller Middleware

Middleware می تواند به controller's route ها در فایل های route شما اختصاص یابد:

Route::get('profile', '[email protected]')-‌>‌middleware('auth');

بهتر است که middleware را در سازنده کنترلر خود مشخص کنید. با استفاده از متد middleware از سازنده کنترلر ، می توانید به راحتی middleware را به controller's action اختصاص دهید. حتی می توانید middleware را فقط به متدهای خاص در کلاس کنترلر محدود کنید:

class UserController extends Controller
    {
        /**
         * Instantiate a new controller instance.
         *
         * @return void
         */
        public function __construct()
        {
            $this-‌>‌middleware('auth');
    
            $this-‌>‌middleware('log')-‌>‌only('index');
    
            $this-‌>‌middleware('subscribed')-‌>‌except('store');
        }
    }

همچنین کنترلر به شما امکان می دهند با استفاده از Closure میان افزار یا middlware را رجیستر کنید. این یک روش مناسب برای تعریف middlaware برای یک کنترلر بدون تعریف تمام middleware class فراهم می کند:

$this-‌>‌middleware(function ($request, $next) {
        // ...
    
        return $next($request);
    });

شما می توانید middleware را به زیر مجموعه ای از controller action ها اختصاص دهید. با این حال ، ممکن است مشخص شود که کنترلر شما بیش از حد بزرگ شده است. در نظر بگیرید که می توانید کنترلر خود را به چندین کنترلر کوچکتر تبدیل کنید.

 Resource Controller ها

روتینگ resource لاراول روتهای "CRUD" را به یک کنترلر با یک خط کد اختصاص می دهد. به عنوان مثال ، ممکن است بخواهید کنترلری ایجاد کنید که کلیه درخواستهای HTTP را برای "عکسهای" ذخیره شده توسط برنامه مدیریت کند. با استفاده از دستور make:controller Artisan ، می توانیم به سرعت چنین کنترلری ایجاد کنیم:

php artisan make:controller PhotoController --resource

این دستور یک کنترلر در app/Http/Controllers/PhotoController.php ایجاد می کند. کنترلر شامل متدی برای هر یک از عملیات available resource است.

در مرحله بعدی ، می توانید یک resourceful route به کنترلر رجیسترکنید:

Route::resource('photos', 'PhotoController');

این اعلان single route، روتهای مختلفی را برای مدیریت انواع اکشن رویresource ایجاد می کند. controller تولید شده همواره متدهایی هایی برای هر یک از این اکشن ها دارد ، از جمله یادداشت هایی که شما را از HTTP و URI هایی که آنها مدیریت می کنند ، مطلع می کند.

با ارسال یک آرایه با متد resources ، می توانید بسیاری از resource controller ها را به طور همزمان رجیسترکنید:

Route::resources([
        'photos' =‌>‌ 'PhotoController',
        'posts' =‌>‌ 'PostController'
    ]);
Actions Handled  با Resource Controller
تعیین Resource Model

اگر از route model binding استفاده می کنید، هنگام تولید کنترلر می توانید از آپشن --model استفاده کنید:

php artisan make:controller PhotoController --resource --model=Photo

Spoofing از Methods

از آنجا که فرمهای HTML نمی توانند درخواستهای PUT, PATCH, یا DELETE را ایجاد کنند ، برای جعل این افعال HTTP باید یک فیلد hidden _method اضافه کنید. دستور method Blade@ می تواند این فیلد را برای شما ایجاد کند:

‌<‌form action="/foo/bar" method="POST"‌>‌
        @method('PUT')
    ‌<‌/form‌>‌

Resource Route های جزئی

هنگام اعلان resource route ، می توانید زیر مجموعه action هایی را که controller باید انجام دهد به جای مجموعه کامل default action ها، مشخص کنید:

Route::resource('photos', 'PhotoController')-‌>‌only([
        'index', 'show'
    ]);
    
    Route::resource('photos', 'PhotoController')-‌>‌except([
        'create', 'store', 'update', 'destroy'
    ]);

API Resource Route ها

هنگام اعلان resource route هایی که توسط APIs مصرف می شوند ، معمولاً می خواهید روت هایی را که دارای HTML template هایی مانند اcreate و edit هستند را حذف کنید. برای سهولت ، می توانید از متد apiResource استفاده کنید تا به طور خودکار این دو route را حذف کنید:

Route::apiResource('photos', 'PhotoController');

با ارسال یک آرایه به متد apiResources ، می توانید بسیاری از API resource controller ها را همزمان رجیستر کنید:

Route::apiResources([
        'photos' =‌>‌ 'PhotoController',
        'posts' =‌>‌ 'PostController'
    ]);

برای تولید سریع یک API resource controller که شامل متدهای create یا edit نباشد، هنگام اجرای دستور make:controller از سوئیچ api-- استفاده کنید:

php artisan make:controller API/PhotoController --api

 Resource های تودرتو

بعضی اوقات ممکن است لازم باشد route هایی را برای یک resource تو در تو تعریف کنید. به عنوان مثال ، یک photo resource می تواند چندین کامنت داشته باشد که به عکس پیوست شده باشد. برای nest کردن منابع  controller ، از علامت "dot" در اعلان route خود استفاده کنید:

Route::resource('photos.comments', 'PhotoCommentController');

این route یک nested resource را رجیستر می کند که می تواند مانند موارد زیر با URIs قابل دسترسی باشد:

/photos/{photo}/comments/{comment}

تو در تو های کم عمق

اغلب داشتن parent و child IDs در یک URI ضروری نیست ، زیرا child ID یک ID یونیک است. هنگام استفاده از unique id مانند کلیدهای اصلی auto-incrementing برای شناسایی مدل های خود در بخش های URI ، می توانید از "shallow nesting" استفاده کنید:

Route::resource('photos.comments', 'CommentController')-‌>‌shallow();

تعریف روت بالا روتهای زیر را مشخص می کند:

 نامگذاری Resource Route ها

به طور پیش فرض ، تمام resource controller action ها یک route name دارند. با این حال ، می توانید با ارسال یک آرایه names با آپشن های خود ، این نام ها را override کنید:

Route::resource('photos', 'PhotoController')-‌>‌names([
        'create' =‌>‌ 'photos.build'
    ]);

نامگذاری پارامترهای Resource Route

به طور پیش فرض ، Route::resource پارامترهای روت را برای روتهای resource شما بر اساس ورژن "singularized" نام resource ایجاد می کند. با استفاده از متد parameters به راحتی می توانید این را بر اساس هر منبع override بگیرید. آرایه ارسال شده به متد parameters باید یک آرایه از resource names و parameter names باشد:

Route::resource('users', 'AdminUserController')-‌>‌parameters([
        'users' =‌>‌ 'admin_user'
    ]);

مثال بالا URI های زیر را برای resource's show route ایجاد می کند:

/users/{admin_user}

محلی سازی Resource URI ها

به طور پیش فرض، Route::resource با استفاده از verb های انگلیسی resource URI ایجاد می کند. اگر می خواهید create و edit را لوکال کنید، می توانید از متد Route::resourceVerbs استفاده کنید که می تواند در متد boot از AppServiceProvider انجام شود:

use Illuminate\Support\Facades\Route;
    
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Route::resourceVerbs([
            'create' =‌>‌ 'crear',
            'edit' =‌>‌ 'editar',
        ]);
    }

پس از سفارشی سازی verb ها،resource route registration هایی مانند Route::resource('fotos', 'PhotoController') URI های زیر را تولید می کند:

/fotos/crear
    
    /fotos/{foto}/editar

ادامه دارد...

× در حال پاسخ به: