Unetway

Laravel - Controllers

Вступление

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

 

Основные контроллеры

Определение контроллеров

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

<?php

namespace App\Http\Controllers;

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

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)]);
    }
}

Вы можете определить маршрут к этому действию контроллера следующим образом:

Route::get('user/{id}', 'UserController@show');

Теперь, когда запрос соответствует указанному URI маршрута, showметод UserControllerкласса будет выполнен. Параметры маршрута также будут переданы методу.

Контроллеры не обязаны расширять базовый класс. Тем не менее, вы не будете иметь доступ к функциям удобства таких как middlewarevalidateи dispatchметоды.

 

Контроллеры и пространства имен

Очень важно отметить, что нам не нужно было указывать полное пространство имен контроллера при определении маршрута контроллера. Поскольку RouteServiceProviderфайлы маршрутов загружаются в группу маршрутов, содержащую пространство имен, мы указали только часть имени класса, которая следует за частью пространства имен.App\Http\Controllers

Если вы решите вложить ваши контроллеры глубже в каталог, используйте конкретное имя класса относительно корневого пространства имен. Итак, если ваш полный класс контроллера , вы должны зарегистрировать маршруты к контроллеру следующим образом:App\Http\ControllersApp\Http\ControllersApp\Http\Controllers\Photos\AdminController

Route::get('foo', 'Photos\AdminController@method');

 

Контроллеры одиночного действия

Если вы хотите определить контроллер, который обрабатывает только одно действие, вы можете поместить один __invokeметод в контроллер:

<?php

namespace App\Http\Controllers;

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

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)]);
    }
}

При регистрации маршрутов для контроллеров с одним действием вам не нужно указывать метод:

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

Вы можете создать вызываемый контроллер, используя --invokableопцию команды Artisan:make:controller

php artisan make:controller ShowProfile --invokable

 

Промежуточное ПО контроллера

Промежуточное программное обеспечение может быть назначено маршрутам контроллера в ваших файлах маршрутов:

Route::get('profile', 'UserController@show')->middleware('auth');

Тем не менее, удобнее указать промежуточное программное обеспечение в конструкторе вашего контроллера. Используя 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. Это обеспечивает удобный способ определения промежуточного программного обеспечения для одного контроллера без определения всего класса промежуточного программного обеспечения:

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

    return $next($request);
});

Вы можете назначить промежуточное ПО подмножеству действий контроллера; однако это может указывать на то, что ваш контроллер становится слишком большим. Вместо этого рассмотрите возможность разбиения вашего контроллера на несколько меньших контроллеров.

 

Контроллеры ресурсов

Маршрутизация ресурсов Laravel назначает типичные маршруты «CRUD» контроллеру с помощью одной строки кода. Например, вы можете создать контроллер, который обрабатывает все HTTP-запросы на «фотографии», хранящиеся в вашем приложении. Используя команду Artisan, мы можем быстро создать такой контроллер:make:controller

php artisan make:controller PhotoController --resource

Эта команда сгенерирует контроллер в . Контроллер будет содержать метод для каждой из доступных операций с ресурсами.app/Http/Controllers/PhotoController.php

Далее вы можете зарегистрировать ресурсный маршрут к контроллеру:

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

Это объявление одного маршрута создает несколько маршрутов для обработки различных действий с ресурсом. Сгенерированный контроллер уже будет иметь методы для каждого из этих действий, включая примечания, информирующие вас о глаголах HTTP и URI, которые они обрабатывают.

Вы можете зарегистрировать много контроллеров ресурсов одновременно, передав массив resourcesметоду:

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

Действия, выполняемые контроллером ресурсов

Verb URI Action Route Name
GET /photos index photos.index
GET /photos/create create photos.create
POST /photos store photos.store
GET /photos/{photo} show photos.show
GET /photos/{photo}/edit edit photos.edit
PUT/PATCH /photos/{photo} update photos.update
DELETE /photos/{photo} destroy photos.destroy

Указание модели ресурсов

