Версія фреймворка: 8.x

Контролери

Вступ

Замість того, щоб визначати всю логіку обробки запитів як Закриття у файлах маршрутів, можливо, ви захочете організувати цю поведінку за допомогою класів контролера. Контролери можуть групувати пов'язану логіку обробки запитів в один клас. Контролери зберігаються вapp/Http/Controllersкаталог.

Основні контролери

Визначення контролерів

Нижче наведено приклад базового класу контролера. Зауважте, що контролер розширює базовий клас контролера, що входить до складу Laravel. Базовий клас забезпечує кілька зручних методів, таких якmiddlewareметод, який може бути використаний для приєднання проміжного програмного забезпечення до дій контролера:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\User;

class UserController extends Controller
{
    /**
     * Show the profile for the given user.
     *
     * @param  int  $id
     * @return \Illuminate\View\View
     */
    public function show($id)
    {
        return view('user.profile', ['user' => User::findOrFail($id)]);
    }
}

Ви можете визначити маршрут до цієї дії контролера так:

use App\Http\Controllers\UserController;

Route::get('user/{id}', [UserController::class, 'show']);

Тепер, коли запит відповідає вказаному URI маршруту, файлshowметод наUserControllerклас буде виконаний. Параметри маршруту також будуть передані методу.

Контролери - нівимагаєтьсярозширити базовий клас. Однак ви не матимете доступу до таких зручних функцій, якmiddleware,validate, іdispatchметоди.

Контролери однієї дії

Якщо ви хочете визначити контролер, який обробляє лише одну дію, ви можете розмістити одну__invokeметод на контролері:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\User;

class ShowProfile extends Controller
{
    /**
     * Show the profile for the given user.
     *
     * @param  int  $id
     * @return \Illuminate\View\View
     */
    public function __invoke($id)
    {
        return view('user.profile', ['user' => User::findOrFail($id)]);
    }
}

При реєстрації маршрутів для контролерів однієї дії не потрібно вказувати метод:

use App\Http\Controllers\ShowProfile;

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

Ви можете створити контролер, що викликається, за допомогою--invokableваріантmake:controllerКоманда ремісників:

php artisan make:controller ShowProfile --invokable
Заглушки контролера можна налаштувати за допомогоюзаглушка видавництва

Middleware контролера

Middlewareможуть бути призначені маршрутам контролера у ваших файлах маршрутів:

Route::get('profile', [UserController::class, 'show'])->middleware('auth');

Однак зручніше вказувати Middleware в конструкторі вашого контролера. Використанняmiddlewareметоду з конструктора вашого контролера, ви можете легко призначити Middleware дії контролера. Ви навіть можете обмежити 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');
    }
}

Контролери також дозволяють реєструвати Middleware за допомогою Закриття. Це забезпечує зручний спосіб визначити Middleware для одного контролера без визначення цілого класу проміжного програмного забезпечення:

$this->middleware(function ($request, $next) {
    // ...

    return $next($request);
});
Ви можете призначити Middleware підмножині дій контролера; однак це може означати, що ваш контролер стає занадто великим. Натомість розгляньте можливість розбиття контролера на кілька менших контролерів.

Resource Контролери

Routing ресурсів Laravel призначає типові маршрути "CRUD" контролеру з одним рядком коду. Наприклад, ви можете створити контролер, який обробляє всі HTTP-запити на "фотографії", що зберігаються у вашому додатку. Використанняmake:controllerРеміснича команда, ми можемо швидко створити такий контролер:

php artisan make:controller PhotoController --resource

Ця команда генерує контролер за адресоюapp/Http/Controllers/PhotoController.php. Контролер буде містити метод для кожної з доступних операцій з ресурсами.

Далі ви можете зареєструвати винахідливий маршрут до контролера:

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

Це одне оголошення маршруту створює кілька маршрутів для обробки різноманітних дій на ресурсі. Сформований контролер вже матиме методи, стербінг для кожної з цих дій, включаючи примітки, що повідомляють вас про дієслова HTTP та URI, якими вони обробляють.

Ви можете зареєструвати багато контролерів ресурсів одночасно, передавши масив доresourcesметод:

Route::resources([
    'photos' => PhotoController::class,
    'posts' => PostController::class,
]);

Дії, які обробляє контролер ресурсів

Дієслово Ненависть Дія Назва маршруту
ОТРИМАТИ /photos індекс photos.index
ОТРИМАТИ /photos/create створити photos.create
ПОСТ /photos магазин photos.store
ОТРИМАТИ /photos/{photo} шоу photos.show
ОТРИМАТИ /photos/{photo}/edit редагувати photos.edit
ВСТАНОВИТИ / ВІДМИТИТИ /photos/{photo} оновлення photos.update
ВИДАЛИТИ /photos/{photo} знищити photos.destroy

