Ресурсная маршрутизация

Фактически, любой CRUD состоит из 7 маршрутов, контроллера и шаблонов. Причём большая часть этого кода идентична, особенно маршруты. Они не содержат логики и всегда строятся по одному и тому же принципу.

Laravel частично заимствовал из Rails ещё один механизм, который называется "ресурсная маршрутизация". Он упрощает создание типичных CRUD, за счёт полной унификации всех маршрутов и способов их обработки. Вместо описания 7 разных маршрутов, ресурсная маршрутизация позволяет указать один метамаршрут:

<?php

Route::resource('/articles', 'ArticleController');

Внутри себя он превращается в те самые семь маршрутов, которые мы реализовывали в предыдущих уроках. Их можно увидеть с помощью команды artisan:

$ php artisan route:list
+-----------+-------------------------+------------------+------------------------------------------------+
| Method    | URI                     | Name             | Action                                         |
+-----------+-------------------------+------------------+------------------------------------------------+
| GET|HEAD  | /                       |                  | Closure                                        |
| GET|HEAD  | articles                | articles.index   | App\Http\Controllers\ArticleController@index   |
| POST      | articles                | articles.store   | App\Http\Controllers\ArticleController@store   |
| GET|HEAD  | articles/create         | articles.create  | App\Http\Controllers\ArticleController@create  |
| GET|HEAD  | articles/{article}      | articles.show    | App\Http\Controllers\ArticleController@show    |
| PUT|PATCH | articles/{article}      | articles.update  | App\Http\Controllers\ArticleController@update  |
| DELETE    | articles/{article}      | articles.destroy | App\Http\Controllers\ArticleController@destroy |
| GET|HEAD  | articles/{article}/edit | articles.edit    | App\Http\Controllers\ArticleController@edit    |
+-----------+-------------------------+------------------+------------------------------------------------+
# Обратите внимание на имя плейсхолдера. Ниже станет понятно почему здесь article, а не id

Довольно неплохо. В проектах где подобных CRUD много (любой типичный веб-проект), ресурсный маршрутизатор очень помогает. Он не просто сокращает количество кода, но и даёт хорошую унификацию. Нужно меньше думать и меньше спорить. Всё уже спроектировано.

Следующий шаг – упрощение контроллера. Во-первых можно сразу сгенерировать контроллер, со всеми нужными обработчиками. Во-вторых, этот контроллер можно интегрировать с нужной моделью:

php artisan make:controller ArticleController --resource --model Article

На выходе получим такой контроллер:

<?php

namespace App\Http\Controllers;

use App\Article;
use Illuminate\Http\Request;

class ArticleController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Article  $article
     * @return \Illuminate\Http\Response
     */
    public function show(Article $article)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Article  $article
     * @return \Illuminate\Http\Response
     */
    public function edit(Article $article)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Article  $article
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Article $article)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Article  $article
     * @return \Illuminate\Http\Response
     */
    public function destroy(Article $article)
    {
        //
    }

Обратите внимание на параметры обработчиков. Laravel самостоятельно находит нужную сущность и достаёт её из базы данных. Это позволяет хоть немного, но сократить код.

Ресурсы могут быть вложенными. Это даёт возможность строить пути, отражающие зависимости между сущностями на сайте:

# Примеры с Хекслета

# Урок /courses/{course}/lessons/{lesson}
/courses/js-testing/lessons/asserts
# Список пройденных курсов /u/{user}/courses
/u/mokevnin/courses

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

# Список
/entities/{entity}/subentities

# Сущность
/entities/{entity}/subentity/{subentity}

# Все остальные маршруты строятся по такому же принципу.
# Впереди добавляется /entities/{entity}.

Вложенный ресурс можно генерировать автоматически:

php artisan make:controller ArticleCommentController --resource --model ArticleComment --parent Article

Например, вот так выглядит ресурс комментарии к статьям:

<?php

Route::resource('/articles.comments', 'ArticleCommentController');

Для вложенного ресурса, в экшены, кроме самой сущности передаётся и родительская сущность:

<?php

# /articles/{article}/comments/{comment}
# Обе сущности можно получить через параметры
public function edit(Article $article, ArticleComment $comment)
{
    return view('article_comment.edit', compact('article', 'comment'));
}

Немного по другому начинает работать хелпер route. Для построения ссылок, там где участвуют оба ресурса, нужно использовать массив для их передачи:

<?php

route('articles.comments.edit', [$article, $comment]);

Заключение

Ресурсная маршрутизация – удобный механизм, позволяющий немного упростить создание CRUD. Он берёт на себя много работы и даёт программисту возможность сосредоточиться на логике.

Существует негласное правило, насколько вложенным может быть вложенная маршрутизация. Считается, что не стоит делать более одного вложения. Иначе ссылки получаются очень длинными, а код начинает усложняться, так как приходится оперировать сразу тремя сущностями и более.

Самостоятельная работа

  1. Удалите все маршруты связанные со статьями
  2. Удалите контроллер статей (шаблоны оставьте)
  3. Добавьте ресурсную маршрутизация articles
  4. Сгенерируйте для него контроллер ArticleController
  5. Реализуйте CRUD

Дополнительные материалы

  1. Ресурсная маршрутизация

Для полного доступа к курсу, нужна профессиональная подписка

Профессиональная подписка откроет полный доступ ко всем курсам Хекслета, даст возможность обращаться за помощью к менторам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
115
курсов
892
упражнения
2241
час теории
3196
тестов

Зарегистрироваться

или войти в аккаунт

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 115 курсов, 2000+ часов теории
  • 800 практических заданий в браузере
  • 250 000 студентов

Нажимая кнопку «Зарегистрироваться», вы даёте своё согласие на обработку персональных данных в соответствии с «Политикой конфиденциальности» и соглашаетесь с «Условиями оказания услуг».

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Rambler
Логотип компании Bookmate
Логотип компании Botmother

Есть вопрос или хотите участвовать в обсуждении?

Зарегистрируйтесь или войдите в свой аккаунт

Нажимая кнопку «Зарегистрироваться», вы даёте своё согласие на обработку персональных данных в соответствии с «Политикой конфиденциальности» и соглашаетесь с «Условиями оказания услуг».