Представлення є частиною архітектури [MVC](http://uk.wikipedia.org/wiki/Модель-вид-контролер).
Це код, який відповідає за відображення даних кінцевим користувачам. У веб-додатку представлення зазвичай створені
у вигляді *шаблонів представлень*, які є файлами скриптів PHP, що містять переважно HTML-код та презентаційний PHP-код.
Управління ними здійснюється за допомогою [компонента додатку](structure-application-components.md) [[yii\web\View|view]], який надає часто використовувані методи
для полегшення компонування та формування представлення. Для простоти, часто шаблони представлень або файли шаблонів представлень називаються
представленнями.
## Створення представлень <span id="creating-views"></span>
Як зазначено вище, представлення є простим скриптом PHP, який містить HTML- та PHP-код. Далі наведено представлення,
що представляє форму входу користувача. Як можна побачити, PHP-код використовується для генерування динамічного вмісту, такого як
заголовку сторінки та форми, тоді як HTML-код організовує їх у презентабельну HTML-сторінку.
```php
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/* @var $this yii\web\View */
/* @var $form yii\widgets\ActiveForm */
/* @var $model app\models\LoginForm */
$this->title = 'Вхід';
?>
<h1><?= Html::encode($this->title) ?></h1>
<p>Будь ласка, заповніть наступні поля для входу:</p>
* [[yii\base\Widget::renderFile()|renderFile()]]: формує представлення визначене шляхом файлу представлення або
[псевдонімом](concept-aliases.md).
Наприклад:
```php
namespace app\components;
use yii\base\Widget;
use yii\helpers\Html;
class ListWidget extends Widget
{
public $items = [];
public function run()
{
// формує представлення з ім’ям "list"
return $this->render('list', [
'items' => $this->items,
]);
}
}
```
### Формування у представленнях <span id="rendering-in-views"></span>
Ви можете формувати представлення всередині іншого представлення за допомогою виклику одного з наступних методів наданих [[yii\base\View|компонентом представлення]]:
При формуванні представлення ви можете визначити його, використовуючи ім’я представлення або шлях/псевдонім до файлу представлення. У більшості випадків
ви будете використовувати перший варіант, тому що він більш лаконічний та гнучкий. Представлення, визначені за допомогою імен називаються *іменованими представленнями*.
Ім’я представлення перетворюється у відповідний шлях до файлу представлення за наступними правилами:
* Ім’я представлення можна вказувати без розширення імені файлу. У цьому випадку в якості розширення буде використовуватись `.php`. Наприклад,
ім’я представлення `about` відповідає імені файлу `about.php`.
* Якщо ім’я представлення починається з двох слешів `//`, то відповідним шляхом до файлу представлення буде `@app/views/ViewName`.
Це означає, що представлення шукається в [[yii\base\Application::viewPath|директорії представлень додатку]].
Наприклад, `//site/about` буде перетворено в `@app/views/site/about.php`.
* Якщо ім’я представлення починається з одного слешу `/`, то шлях до файлу представлення складатиметься з імені представлення та префіксу
у вигляді [[yii\base\Module::viewPath|директорії представлень]] поточного активного [модулю](structure-modules.md).
Якщо немає активного модулю, то буде використовуватись `@app/views/ViewName`. Наприклад, `/user/create` буде перетворено в
`@app/modules/user/views/user/create.php`, якщо поточним активним модулем є `user`. Якщо немає активного модулю,
то шляхом до файлу представлення буде `@app/views/user/create.php`.
* Якщо представлення формується з [[yii\base\View::context|контекстом]] і контекст має реалізований інтерфейс [[yii\base\ViewContextInterface]],
то шлях до файлу представлення складатиметься з префікса у вигляді [[yii\base\ViewContextInterface::getViewPath()|директорії представлень]]
контексту та з імені представлення. Це частіше застосовується до представлень, які формуються всередині контролерів або віджетів. Наприклад,
`about` буде перетворено в `@app/views/site/about.php`, якщо контекстом є контролер `SiteController`.
* Якщо представлення формується в середині іншого представлення, директорія, що містить інше представлення буде додана перед
іменем представлення, що формується, для створення актуального шляху до файлу. Наприклад, `item` перетвориться в `@app/views/post/item.php`,
якщо буде формуватись із представлення `@app/views/post/index.php`.
Згідно з наведеними правилами, виклик `$this->render('view')` у контролері `app\controllers\PostController` буде
формувати представлення з файлу `@app/views/post/view.php`, в той час як виклик `$this->render('_overview')` у тому представленні
буде формувати представлення з файлу `@app/views/post/_overview.php`.
### Доступ до даних у представленнях <span id="accessing-data-in-views"></span>
Є два підходи при доступові до даних в середині представлення: "вштовхування" та "витягування".
Передаючи дані другим параметром у методи формування представлення, ви використовуєте підхід "вштовхування".
Дані повинні бути надані у вигляді масиву пар ключ-значення. Під час формування представлення буде викликана функція PHP
`extract()` на цьому масиві, видобувши таким чином змінні у представлення.
Наприклад, наступний код формування представлення у контролері "вштовхне" дві змінні до представлення `report`:
`$foo = 1` та `$bar = 2`.
```php
echo $this->render('report', [
'foo' => 1,
'bar' => 2,
]);
```
Підхід "витягування" активно здобуває дані з [[yii\base\View|компоненту представлення]] або інших об’єктів, доступних
у представленнях (наприклад, `Yii::$app`). Використовуючи нижче наведений код як приклад, всередині представлення можна отримати об’єкт
за допомогою виразу `$this->context`. У результаті, стає можливим доступ до усіх властивостей та методів
контролера у представленні `report`, як, наприклад, ідентифікатору контролера, що наведений у прикладі:
Як ви можете бачити, макет генерує HTML-теги, які є спільними для всіх сторінок. У секції `<body>`
макет виводить змінну `$content`, яка містить результат формування вкладених представлень та "вштовхується"
у макет під час виклику методу [[yii\base\Controller::render()]].
В більшості макетів наступні методи будуть викликатись як показано у вищенаведеному коді. Ці методи здебільшого породжують події,
пов’язані з процесом формування, щоб скрипти та теги, які зареєстровані в інших місцях могли бути правильно включенні в
місцях, де ці методи викликаються.
- [[yii\base\View::beginPage()|beginPage()]]: Цей метод повинен викликатись на самому початку макету.
Він породжує подію [[yii\base\View::EVENT_BEGIN_PAGE|EVENT_BEGIN_PAGE]], яка слугує ознакою початку сторінки.
- [[yii\base\View::endPage()|endPage()]]: Цей метод повинен викликатись в кінці макету.
Він породжує подію [[yii\base\View::EVENT_END_PAGE|EVENT_END_PAGE]], яка слугує ознакою кінця сторінки.
- [[yii\web\View::head()|head()]]: Цей метод повинен викликатись всередині секції `<head>` HTML-сторінки.
Він генерує заповнювач, який буде замінено зареєстрованим HTML-кодом (наприклад, теги link і meta),
коли сторінка буде повністю сформована.
- [[yii\web\View::beginBody()|beginBody()]]: Цей метод повинен викликатись на початку секції `<body>`.
Він породжує подію [[yii\web\View::EVENT_BEGIN_BODY|EVENT_BEGIN_BODY]] та генерує заповнювач, який
буде замінено зареєстрованим HTML-кодом (наприклад, JavaScript) на початку секції `<body>`.
- [[yii\web\View::endBody()|endBody()]]: Цей метод повинен викликатись у кінці секції `<body>`.
Він породжує подію [[yii\web\View::EVENT_END_BODY|EVENT_END_BODY]] та генерує заповнювач, який
буде замінено зареєстрованим HTML-кодом (наприклад, JavaScript) у кінці секції `<body>`.
### Доступ до даних у макетах <span id="accessing-data-in-layouts"></span>
Всередині макету ви маєте доступ до двох попередньо визначених змінних: `$this` та `$content`. Перша посилається на
компонент [[yii\base\View|представлення]], як і у звичайних представленнях, в той час як друга містить результат формування вкладеного
представлення, який формується викликом методу [[yii\base\Controller::render()|render()]] у контролерах.
Якщо ви бажаєте мати доступ до інших даних у макетах, то вам потрібно використовувати підхід "витягування", описаний в
підрозділі [Доступ до даних у представленнях](#accessing-data-in-views). Якщо ви бажаєте отримати дані з вкладеного представлення
у макеті, то можете використати підхід описаний у підрозділі [Обмін даними між представленнями](#sharing-data-among-views).
### Використання макетів <span id="using-layouts"></span>
Як описано в підрозділі [Формування в контролерах](#rendering-in-controllers), під час формування представлення
через виклик методу [[yii\base\Controller::render()|render()]] у контролері, буде застосовний макет
до результату формування. За замовчуванням, буде використовуватись макет `@app/views/layouts/main.php`.
Ви можете використовувати інший макет сконфігурувавши властивість [[yii\base\Application::layout]] або [[yii\base\Controller::layout]].
Перша відповідає за макет, який використовується усіма контролерами, друга ж перекриває першу для окремих контролерів.
Наприклад, наступний код налаштовує контролер `post` на використання макету `@app/views/layouts/post.php`
під час формування його представлень. Інші контролери, за умови, що їх властивість `layout` не встановлена, будуть надалі
використовувати типовий макет `@app/views/layouts/main.php`.
```php
namespace app\controllers;
use yii\web\Controller;
class PostController extends Controller
{
public $layout = 'post';
// ...
}
```
Для контролерів, що належать модулю, ви можете також сконфігурувати властивість модуля [[yii\base\Module::layout|layout]], щоб
використовувати окремий макет для цих контролерів.
Оскільки властивість `layout` може бути сконфігурована на різних рівнях (контролери, моделі, додаток),
"за лаштунками" Yii виконує два кроки, щоб визначити, який файл макету є актуальним для окремого контролера.
На першому кроці, визначається значення `layout` та контекстний модуль:
- Якщо властивість контролера [[yii\base\Controller::layout]] відмінна від `null`, використовується вона і
[[yii\base\Controller::module|модуль]] контролера як контекстний модуль.
- Якщо [[yii\base\Controller::layout|layout]] не визначено (дорівнює `null`), здійснюється пошук у всіх батьківських модулях (включаючи сам додаток) контролера та
знаходиться перший модуль, властивість [[yii\base\Module::layout|layout]] якого не дорівнює `null`. Використовується значення цього модуля
[[yii\base\Module::layout|layout]] та сам модуль як контекстний модуль.
Якщо такого модуля не знайдено, це означає, що макет не буде застосовано.
На другому кроці, визначається актуальний файл макету відповідно до значення `layout` та контекстного модулю,
визначених на першому кроці. Значенням `layout` може бути:
- псевдонім шляху (наприклад, `@app/views/layouts/main`);
- абсолютний шлях (наприклад, `/main`): значення `layout` починається зі слешу. Актуальний файл макету буде
шукатись під [[yii\base\Application::layoutPath|директорією макетів]] додатка, яка типово дорівнює
`@app/views/layouts`;
- відносний шлях (наприклад, `main`): актуальний файл макету буде шукатись під
[[yii\base\Module::layoutPath|директорією макетів]] контекстного модуля, яка типово є директорією `views/layouts` під
[[yii\base\Module::basePath|директорією модуля]];
- логічне значення `false`: макет не буде застосовано.
Якщо значення `layout` не містить розширення файлу, то буде використане типове розширення `.php`.
Як показано вище, вміст дочірнього макету повинен бути замкнений між [[yii\base\View::beginContent()|beginContent()]] та
[[yii\base\View::endContent()|endContent()]]. Параметр, який передається в [[yii\base\View::beginContent()|beginContent()]]
визначає батьківський макет. Цей може бути файл макету чи псевдонім шляху.
Використовуючи цей підхід, можна вкладати макети більше, ніж на один рівень.
### Використання блоків <span id="using-blocks"></span>
Блоки дозволяють визначати вміст представлення в одному місці, а відображати в іншому. Вони часто використовуються разом
з макетами. Наприклад, ви можете визначити блок у вкладеному представленні та відобразити його у макеті.
Виклики [[yii\base\View::beginBlock()|beginBlock()]] та [[yii\base\View::endBlock()|endBlock()]] визначають блок.
Потім блок може бути доступним через `$view->blocks[$blockID]`, де `$blockID` означає унікальний ідентифікатор, який ви призначаєте
блоку під час його визначення.
Нижченаведений приклад показує як ви можете використовувати блоки у вкладеному представленні для налаштовування окремих частин макету.
Спершу, у вкладеному представленні, визначається один чи більше блоків:
```php
...
<?php $this->beginBlock('block1'); ?>
...вміст блоку 1...
<?php $this->endBlock(); ?>
...
<?php $this->beginBlock('block3'); ?>
...вміст блоку 3...
<?php $this->endBlock(); ?>
```
Потім, у макеті, формуються блоки, якщо вони присутні, або відображається деякий типовий вміст, якщо блок
не визначено.
```php
...
<?php if (isset($this->blocks['block1'])): ?>
<?= $this->blocks['block1'] ?>
<?php else: ?>
... типовий вміст для блоку 1 ...
<?php endif; ?>
...
<?php if (isset($this->blocks['block2'])): ?>
<?= $this->blocks['block2'] ?>
<?php else: ?>
... типовий вміст для блоку 2 ...
<?php endif; ?>
...
<?php if (isset($this->blocks['block3'])): ?>
<?= $this->blocks['block3'] ?>
<?php else: ?>
... типовий вміст для блоку 3 ...
<?php endif; ?>
...
```
## Використання компонентів представлення <span id="using-view-components"></span>
[[yii\base\View|Компоненти представлення]] надають багато можливостей, пов’язаних із представленням. Ви можете отримувати компоненти представлення
за допомогою створення індивідуальних екземплярів [[yii\base\View]] або його дочірніх класів, але у більшості випадків ви переважно будете використовувати
компонент `view` додатку. Ви можете сконфігурувати цей компонент у [конфігураціях додатку](structure-applications.md#application-configurations)
як наведено нижче:
```php
[
// ...
'components' => [
'view' => [
'class' => 'app\components\View',
],
// ...
],
]
```
Компоненти представлення надають наступні корисні можливості, пов’язані з представленням, які описані більш детально в окремих розділах:
* [темізація](output-theming.md): дозволяє проектувати та змінювати тему для веб-сайту;
* [кешування фрагментів](caching-fragment.md): дозволяє кешувати фрагменти веб-сторінки;
* [опрацювання клієнтських скриптів](output-client-scripts.md): підтримує реєстрацію та формування CSS та JavaScript;
* [опрацювання колекції ресурсів](structure-assets.md): підтримує реєстрацію та формування [колекцій ресурсів](structure-assets.md);
* [альтернативні шаблонізатори](tutorial-template-engines.md): дозволяє використовувати інші шаблонізатори, такі як
### Реєстрація тегів link <span id="registering-link-tags"></span>
Так само як і [мета-теги](#registering-meta-tags), теги link є корисними у багатьох випадках, як, наприклад, налаштування favicon, посилання на
стрічку новин (RSS) або делегування OpenID іншому серверу. Ви можете працювати з тегами link подібним шляхом як і з мета-тегами,
використовуючи [[yii\web\View::registerLinkTag()]]. Наприклад, у вкладеному представленні, ви можете зареєструвати тег link наступним чином,
```php
$this->registerLinkTag([
'title' => 'Свіжі новини про Yii',
'rel' => 'alternate',
'type' => 'application/rss+xml',
'href' => 'http://www.yiiframework.com/rss.xml/',
]);
```
Результатом вищенаведеного коду буде
```html
<linktitle="Свіжі новини про Yii"rel="alternate"type="application/rss+xml"href="http://www.yiiframework.com/rss.xml/">
```
Подібно до [[yii\web\View::registerMetaTag()|registerMetaTags()]], ви можете визначати ключ під час виклику
[[yii\web\View::registerLinkTag()|registerLinkTag()]] для запобігання генерування повторних тегів link одного типу.
## Події у представленнях <span id="view-events"></span>
[[yii\base\View|Компоненти представлення]] породжують кілька подій в процесі формування представлення. Ви можете призначити обробники
на ці події для вставлення вмісту в представлення або для опрацювання сформованих результатів перед їх відправленням кінцевим користувачам.
- Подія [[yii\base\View::EVENT_BEFORE_RENDER|EVENT_BEFORE_RENDER]]: породжується на початку формування файлу
в контролері. Обробники цієї події можуть встановлювати значення властивості [[yii\base\ViewEvent::isValid]] рівним `false` для скасування процесу формування.
- Подія [[yii\base\View::EVENT_AFTER_RENDER|EVENT_AFTER_RENDER]]: породжується після формування файлу викликом [[yii\base\View::afterRender()]].
Обробники цієї події можуть отримати результат формування через властивість [[yii\base\ViewEvent::output]] та можуть модифікувати
її для зміни результату формування.
- Подія [[yii\base\View::EVENT_BEGIN_PAGE|EVENT_BEGIN_PAGE]]: породжується викликом [[yii\base\View::beginPage()]] у макетах.
- Подія [[yii\base\View::EVENT_END_PAGE|EVENT_END_PAGE]]: породжується викликом [[yii\base\View::endPage()]] у макетах.
- Подія [[yii\web\View::EVENT_BEGIN_BODY|EVENT_BEGIN_BODY]]: породжується викликом [[yii\web\View::beginBody()]] у макетах.
- Подія [[yii\web\View::EVENT_END_BODY|EVENT_END_BODY]]: породжується викликом [[yii\web\View::endBody()]] у макетах.
Наприклад, наступний код вставить поточну дату в кінці секції `<body>` сторінки:
```php
\Yii::$app->view->on(View::EVENT_END_BODY, function () {
echo date('Y-m-d');
});
```
## Формування статичних сторінок <span id="rendering-static-pages"></span>
До статичних сторінок відносяться ті веб-сторінки, в яких основний вміст здебільшого статичний та не потребує доступу
до динамічних даних, що передаються з контролерів.
Можна виводити статичні сторінки, розмістивши їх код у представленні, а потім використовуючи код подібний до наведеного у контролері:
```php
public function actionAbout()
{
return $this->render('about');
}
```
Якщо веб-сайт містить багато статичних сторінок, було б дуже стомливим повторювати схожий код багато разів.
Для вирішення цієї проблеми можна впровадити [автономну дію](structure-controllers.md#standalone-actions)
[[yii\web\ViewAction]] у контролері. Наприклад,
```php
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
public function actions()
{
return [
'page' => [
'class' => 'yii\web\ViewAction',
],
];
}
}
```
Тепер, якщо створити представлення з ім’ям `about` у директорії `@app/views/site/pages`, стане можливим
відображення цього представлення за наступною URL-адресою:
```
http://localhost/index.php?r=site/page&view=about
```
Параметр `view` із запиту `GET` вказує автономній дії [[yii\web\ViewAction]], яке представлення запитане. Потім дія здійснює пошук
цього представлення в директорії `@app/views/site/pages`. Ви можете сконфігурувати [[yii\web\ViewAction::viewPrefix]],
щоб змінити директорію для пошуку цих представлень.