mirror of
				https://github.com/yiisoft/yii2.git
				synced 2025-11-01 03:26:36 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			724 lines
		
	
	
		
			51 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			724 lines
		
	
	
		
			51 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| Представлення
 | ||
| =============
 | ||
| 
 | ||
| Представлення є частиною архітектури [MVC](https://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>
 | ||
| 
 | ||
| <?php $form = ActiveForm::begin(); ?>
 | ||
|     <?= $form->field($model, 'username') ?>
 | ||
|     <?= $form->field($model, 'password')->passwordInput() ?>
 | ||
|     <?= Html::submitButton('Увійти') ?>
 | ||
| <?php ActiveForm::end(); ?>
 | ||
| ```
 | ||
| 
 | ||
| Всередині представлення ви можете використовувати `$this`, що відноситься до [[yii\web\View|компоненту представлення]], який забезпечує керування
 | ||
| цим шаблоном та його формування.
 | ||
| 
 | ||
| Окрім `$this`, у представленні можуть бути інші попередньо визначені змінні, такі як `$model` у прикладі
 | ||
| вище. Ці змінні представляють дані, які були *передані* у представлення через [контролери](structure-controllers.md)
 | ||
| або інші об’єкти, які спричинили [формування представлення](#rendering-views).
 | ||
| 
 | ||
| > Tip: Попередньо визначені змінні перелічені в блоці коментаря у початку представлення, так що вони можуть
 | ||
|   бути розпізнані в інтегрованих середовищах розробки (IDE). Це також є хорошим способом документування ваших представлень.
 | ||
| 
 | ||
| 
 | ||
| ### Безпека <span id="security"></span>
 | ||
| 
 | ||
| При створенні представлень, які генерують HTML-сторінки, важливо кодувати і/або фільтрувати дані, що надходять
 | ||
| від кінцевих користувачів, перед їх відображенням. В протилежному випадку ваш додаток може стати предметом
 | ||
| атак типу [міжсайтовий скриптінг (XSS)](https://uk.wikipedia.org/wiki/Міжсайтовий_скриптінг).
 | ||
| 
 | ||
| Для відображення звичайного тексту спершу закодуйте його за допомогою [[yii\helpers\Html::encode()]]. Наприклад, в наступному коді
 | ||
| перед відображенням кодується ім’я користувача:
 | ||
| 
 | ||
| ```php
 | ||
| <?php
 | ||
| use yii\helpers\Html;
 | ||
| ?>
 | ||
| 
 | ||
| <div class="username">
 | ||
|     <?= Html::encode($user->name) ?>
 | ||
| </div>
 | ||
| ```
 | ||
| 
 | ||
| Для відображення HTML-вмісту використовуйте [[yii\helpers\HtmlPurifier]], щоб відфільтрувати потенційно небезпечний вміст. Наприклад, в наступному
 | ||
| коді фільтрується вміст публікації перед відображенням:
 | ||
| 
 | ||
| ```php
 | ||
| <?php
 | ||
| use yii\helpers\HtmlPurifier;
 | ||
| ?>
 | ||
| 
 | ||
| <div class="post">
 | ||
|     <?= HtmlPurifier::process($post->text) ?>
 | ||
| </div>
 | ||
| ```
 | ||
| 
 | ||
| > Tip: В той час як HTMLPurifier бездоганно виконує роботу, щоб зробити вивід безпечним, він не є швидким. Вам потрібно розглянути
 | ||
|   можливість [кешування](caching-overview.md) результатів фільтрування, якщо ваш додаток потребує високої швидкодії.
 | ||
| 
 | ||
| 
 | ||
| ### Впорядкування представлень <span id="organizing-views"></span>
 | ||
| 
 | ||
| Подібно до [контролерів](structure-controllers.md) та [моделей](structure-models.md), існують домовленості щодо впорядкування представлень.
 | ||
| 
 | ||
| * Представлення, які формуються контролером, повинні бути розміщені в директорії `@app/views/ControllerID` за замовчуванням,
 | ||
|   де `ControllerID` відповідає [ідентифікатору контролера](structure-controllers.md#routes). Наприклад, для
 | ||
|   класу контролера `PostController` директорія повинна бути `@app/views/post`; для класу `PostCommentController`
 | ||
|   директорія повинна бути `@app/views/post-comment`. У випадку, коли контролер належить модулю, директорія
 | ||
|   повинна бути `views/ControllerID` у [[yii\base\Module::basePath|директорії модуля]].
 | ||
| * Представлення, які формуються у [віджетах](structure-widgets.md), повинні бути розміщені в директорії `WidgetPath/views` за
 | ||
|   замовчуванням, де `WidgetPath` означає шлях до директорії, в якій знаходиться файл класу віджету.
 | ||
| * Для представлень, які формуються іншими об’єктами, рекомендується виконувати домовленості подібно до віджетів.
 | ||
| 
 | ||
| Ви можете налаштувати ці типові директорії представлень, перевизначивши метод [[yii\base\ViewContextInterface::getViewPath()]]
 | ||
| контролерів або віджетів.
 | ||
| 
 | ||
| 
 | ||
| ## Формування представлень <span id="rendering-views"></span>
 | ||
| 
 | ||
| Ви можете формувати представлення в [контролерах](structure-controllers.md), [віджетах](structure-widgets.md) чи в будь-яких
 | ||
| інших місцях за допомогою виклику методів формування представлення. Усі ці методи мають подібну сигнатуру, що наведена нижче:
 | ||
| 
 | ||
| ```
 | ||
| /**
 | ||
|  * @param string $view ім’я представлення або шлях до файлу, в залежності від того, який метод формування використовується
 | ||
|  * @param array $params дані, які передаються представленню
 | ||
|  * @return string результат формування
 | ||
|  */
 | ||
| methodName($view, $params = [])
 | ||
| ```
 | ||
| 
 | ||
| 
 | ||
| ### Формування в контролерах <span id="rendering-in-controllers"></span>
 | ||
| 
 | ||
| Всередині [контролерів](structure-controllers.md), ви можете викликати наступні методи контролера для формування представлень:
 | ||
| 
 | ||
| * [[yii\base\Controller::render()|render()]]: формує [іменоване представлення](#named-views) та застосовує [макет](#layouts)
 | ||
|   до результату формування.
 | ||
| * [[yii\base\Controller::renderPartial()|renderPartial()]]: формує [іменоване представлення](#named-views) без будь-якого макету.
 | ||
| * [[yii\web\Controller::renderAjax()|renderAjax()]]: формує [іменоване представлення](#named-views) без будь-якого макету
 | ||
|   та включає усі зареєстровані скрипти і файли JS/CSS. Це зазвичай використовується у відповіді на веб-запити AJAX.
 | ||
| * [[yii\base\Controller::renderFile()|renderFile()]]: формує представлення визначене шляхом файлу представлення або
 | ||
|   [псевдонімом](concept-aliases.md).
 | ||
| * [[yii\base\Controller::renderContent()|renderContent()]]: формує статичний текстовий рядок, включаючи його в
 | ||
|   поточний застосовний [макет](#layouts). Цей метод доступний починаючи з версії 2.0.1.
 | ||
| 
 | ||
| Наприклад:
 | ||
| 
 | ||
| ```php
 | ||
| namespace app\controllers;
 | ||
| 
 | ||
| use Yii;
 | ||
| use app\models\Post;
 | ||
| use yii\web\Controller;
 | ||
| use yii\web\NotFoundHttpException;
 | ||
| 
 | ||
| class PostController extends Controller
 | ||
| {
 | ||
|     public function actionView($id)
 | ||
|     {
 | ||
|         $model = Post::findOne($id);
 | ||
|         if ($model === null) {
 | ||
|             throw new NotFoundHttpException;
 | ||
|         }
 | ||
| 
 | ||
|         // формує представлення з ім’ям "view" та застосовує макет до нього
 | ||
|         return $this->render('view', [
 | ||
|             'model' => $model,
 | ||
|         ]);
 | ||
|     }
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| 
 | ||
| ### Формування у віджетах <span id="rendering-in-widgets"></span>
 | ||
| 
 | ||
| Всередині [віджетів](structure-widgets.md), ви можете викликати наступні методи віджету для формування представлень.
 | ||
| 
 | ||
| * [[yii\base\Widget::render()|render()]]: формує [іменоване представлення](#named-views).
 | ||
| * [[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|компонентом представлення]]:
 | ||
| 
 | ||
| * [[yii\base\View::render()|render()]]: формує [іменоване представлення](#named-views).
 | ||
| * [[yii\web\View::renderAjax()|renderAjax()]]: формує [іменоване представлення](#named-views) та включає усі зареєстровані
 | ||
|   скрипти і файли JS/CSS. Це зазвичай використовується у відповіді на веб-запити AJAX.
 | ||
| * [[yii\base\View::renderFile()|renderFile()]]: формує представлення визначене шляхом файлу представлення або
 | ||
|   [псевдонімом](concept-aliases.md).
 | ||
| 
 | ||
| Наприклад, наступний код у представленні формує файл представлення `_overview.php`, який знаходиться в тій самій директорії,
 | ||
| що й представлення, яке зараз формується. Запам’ятайте, що `$this` у представленні відноситься до компонента [[yii\base\View|представлення]]:
 | ||
| 
 | ||
| ```php
 | ||
| <?= $this->render('_overview') ?>
 | ||
| ```
 | ||
| 
 | ||
| 
 | ||
| ### Формування в інших місцях <span id="rendering-in-other-places"></span>
 | ||
| 
 | ||
| В будь-якому місці ви можете отримати доступ до компонента додатка [[yii\base\View|представлення]] за допомогою виразу
 | ||
| `Yii::$app->view` та потім викликати його вищезгадані методи для формування представлення. Наприклад:
 | ||
| 
 | ||
| ```php
 | ||
| // відображає файл представлення "@app/views/site/license.php"
 | ||
| echo \Yii::$app->view->renderFile('@app/views/site/license.php');
 | ||
| ```
 | ||
| 
 | ||
| 
 | ||
| ### Іменовані представлення <span id="named-views"></span>
 | ||
| 
 | ||
| При формуванні представлення ви можете визначити його, використовуючи ім’я представлення або шлях/псевдонім до файлу представлення. У більшості випадків
 | ||
| ви будете використовувати перший варіант, тому що він більш лаконічний та гнучкий. Представлення, визначені за допомогою імен називаються *іменованими представленнями*.
 | ||
| 
 | ||
| Ім’я представлення перетворюється у відповідний шлях до файлу представлення за наступними правилами:
 | ||
| 
 | ||
| * Ім’я представлення можна вказувати без розширення імені файлу. У цьому випадку в якості розширення буде використовуватись `.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`, як, наприклад, ідентифікатору контролера, що наведений у прикладі:
 | ||
| 
 | ||
| ```php
 | ||
| Ідентифікатор контролера: <?= $this->context->id ?>
 | ||
| ```
 | ||
| 
 | ||
| Підхід "вштовхування" є бажанішим шляхом для доступу до даних у представленнях, тому що він робить представлення менш залежними
 | ||
| від об’єктів контексту, але його недоліком є необхідність весь час будувати масив даних вручну, що може
 | ||
| стати стомливим та збільшує вірогідність допустити помилку, якщо представлення використовується та формується у різних місцях.
 | ||
| 
 | ||
| 
 | ||
| ### Обмін даними між представленнями <span id="sharing-data-among-views"></span>
 | ||
| 
 | ||
| [[yii\base\View|Компонент представлення]] надає властивість [[yii\base\View::params|params]], яку можна використовувати
 | ||
| для обміну даними між представленнями.
 | ||
| 
 | ||
| Наприклад, в представленні `about`, ви можете мати наступний код, який визначає поточну частину
 | ||
| "хлібних крихт".
 | ||
| 
 | ||
| ```php
 | ||
| $this->params['breadcrumbs'][] = 'Про нас';
 | ||
| ```
 | ||
| 
 | ||
| Потім у файлі [макету](#layouts), який також є представленням, ви можете відобразити "хлібні крихти", використовуючи дані
 | ||
| передані через [[yii\base\View::params|params]]:
 | ||
| 
 | ||
| ```php
 | ||
| <?= yii\widgets\Breadcrumbs::widget([
 | ||
|     'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
 | ||
| ]) ?>
 | ||
| ```
 | ||
| 
 | ||
| 
 | ||
| ## Макети <span id="layouts"></span>
 | ||
| 
 | ||
| Макети - особливий тип представлень, які представляють спільні частини для інших представлень. Наприклад, сторінки
 | ||
| більшості веб-додатків мають однакові шапку та футер. Ви можете повторювати однакові шапку та футер сторінки
 | ||
| у кожному представленні, але краще зробити це один раз у макеті та розмістити результат формування вкладеного представлення
 | ||
| у відповідному місці макету.
 | ||
| 
 | ||
| 
 | ||
| ### Створення макетів <span id="creating-layouts"></span>
 | ||
| 
 | ||
| Оскільки макети є представленнями, вони можуть бути створенні тим самим шляхом, як і звичайні представлення. За замовчуванням, макети
 | ||
| зберігаються в директорії `@app/views/layouts`. Макети, які використовуються у [модулі](structure-modules.md),
 | ||
| повинні зберігатись в директорії `views/layouts` під [[yii\base\Module::basePath|директорією модуля]].
 | ||
| Ви можете налаштувати типову директорію для макетів сконфігурувавши властивість [[yii\base\Module::layoutPath]]
 | ||
| додатку або модулів.
 | ||
| 
 | ||
| Наступний приклад показує як виглядає макет. Майте на увазі, що для кращого сприйняття код у макеті дуже спрощений.
 | ||
| На практиці, ви можливо захочете додати більше вмісту до нього, такого як теги секції `<head>`, головне меню та інше.
 | ||
| 
 | ||
| ```php
 | ||
| <?php
 | ||
| use yii\helpers\Html;
 | ||
| 
 | ||
| /* @var $this yii\web\View */
 | ||
| /* @var $content string */
 | ||
| ?>
 | ||
| <?php $this->beginPage() ?>
 | ||
| <!DOCTYPE html>
 | ||
| <html lang="en">
 | ||
| <head>
 | ||
|     <meta charset="UTF-8"/>
 | ||
|     <?= Html::csrfMetaTags() ?>
 | ||
|     <title><?= Html::encode($this->title) ?></title>
 | ||
|     <?php $this->head() ?>
 | ||
| </head>
 | ||
| <body>
 | ||
| <?php $this->beginBody() ?>
 | ||
|     <header>Моя компанія</header>
 | ||
|     <?= $content ?>
 | ||
|     <footer>Моя компанія © 2014</footer>
 | ||
| <?php $this->endBody() ?>
 | ||
| </body>
 | ||
| </html>
 | ||
| <?php $this->endPage() ?>
 | ||
| ```
 | ||
| 
 | ||
| Як ви можете бачити, макет генерує 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`.
 | ||
| 
 | ||
| 
 | ||
| ### Вкладені макети <span id="nested-layouts"></span>
 | ||
| 
 | ||
| Іноді потрібно вкласти один макет в інший. Наприклад, у різних розділах веб-сайту ви
 | ||
| захочете використовувати різні макети, які мають однаковий базовий макет, що генерує загальну
 | ||
| структуру HTML5-сторінки. Це можна зробити за допомогою викликів [[yii\base\View::beginContent()|beginContent()]] та
 | ||
| [[yii\base\View::endContent()|endContent()]] в дочірніх макетах як наведено нижче:
 | ||
| 
 | ||
| ```php
 | ||
| <?php $this->beginContent('@app/views/layouts/base.php'); ?>
 | ||
| 
 | ||
| ...вміст дочірнього макету...
 | ||
| 
 | ||
| <?php $this->endContent(); ?>
 | ||
| ```
 | ||
| 
 | ||
| Як показано вище, вміст дочірнього макету повинен бути замкнений між [[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): дозволяє використовувати інші шаблонізатори, такі як
 | ||
|   [Twig](https://twig.symfony.com/), [Smarty](https://www.smarty.net/).
 | ||
| 
 | ||
| Ви також можете часто використовувати наступні другорядні, але корисні, можливості в процесі розробки веб-сторінок.
 | ||
| 
 | ||
| 
 | ||
| ### Встановлення заголовків сторінок <span id="setting-page-titles"></span>
 | ||
| 
 | ||
| Кожна веб-сторінка повинна мати заголовок. Звичайно тег заголовку виводиться в [макеті](#layouts). Однак, на практиці
 | ||
| заголовок часто визначається у вкладених представленнях, а не в макетах. Для вирішення цієї проблеми, компонент [[yii\web\View]] надає
 | ||
| властивість [[yii\web\View::title|title]], за допомогою якої можна передавати з вкладеного представлення до макетів інформацію заголовку.
 | ||
| 
 | ||
| Для використання цієї можливості, в кожному вкладеному представленні ви можете задати заголовок як наведено нижче:
 | ||
| 
 | ||
| ```php
 | ||
| <?php
 | ||
| $this->title = 'Мій заголовок сторінки';
 | ||
| ?>
 | ||
| ```
 | ||
| 
 | ||
| Потім переконайтесь, що маєте наступний код в секції `<head>` у макеті:
 | ||
| 
 | ||
| ```php
 | ||
| <title><?= Html::encode($this->title) ?></title>
 | ||
| ```
 | ||
| 
 | ||
| 
 | ||
| ### Реєстрація мета-тегів <span id="registering-meta-tags"></span>
 | ||
| 
 | ||
| Для веб-сторінок зазвичай потрібно генерувати різноманітні мета-теги, які мають різне цільове призначення. Подібно до заголовків сторінок, мета-теги
 | ||
| фігурують в секції `<head>` та зазвичай генеруються в макетах.
 | ||
| 
 | ||
| Якщо ви бажаєте визначити, які мета-теги генерувати у вкладених представленнях, ви можете викликати [[yii\web\View::registerMetaTag()]]
 | ||
| у вкладеному представленні, подібно до наведеного:
 | ||
| 
 | ||
| ```php
 | ||
| <?php
 | ||
| $this->registerMetaTag(['name' => 'keywords', 'content' => 'yii, framework, php']);
 | ||
| ?>
 | ||
| ```
 | ||
| 
 | ||
| В коді вище реєструється мета-тег "keywords" у компоненті представлення. Зареєстрований мета-тег
 | ||
| формується після закінчення формування макету. Наступний HTML-код буде згенеровано та вставлено
 | ||
| в місці, де ви викличете [[yii\web\View::head()]] у макеті:
 | ||
| 
 | ||
| ```php
 | ||
| <meta name="keywords" content="yii, framework, php">
 | ||
| ```
 | ||
| 
 | ||
| Зауважте, якщо викликати [[yii\web\View::registerMetaTag()]] декілька разів, в результаті цього зареєструється кілька мета-тегів,
 | ||
| не зважаючи на те, чи мета-теги однакові чи ні.
 | ||
| 
 | ||
| Щоб мати лише один екземпляр специфічного типу мета-тегу, потрібно визначати ключ в другому параметрі під час виклику методу.
 | ||
| Наприклад, наступний код реєструє два мета-теги "description". Однак, лише другий буде сформовано.
 | ||
| 
 | ||
| ```html
 | ||
| $this->registerMetaTag(['name' => 'description', 'content' => 'Це мій класний веб-сайт, який створено за допомогою Yii!'], 'description');
 | ||
| $this->registerMetaTag(['name' => 'description', 'content' => 'Цей веб-сайт про смішних єнотів.'], 'description');
 | ||
| ```
 | ||
| 
 | ||
| 
 | ||
| ### Реєстрація тегів 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' => 'https://www.yiiframework.com/rss.xml/',
 | ||
| ]);
 | ||
| ```
 | ||
| 
 | ||
| Результатом вищенаведеного коду буде
 | ||
| 
 | ||
| ```html
 | ||
| <link title="Свіжі новини про Yii" rel="alternate" type="application/rss+xml" href="https://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%2Fpage&view=about
 | ||
| ```
 | ||
| 
 | ||
| Параметр `view` із запиту `GET` вказує автономній дії [[yii\web\ViewAction]], яке представлення запитане. Потім дія здійснює пошук
 | ||
| цього представлення в директорії `@app/views/site/pages`. Ви можете сконфігурувати [[yii\web\ViewAction::viewPrefix]],
 | ||
| щоб змінити директорію для пошуку цих представлень.
 | ||
| 
 | ||
| 
 | ||
| ## Кращі практики <span id="best-practices"></span>
 | ||
| 
 | ||
| Представлення відповідають за репрезентацію моделей у форматі зрозумілому кінцевим користувачам. В цілому, представлення
 | ||
| 
 | ||
| * повинні здебільшого містити презентаційний код, такий як HTML та простий PHP-код для подання, форматування та формування даних;
 | ||
| * не повинні містити код, який виконує запити до БД. Такий код повинен бути в моделях;
 | ||
| * повинні уникати безпосереднього доступу до даних запиту, таких як `$_GET`, `$_POST`. Це обов’язок контролерів.
 | ||
|   У випадку необхідності дані запиту повинні бути передані в представлення через контролери;
 | ||
| * можуть читати властивості моделі, але не повинні змінювати їх.
 | ||
| 
 | ||
| Щоб зробити представлення більш контрольованими, уникайте створення представлень, які є дуже складними або містять забагато надлишкового коду.
 | ||
| Використовуйте наступні техніки, щоб досягнути цього:
 | ||
| 
 | ||
| * використовуйте [макети](#layouts) для відображення спільних презентаційних секцій (наприклад, шапка та футер сторінки);
 | ||
| * розділяйте складне представлення на декілька менших. Менші представлення можуть бути сформовані та складені у більше
 | ||
|   за допомогою методів формування описаних раніше у цьому розділі;
 | ||
| * створюйте та використовуйте [віджети](structure-widgets.md) як будівельні блоки представлень;
 | ||
| * створюйте та використовуйте класи-хелпери для перетворення та форматування даних у представленнях.
 | ||
| 
 | 