Вказівка ​​моделі ресурсу

Якщо ви використовуєте прив'язку моделі маршруту і хочете, щоб методи контролера ресурсів натякали на примірник моделі, ви можете використовувати--modelопція при генерації контролера:

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

Часткові маршрути ресурсів

При оголошенні маршруту ресурсу ви можете вказати підмножину дій, які повинен виконувати контролер замість повного набору дій за замовчуванням:

Route::resource('photos', PhotoController::class)->only([
    'index', 'show'
]);

Route::resource('photos', PhotoController::class)->except([
    'create', 'store', 'update', 'destroy'
]);

Маршрути ресурсів API

Оголошуючи маршрути ресурсів, які будуть споживатися API, ви зазвичай хочете виключити маршрути, що містять HTML-шаблони, такі якcreateіedit. Для зручності ви можете використовуватиapiResourceметод автоматичного виключення цих двох маршрутів:

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

Ви можете зареєструвати багато контролерів ресурсів API одночасно, передавши масив доapiResources method:

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

Швидко сформувати контролер ресурсів API, який не включаєcreateабоeditметоди, використовуйте--apiперемикач при виконанніmake:controllerкоманда:

php artisan make:controller API/PhotoController --api

Вкладені ресурси

Іноді вам може знадобитися визначити маршрути до вкладеного ресурсу. Наприклад, фоторесурс може мати кілька коментарів, які можуть бути прикріплені до фотографії. Щоб вкласти Resource Контролери , використовуйте Tagging «крапка» у декларації маршруту:

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

Цей маршрут реєструє вкладений ресурс, до якого можна отримати доступ за допомогою URI, як показано нижче:

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

Обсяг вкладених ресурсів

Laravelimplicit model bindingфункція може автоматично застосовувати вкладені прив'язки таким чином, що дозволена дочірня модель підтверджується, що належить батьківській моделі. За допомогоюscopedметоду при визначенні вкладеного ресурсу, ви можете ввімкнути автоматичне масштабування, а також проінструктувати Laravel, яке поле має отримати дочірній ресурс:

Route::resource('photos.comments', PhotoCommentController::class)->scoped([
    'comment' => 'slug',
]);

Цей маршрут буде реєструвати вкладений ресурс, до якого можна отримати доступ за допомогою URI, як показано нижче:

/photos/{photo}/comments/{comment:slug}

Неглибоке гніздування

Часто в URI не обов’язково мати і батьківський, і дочірній ідентифікатори, оскільки дочірній ідентифікатор вже є унікальним ідентифікатором. Використовуючи унікальні ідентифікатори, такі як автоматичне збільшення первинних ключів для ідентифікації ваших моделей у сегментах URI, ви можете вибрати використання "неглибокого вкладання":

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

Визначення маршруту вище визначатиме такі маршрути:

Дієслово Ненависть Дія Назва маршруту
ОТРИМАТИ /photos/{photo}/comments індекс photos.comments.index
ОТРИМАТИ /photos/{photo}/comments/create створити photos.comments.create
ПОСТ /photos/{photo}/comments магазин photos.comments.store
ОТРИМАТИ /comments/{comment} шоу comments.show
ОТРИМАТИ /comments/{comment}/edit редагувати коментарі. ред
ВСТАНОВИТИ / ВІДМИТИТИ /comments/{comment} оновлення коментарі. оновити
ВИДАЛИТИ /comments/{comment} знищити коментарі.руйнувати

Іменування маршрутів ресурсів

За замовчуванням усі дії контролера ресурсів мають назву маршруту; однак ви можете замінити ці імена, передавши anamesмасив з вашими опціями:

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

Присвоєння параметрів маршруту ресурсу

За замовчуванням,Route::resourceстворить параметри маршрутів для ваших маршрутів ресурсів на основі "одиничної" версії імені ресурсу. Ви можете легко замінити це для кожного ресурсу, використовуючиparametersметод. Масив перейшов уparametersметод повинен бути асоціативним масивом імен ресурсів та імен параметрів:

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

Наведений вище приклад генерує такі URI для ресурсівshowмаршрут:

/users/{admin_user}

Обсяг маршрутів використання ресурсів

Іноді, при неявному прив’язуванні декількох Eloquent моделей у визначеннях маршрутів ресурсів, можливо, ви захочете застосувати другу модель красномовства таким чином, що вона повинна бути дочірньою до першої Eloquentї моделі. Наприклад, розглянемо цю ситуацію, яка отримує допис у блозі від slug для певного користувача:

