Организация ваших шаблонов

Организация ваших шаблонов в Laravel

Часто наши приложения используют большое количество blade-шаблонов. Когда их становится больше десятка, то вы начинаете создавать их везде, где не требуется рефакторить к ним путь. А потом вы в них теряетесь: где компоненты? Где макеты? А этот макет надо засунуть сюда или туда?

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

views/
├── mail
│   └── ...
├── components
│   ├── post-card.blade.php
│   ├── user-card.blade.php
│   ├── password-input.blade.php
│   └── image-container.blade
└── web/
    ├── layout
    │   ├── header
    │   │   ├── links.blade.php
    │   │   ├── css.blade.php
    │   │   └── js.blade.php
    │   ├── header.blade.php
    │   ├── head.blade.php
    │   └── footer.blade.php
    ├── sections
    │   ├── static
    │   │   ├── home.blade.php
    │   │   ├── about.blade.php
    │   │   ├── contact.blade.php
    │   │   └── layout.blade.php
    │   ├── profile
    │   │   ├── show.blade.php
    │   │   ├── security.blade.php
    │   │   ├── preferences.blade.php
    │   │   └── layout.blade.php
    │   ├── comment
    │   │   ├── index.blade.php
    │   │   ├── show.blade.php
    │   │   ├── edit.blade.php
    │   │   └── layout.blade.php
    │   ├── user
    │   │   ├── index.blade.php
    │   │   ├── show.blade.php
    │   │   ├── edit.blade.php
    │   │   └── layout.blade.php
    │   └── post
    │       ├── subviews
    │       │   ├── comment.blade.php
    │       │   ├── author.blade.php
    │       │   └── tags.blade.php
    │       ├── index.blade.php
    │       ├── show.blade.php
    │       ├── edit.blade.php
    │       └── layout.blade.php
    └── layout.php

Мой способ организации Views каталога очень прост. Как вы можете видеть, в моем приложении «Blog» есть несколько видов шаблонов: статические, (например «Home»), страница профиля пользователя, шаблоны комментариев, пользователей и публикаций.

Веб-шаблоны

Чтобы отделить веб-шаблоны от прочих, таких Mail или Vendor, я использую каталог web. Это отправная точка для всего что происходит в вебе, например для страниц на чистом HTML.

Я знаю, где находятся мои веб-шаблоны и могу отделить их от других каналов. Например, если в следующем году мне понадобится отдать HTML через AJAX, то я использую папку ajax:

views/
├── mail
│   └── ...
├── components
│   └── ...
├── web
│   └── ...
└── ajax
    └── ...

Макет «Master»

В корневой папке веб-шаблонов есть файл layout.blade.php — это HTML-каркас для остальных шаблонов. Обычно я определяю в этом файле основные секции скелета HTML, например, <head>, <header>, <footer> и <main>. В зависимости от сложности, я разбиваю код на подшаблоны, которые кладу в каталог layout. В то время как секции почти обязательны, для размещения контента внутри каждой части шаблона, использование же стеков очень полезно — другие шаблоны могут подключать нужные им CSS или JS.

// resources/views/web/layout/header.balde.php
<header>
    <title>@yield('title')</title>
    <link rel="stylesheet" type="text/css" href="/app.css">
    <script src="/app.js"></script>    
    
    @stack('head-css')
    @stack('head-scripts')
</header>

Я так же помещаю сюда CSS и JS из других фронтенд-фреймворков. Это дает мне централизованный способ управления ими и обновления, при необходимости, вместо того, чтобы запихнуть всё в один шаблон.

Большинство макетов, которые я делаю, выглядят вот так, потому что я делегирую каждую часть приложения соответствующей секции.

<!doctype html>
<html lang="{{ config('app.locale') }}">
<head>
    @include('web.layout.head')
</head>
<body>
<header>
    @include('web.layout.header')
</header>
<main>
    @include('web.layout.main')
</main>
<footer>
    @include('web.layout.footer')
</footer>
</body>
</html>

Разделы каталога

Создание разделов полезно для категоризации того, что представляет собой шаблон, и (надеюсь) совпадает с названием маршрута.

// routes/web.php
Route::get('post/{post}', 'PostController@show')
    ->name('post.show');

// PostController.php
public function show(Post $post)
{
    return view('web.post.show', ['post' => $post]);
}

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

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

Раздел подшаблонов

Все, что подключается через @include является подшаблоном, зависящим от от данных родительского шаблона, поэтому я размещаю их в собственных каталогах, чтобы не загрязнять большие шаблоны.

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

Создание подшаблонов — это хороший способ очистки шаблонов от громоздкого кода. Рассмотрим например post.edit:

@extends('web.post.layout')@section('main')
    <form method="post">
        @csrf
        @method('patch')
   
        <input type="text" name="title" value="{{ old('title'}}">
        <textarea name="body" value="{!! old('title' !!}">        
        
        @include('web.post.subviews.tags')
        @include('web.post.subviews.cover')        
        
        <button type="submit">Update post</button>
    </form>
@endsection

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

Компоненты

По умолчанию Laravel ищет Компоненты в папке resources/views/components. Я рассматриваю их как автономные шаблоны, которые можно использовать где угодно и не бояться, что они сломаются, если вы передадите им что-то не то.

Например, post-card.blade.php требует экземпляра модели App\Post и показывает краткое описание публикации:

Описание для Doom Eternal

Для отображения этого блока не нужно ничего, кроме публикации с необходимой информацией: заголовок, обложка и краткое описание. Я могу использовать этот компонент где угодно, например, внутри post.index, на боковой панели post.show или в шаблоне Mail.

Фронтенд против Бэкенда

Иногда лучше отделить Фронтенд (публичные шаблоны) от Бэкенда (административная панель).

Это позволит вашим шаблонам исключить фронтенд-логику и убрать архитектуру ролей/прав, чтобы иметь больше свободы для работы с бэкендом.

views/
└── web/
    ├── frontend
    │   ├── layout
    │   ├── components
    │   ├── profile
    │   └── post
    └── backend
        ├── layout
        ├── user
        ├── post
        └── comments

Здесь применяются те же принципы, поскольку мы всего лишь углубились на один каталог. По желанию можно разделить макеты для фронтенд и бэкенда, поскольку, возможно, далее вы будете обновлять и изменять их по отдельности.

Это практически все, что я хотел вас рассказать. Удачной организации ваших шаблонов.

Автор: Italo Baeza Cabrera
Перевод: Алексей Широков

Наш Телеграм-канал — следите за новостями о Laravel.