Сайт вебмастера

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 &gt; world</title>

Экранировать данные нужно на уровне их вывода. То есть не нужно пытаться экранировать данные в контролере — он должен возвращать и передавать данные как есть без искажений.

Related Posts
Comments (3) RSS
1 Александр Соловей 2019-08-15 17:32:52

А про layouts будешь писать?


2 Admin 2019-08-15 17:47:12 admin

Так section и есть Layouts в представлении.


3 Ярослав 2021-11-10 10:44:42

Спасибо! Недавно начал изучать CodeIgniter и ваша статья мне очень помогла!