use App\Http\Controllers\PostsController;

Route::resource('users.posts', PostsController::class)->scoped();

Ви можете замінити типові ключі моделі за замовчуванням, передавши масив доscopedметод:

use App\Http\Controllers\PostsController;

Route::resource('users.posts', PostsController::class)->scoped([
    'post' => 'slug',
]);

При використанні користувацького неявного прив’язування як вкладеного параметра маршруту, Laravel автоматично застосує запит для отримання вкладеної моделі своїм батьком, використовуючи конвенції, щоб вгадати ім’я зв’язку на батьківському. У цьому випадку передбачається, щоUserмодель має зв'язки з іменемposts(множина імені параметра параметра маршруту), який можна використовувати для отриманняPostмодель.

Локалізація ресурсів URI

За замовчуванням,Route::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',
    ]);
}

Після налаштування дієслів, реєстрація маршруту ресурсу, наприкладRoute::resource('fotos', 'PhotoController')видасть такі URI:

/fotos/crear

/fotos/{foto}/editar

Доповнення контролерів ресурсів

Якщо вам потрібно додати додаткові маршрути до контролера ресурсів, що перевищують набір маршрутів ресурсів за замовчуванням, вам слід визначити ці маршрути перед вашим викликомRoute::resource; в іншому випадку маршрути, визначеніresourceметод ненавмисно може мати перевагу над вашими додатковими маршрутами:

Route::get('photos/popular', [PhotoController::class, 'popular']);

Route::resource('photos', PhotoController::class);
Пам’ятайте, щоб ваші контролери були зосередженими. Якщо ви вважаєте, що вам регулярно потрібні методи поза типовим набором дій із ресурсами, розгляньте можливість розділити свій контролер на два менших контролери.

Інжекція залежності та контролери

Інжектор конструктора

Laravelьслужбовий контейнервикористовується для вирішення всіх контролерів Laravel. Як результат, ви можете вводити натяк на будь-які залежності, які можуть знадобитися вашому контролеру, у своєму конструкторі. Заявлені залежності будуть автоматично вирішені та введені в екземпляр контролера:

<?php

namespace App\Http\Controllers;

use App\Repositories\UserRepository;

class UserController extends Controller
{
    /**
     * The user repository instance.
     */
    protected $users;

    /**
     * Create a new controller instance.
     *
     * @param  UserRepository  $users
     * @return void
     */
    public function __construct(UserRepository $users)
    {
        $this->users = $users;
    }
}

Ви також можете ввести будь-який натякКонтракт Laravel. Якщо контейнер може це вирішити, ви можете ввести-підказати. Залежно від вашої програми, введення ваших залежностей у ваш контролер може забезпечити кращу перевірочність.

Метод ін’єкції

На додаток до введення конструктора, ви також можете натякнути на залежність від методів вашого контролера. Поширеним варіантом використання ін'єкції методу є ін'єкціяIlluminate\Http\Requestекземпляр у ваші методи контролера:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
     * Store a new user.
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        $name = $request->name;

        //
    }
}

Якщо ваш метод контролера також очікує введення від параметра маршруту, перелічіть аргументи маршруту після інших залежностей. Наприклад, якщо ваш маршрут визначено так:

Route::put('user/{id}', [UserController::class, 'update']);

Ви все ще можете навести натяк наIlluminate\Http\Requestі отримати доступ до вашогоidпараметром, визначивши метод контролера наступним чином:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
     * Update the given user.
     *
     * @param  Request  $request
     * @param  string  $id
     * @return Response
     */
    public function update(Request $request, $id)
    {
        //
    }
}

Кешування маршрутів

Якщо у вашій програмі використовуються виключно маршрути, засновані на контролерах, вам слід скористатися кешем маршрутів Laravel. Використання кешу маршрутів різко зменшить кількість часу, необхідного для реєстрації всіх маршрутів вашої програми. У деяких випадках реєстрація маршруту може бути навіть в 100 разів швидшою. Щоб створити кеш маршруту, просто запустітьroute:cacheКоманда ремісників:

php artisan route:cache

Після запуску цієї команди ваш кешований файл маршрутів буде завантажений при кожному запиті. Пам'ятайте, що якщо ви додаєте нові маршрути, вам потрібно буде створити новий кеш маршрутів. Через це вам слід лише запускатиroute:cacheкоманда під час розгортання вашого проекту.

Ви можете використовуватиroute:clearкоманда для очищення кешу маршруту:

php artisan route:clear