Если вы используете привязку модели маршрута и хотите, чтобы методы контроллера ресурсов указывали на экземпляр модели, вы можете использовать эту --modelопцию при генерации контроллера:

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

Методы спуфинговой формы

Поскольку HTML - форма не может сделать PUTPATCHили DELETEзапросы, то вам нужно добавить скрытое _methodполе , чтобы подменить этот HTTP глаголы. @methodДиректива клинка может создать это поле для Вас:

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

 

Частичные ресурсные маршруты

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

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

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

Ресурсные маршруты API

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

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

Вы можете зарегистрировать много контроллеров ресурсов API одновременно, передав массив apiResourcesметоду:

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

Чтобы быстро сгенерировать контроллер ресурса API, который не включает методы createили edit, используйте --apiпереключатель при выполнении команды:make:controller

php artisan make:controller API/PhotoController --api

 

Маршруты именования ресурсов

По умолчанию все действия контроллера ресурсов имеют имя маршрута; однако вы можете переопределить эти имена, передав namesмассив с вашими параметрами:

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

 

Наименование параметров маршрута ресурса

По умолчанию будут созданы параметры маршрута для маршрутов вашего ресурса на основе «единой» версии имени ресурса. Вы можете легко переопределить это для каждого ресурса, используя метод. Массив, передаваемый в метод, должен быть ассоциативным массивом имен ресурсов и имен параметров:Route::resourceparametersparameters

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

В приведенном выше примере создаются следующие URI для showмаршрута ресурса :

/users/{admin_user}

 

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

По умолчанию будут созданы ресурсы URI с использованием английских глаголов. Если вам нужно локализовать глаголы действия и действия, вы можете использовать метод. Это может быть сделано в методе вашего :Route::resourcecreateeditRoute::resourceVerbsbootAppServiceProvider

use Illuminate\Support\Facades\Route;

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

Как только глаголы будут настроены, при регистрации маршрута ресурса, например, будут созданы следующие URI:Route::resource('fotos', 'PhotoController')

/fotos/crear

/fotos/{foto}/editar

 

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

Если вам нужно добавить дополнительные маршруты к контроллеру ресурсов помимо набора маршрутов ресурсов по умолчанию, вы должны определить эти маршруты перед вызовом ; в противном случае маршруты, определенные методом, могут непреднамеренно иметь приоритет над вашими дополнительными маршрутами:Route::resourceresource

Route::get('photos/popular', 'PhotoController@method');

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

Не забывайте держать ваши контроллеры в фокусе. Если вы обнаружите, что постоянно нуждаетесь в методах, выходящих за рамки типичного набора действий с ресурсами, рассмотрите возможность разделения вашего контроллера на два меньших контроллера.

 

Инъекция зависимостей и контроллеры

Конструктор Инъекция

Сервисный контейнер 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@update');

Вы все еще можете напечатать подсказку и получить доступ к своему параметру, определив метод контроллера следующим образом:Illuminate\Http\Requestid

<?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)
    {
        //
    }
}

 

Кэширование маршрута

Маршруты на основе замыкания не могут быть кэшированы. Чтобы использовать кэширование маршрутов, вы должны преобразовать все маршруты Closure в классы контроллеров.

Если ваше приложение использует исключительно маршруты на основе контроллера, вы должны воспользоваться кешем маршрутов Laravel. Использование кэша маршрутов значительно сократит время, необходимое для регистрации всех маршрутов вашего приложения. В некоторых случаях регистрация вашего маршрута может быть даже в 100 раз быстрее. Чтобы создать кэш маршрута, просто выполните команду Artisan:route:cache

php artisan route:cache

После выполнения этой команды ваш файл кэшированных маршрутов будет загружаться при каждом запросе. Помните, что если вы добавляете какие-либо новые маршруты, вам нужно будет создать новый кеш маршрутов. Из-за этого вы должны запускать команду только во время развертывания вашего проекта.route:cache

Вы можете использовать команду для очистки кэша маршрута:route:clear

php artisan route:clear