CodeIgniter 4. Views
15-08-2019Reading time ~ 5 min.CodeIgniter 8973
Усложним наше приложение. Пусть это будет несколько статичных html-страниц, например about и hello. Сделаем так, чтобы html-шаблон был разбит на части.
Основа любого фреймворка — роутинг — именно через него пропускается входящий url-запрос и дальше решается какой контролёр будет запущен. В CodeIgniter используется «классический» вариант роутинга
http://example.com/[controller-class]/[controller-method]/[arguments]
То есть если мы захотим обслужить адрес http://example.com/about будет достаточно сделать контролер About.php
. Это что-то вроде «автороутинга», где CodeIgniter сам подхватывает подходящий файл и класс.
Проверим. Сделайте файл контролёра About.php
(можно скопировать Home.php
и отредактировать).
namespace App\Controllers; class About extends BaseController { public function index() { return view('welcome_message'); } }
То есть теперь это класс About. При этом мы всё также выводим представление welcome_message.php
. Теперь сделаем ещё один адрес http://example.com/about/contact. То есть у нас тот же самый класс About, но уже с методом contact().
По умолчанию в контролёрах используется метод index()
.
Добавим:
namespace App\Controllers; class About extends BaseController { public function index() { return view('welcome_message'); } public function contact() { return view('welcome_message'); } }
Запустим в браузере http://example.com/about/contact и увидим всё тоже приветствие. Если же запустить адрес без этого метода, то CodeIgniter выдаст 404-страницу.
Представления Views
«Вьюшки» по своей сути — обычные php-файлы. Функция view()
на самом деле оболочка над View->render
, который выполняет «рендеринг» файла. Но чаще всего это называют html/php-шаблонизатор, который не просто подключает view-файл, но и предоставляет в его распоряжение заранее подготовленные данные.
Например для about-страницы, мы хотим передать title для браузера и какой-то заголовок.
namespace App\Controllers; class About extends BaseController { public function index() { $data['title'] = 'О сайте'; $data['header'] = 'О нашем сайте'; return view('about', $data); } public function contact() { $data['title'] = 'О сайте / Контакты'; $data['header'] = 'Связаться с нами'; return view('about', $data); } }
В данном примере в представление будет передан массив $data
, где он автоматом будет «экстрактнут» — появятся переменные $title
и $header
. Сделаем файл предcтвления about.php
<!doctype html><html> <head> <title><?= $title ?></title> </head> <body> <h1><?= $header ?></h1> </body> </html>
Разделение представления
Сейчас файл about.php
содержит всю html-разметку. С точки зрения верстальщика — это тихий ужас, поэтому мы сделаем так, чтобы вынести вёрстку страницы в раздельные файлы. Для этого сделаем каталог app/Views/template
, где будем хранить файлы начальной и конечной части страницы.
Файл app/Views/template/start.php
:
<!doctype html><html> <head> <title><?= $title ?></title> </head> <body>
Файл app/Views/template/end.php
:
</body></html>
Соответственно файл about.php
:
<h1><?= $header ?></h1>
Теперь в контролёре About подключим эти файлы:
namespace App\Controllers; class About extends BaseController { public function index() { $data['title'] = 'О сайте'; $data['header'] = 'О нашем сайте'; echo view('template/start', $data); echo view('about', $data); echo view('template/end', $data); } public function contact() { $data['title'] = 'О сайте / Контакты'; $data['header'] = 'Связаться с нами'; echo view('template/start', $data); echo view('about', $data); echo view('template/end', $data); } }
Таким вот нехитрым способом можно разбивать вывод представления частями.
Включения в представление
То что мы перенесли логику представления в контролер не самая лучшая идея. Она годится, если нужно сделать что-то несложное, но представьте себе страницу, где нужно вывести десяток блоков? Проблема будет ещё в тех случаях, когда используется сложная html-структура, где блоки могут переплетаться между собой.
В таких случаях желательно переносить логику включений в само представление. Сделаем ещё одну страницу hello.
namespace App\Controllers; class Hello extends BaseController { public function index() { $data['title'] = 'Hello'; $data['header'] = 'Hello, world!'; echo view('hello', $data); } }
Обратите внимание, что здесь мы подключаем только одну «вьюшку» hello.php
. В этом файле выполним включение:
<?= $this->include('template/start') ?> <h1><?= $header ?></h1> <?= $this->include('template/end') ?>
То есть теперь можно разбивать представление на любые файлы и использовать их по ситуации. Это лучше, чем каждый раз править контролёр.
Включение в шаблон
Существует еще один способ вставки представления в html-шаблон (назовем его main). Здесь вставка происходит как бы наоборот: в main-шаблоне задаются секции для вывода, а представление уже реализуют эти самые секции. Контролер при этом не меняется.
Вначале нужно задать main-шаблон, например template/main.php
<!doctype html> <html><head> <title><?= $title ?></title> </head> <body> <?= $this->renderSection('header') ?> <hr> <?= $this->renderSection('description') ?> </body> </html>
Здесь мы определяем две секции: header и description.
Теперь открываем нашу «вьюшку» hello.php
<?php $this->extend('template/main') ?> <?= $this->section('header') ?> <h1><?= $header ?></h1> <?= $this->endSection() ?> <?= $this->section('description') ?> <h5>Welcome to CodeIgniter 4!</h5> <?= $this->endSection() ?>
Первая строчка (extend) указывает на используемый main-шаблон. CodeIgniter, когда встретит этот код, переведёт вывод в «секционный режим». Каждая секция обрамляется индивидуально. В этом примере их задано две: header и description, то есть те самые секции, которые выводятся в html-каркасе. CodeIgniter их распарсит, а после подставит результат в main-шаблон.
Какой вариант компоновки вывода использовать будет зависеть от задач. Если в main-шаблоне немного секций, то можно делать через него. Если же секций много, то есть смысл использовать компоновку на уровне каждого представления.
Экранирование вывода
В некоторых случаях для вывода нужно использовать экранирование html-данных. Например в title нужно заменить html-спецсимволы. Для этого в CodeIgniter используется вспомогательная функция esc()
(можно и стандартные php-функции).
Например в данных:
$data['title'] = 'Hello > world';
Если не экранировать, то получится такой html-код:
<title>Hello > world</title>
Поэтому делаем так:
<title><?= esc($title) ?></title>
В результате получаем корректный html-код.
<title>Hello > world</title>
Экранировать данные нужно на уровне их вывода. То есть не нужно пытаться экранировать данные в контролере — он должен возвращать и передавать данные как есть без искажений.
А про layouts будешь писать?
Так section и есть Layouts в представлении.
Спасибо! Недавно начал изучать CodeIgniter и ваша статья мне очень помогла!