Alexander Makarov
9 years ago
97 changed files with 2236 additions and 345 deletions
@ -0,0 +1,723 @@
|
||||
Представлення |
||||
============= |
||||
|
||||
Представлення є частиною архітектури [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> |
||||
|
||||
<?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). |
||||
|
||||
> Підказка: Попередньо визначені змінні перелічені в блоці коментаря у початку представлення, так що вони можуть |
||||
бути розпізнані в інтегрованих середовищах розробки (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> |
||||
``` |
||||
|
||||
> Підказка: В той час як 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](http://twig.sensiolabs.org/), [Smarty](http://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' => 'http://www.yiiframework.com/rss.xml/', |
||||
]); |
||||
``` |
||||
|
||||
Результатом вищенаведеного коду буде |
||||
|
||||
```html |
||||
<link title="Свіжі новини про 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]], |
||||
щоб змінити директорію для пошуку цих представлень. |
||||
|
||||
|
||||
## Кращі практики <span id="best-practices"></span> |
||||
|
||||
Представлення відповідають за репрезентацію моделей у форматі зрозумілому кінцевим користувачам. В цілому, представлення |
||||
|
||||
* повинні здебільшого містити презентаційний код, такий як HTML та простий PHP-код для подання, форматування та формування даних; |
||||
* не повинні містити код, який виконує запити до БД. Такий код повинен бути в моделях; |
||||
* повинні уникати безпосереднього доступу до даних запиту, таких як `$_GET`, `$_POST`. Це обов’язок контролерів. |
||||
У випадку необхідності дані запиту повинні бути передані в представлення через контролери; |
||||
* можуть читати властивості моделі, але не повинні змінювати їх. |
||||
|
||||
Щоб зробити представлення більш контрольованими, уникайте створення представлень, які є дуже складними або містять забагато надлишкового коду. |
||||
Використовуйте наступні техніки, щоб досягнути цього: |
||||
|
||||
* використовуйте [макети](#layouts) для відображення спільних презентаційних секцій (наприклад, шапка та футер сторінки); |
||||
* розділяйте складне представлення на декілька менших. Менші представлення можуть бути сформовані та складені у більше |
||||
за допомогою методів формування описаних раніше у цьому розділі; |
||||
* створюйте та використовуйте [віджети](structure-widgets.md) як будівельні блоки представлень; |
||||
* створюйте та використовуйте класи-хелпери для перетворення та форматування даних у представленнях. |
||||
|
@ -0,0 +1,66 @@
|
||||
<?php |
||||
|
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
use yii\base\InvalidConfigException; |
||||
use yii\caching\DbCache; |
||||
use yii\db\Migration; |
||||
|
||||
/** |
||||
* Initializes Cache tables |
||||
* |
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com> |
||||
* @since 2.0 |
||||
*/ |
||||
class m150909_153426_cache_init extends Migration |
||||
{ |
||||
|
||||
/** |
||||
* @throws yii\base\InvalidConfigException |
||||
* @return DbCache |
||||
*/ |
||||
protected function getCache() |
||||
{ |
||||
$cache = Yii::$app->getCache(); |
||||
if (!$cache instanceof DbCache) { |
||||
throw new InvalidConfigException('You should configure "cache" component to use database before executing this migration.'); |
||||
} |
||||
return $cache; |
||||
} |
||||
|
||||
/** |
||||
* @inheritdoc |
||||
*/ |
||||
public function up() |
||||
{ |
||||
$cache = $this->getCache(); |
||||
$this->db = $cache->db; |
||||
|
||||
$tableOptions = null; |
||||
if ($this->db->driverName === 'mysql') { |
||||
// http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci |
||||
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; |
||||
} |
||||
|
||||
$this->createTable($cache->cacheTable, [ |
||||
'id' => $this->string(128)->notNull(), |
||||
'expire' => $this->integer(), |
||||
'data' => $this->binary(), |
||||
'PRIMARY KEY ([[id]])', |
||||
], $tableOptions); |
||||
} |
||||
|
||||
/** |
||||
* @inheritdoc |
||||
*/ |
||||
public function down() |
||||
{ |
||||
$cache = $this->getCache(); |
||||
$this->db = $cache->db; |
||||
|
||||
$this->dropTable($cache->cacheTable); |
||||
} |
||||
} |
@ -0,0 +1,20 @@
|
||||
/** |
||||
* Database schema required by \yii\caching\DbCache. |
||||
* |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com> |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
* @since 2.0 |
||||
*/ |
||||
|
||||
drop table if exists [cache]; |
||||
|
||||
create table [cache] |
||||
( |
||||
[id] varchar(128) not null, |
||||
[expire] integer, |
||||
[data] BLOB, |
||||
primary key ([id]) |
||||
); |
@ -0,0 +1,20 @@
|
||||
/** |
||||
* Database schema required by \yii\caching\DbCache. |
||||
* |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com> |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
* @since 2.0 |
||||
*/ |
||||
|
||||
drop table if exists `cache`; |
||||
|
||||
create table `cache` |
||||
( |
||||
`id` varchar(128) not null, |
||||
`expire` integer, |
||||
`data` LONGBLOB, |
||||
primary key (`id`) |
||||
) engine InnoDB; |
@ -0,0 +1,20 @@
|
||||
/** |
||||
* Database schema required by \yii\caching\DbCache. |
||||
* |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com> |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
* @since 2.0 |
||||
*/ |
||||
|
||||
drop table if exists "cache"; |
||||
|
||||
create table "cache" |
||||
( |
||||
"id" varchar(128) not null, |
||||
"expire" integer, |
||||
"data" BYTEA, |
||||
primary key ("id") |
||||
); |
@ -0,0 +1,20 @@
|
||||
/** |
||||
* Database schema required by \yii\caching\DbCache. |
||||
* |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com> |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
* @since 2.0 |
||||
*/ |
||||
|
||||
drop table if exists "cache"; |
||||
|
||||
create table "cache" |
||||
( |
||||
"id" varchar(128) not null, |
||||
"expire" integer, |
||||
"data" BLOB, |
||||
primary key ("id") |
||||
); |
@ -0,0 +1,20 @@
|
||||
/** |
||||
* Database schema required by \yii\caching\DbCache. |
||||
* |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com> |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
* @since 2.0 |
||||
*/ |
||||
|
||||
drop table if exists "cache"; |
||||
|
||||
create table "cache" |
||||
( |
||||
"id" varchar(128) not null, |
||||
"expire" integer, |
||||
"data" BLOB, |
||||
primary key ("id") |
||||
); |
@ -0,0 +1,105 @@
|
||||
<?php |
||||
/** |
||||
* Message translations. |
||||
* |
||||
* This file is automatically generated by 'yii message' command. |
||||
* It contains the localizable messages extracted from source code. |
||||
* You may modify this file by translating the extracted messages. |
||||
* |
||||
* Each array element represents the translation (value) of a message (key). |
||||
* If the value is empty, the message is considered as not translated. |
||||
* Messages that no longer need translation will have their translations |
||||
* enclosed between a pair of '@@' marks. |
||||
* |
||||
* Message string can be used with plural forms format. Check i18n section |
||||
* of the guide for details. |
||||
* |
||||
* NOTE: this file must be saved in UTF-8 encoding. |
||||
*/ |
||||
return [ |
||||
'(not set)' => '(nije postavljeno)', |
||||
'An internal server error occurred.' => 'Došlo je to interne pogreške servera.', |
||||
'Are you sure you want to delete this item' => 'Želiš li to obrisati?', |
||||
'Delete' => 'Obrisati', |
||||
'Error' => 'Pogreška', |
||||
'File upload failed.' => 'Upload podatka nije uspio.', |
||||
'Home' => 'Home', |
||||
'Invalid data received for parameter "{param}".' => 'Nevažeći podaci primljeni za parametar "{param}"', |
||||
'Login Required' => 'Prijava potrebna', |
||||
'Missing required arguments: {params}' => 'Nedostaju potrebni argunenti: {params}', |
||||
'Missing required parameters: {params}' => 'Falten paràmetres requerits: {params}', |
||||
'No' => 'Ne', |
||||
'No help for unknown command "{command}".' => 'Nema pomoći za nepoznatu naredbu "{command}"', |
||||
'No help for unknown sub-command "{command}".' => 'Nema pomoći za nepoznatu pod-naredbu "{command}"', |
||||
'No results found.' => 'Nema rezultata.', |
||||
'Only files with these MIME types are allowed: {mimeTypes}.' => 'Samo datoteke s ovim MIME vrstama su dopuštene: {mimeTypes}.', |
||||
'Only files with these extensions are allowed: {extensions}.' => 'Samo datoteke s ovim eksentinzijama su dopuštene:: {extensions}', |
||||
'Page not found.' => 'Stranica nije pronađena.', |
||||
'Please fix the following errors:' => 'Molimo vas ispravite pogreške:', |
||||
'Please upload a file.' => 'Molimo vas da uploadate datoteku.', |
||||
'Showing <b>{begin, number}-{end, number}</b> of <b>{totalCount, number}</b> {totalCount, plural, one{item} other{items}}.' => 'Prikazuj <b>{begin, number}-{end, number}</b> od <b>{totalCount, number}</b> {totalCount, plural, one{red} other{redova}}.', |
||||
'The file "{file}" is not an image.' => 'Podatak "{file}" nije slika.', |
||||
'The file "{file}" is too big. Its size cannot exceed {limit, number} {limit, plural, one{byte} other{bytes}}.' => 'Podatak "{file}" je prevelik.Nesmije biti veči od {limit, number} {limit, plural, one{byte} other{bytes}}.', |
||||
'The file "{file}" is too small. Its size cannot be smaller than {limit, number} {limit, plural, one{byte} other{bytes}}.' => 'Podatak "{file}" je premalen. Nesmije biti manji od {limit, number} {limit, plural, one{byte} other{bytes}}.', |
||||
'The format of {attribute} is invalid.' => 'Format od {attribute} je nevažeći.', |
||||
'The image "{file}" is too large. The height cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Slika "{file}" je prevelika. Visina slike nesmije biti veča od {limit, number} {limit, plural, one{piksel} other{piksela}}.', |
||||
'The image "{file}" is too large. The width cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Slika "{file}" je prevelika. Širina slike nesmije biti veča od {limit, number} {limit, plural, one{piksel} other{piksela}}.', |
||||
'The image "{file}" is too small. The height cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Slika "{file}" je premalena. Visina slike nesmije biti manja od {limit, number} {limit, plural, one{piksel} other{piksela}}.', |
||||
'The image "{file}" is too small. The width cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Slika "{file}" je premalena. Širina slike nesmije biti manja od {limit, number} {limit, plural, one{piksel} other{piksela}}.', |
||||
'The verification code is incorrect.' => 'Kod za provjeru nije točan.', |
||||
'Total <b>{count, number}</b> {count, plural, one{item} other{items}}.' => 'Ukupni <b>{count, number}</b> {count, plural, one{red} other{redova}}.', |
||||
'Unable to verify your data submission.' => 'Nije moguće provjeriti podnesene podatke.', |
||||
'Unknown command "{command}".' => 'Nepoznata naredba "{command}".', |
||||
'Unknown option: --{name}' => 'Nepoznata opcija: --{name}', |
||||
'Update' => 'Actualitzar', |
||||
'View' => 'Pregled', |
||||
'Yes' => 'Da', |
||||
'You are not allowed to perform this action.' => 'Nije vam dopušteno obavljati tu radnju.', |
||||
'You can upload at most {limit, number} {limit, plural, one{file} other{files}}.' => 'Najviše možete uploadat {limit, number} {limit, plural, one{arxiu} other{arxius}}.', |
||||
'in {delta, plural, =1{a day} other{# days}}' => 'u {delta, plural, =1{un dia} other{# dies}}', |
||||
'in {delta, plural, =1{a minute} other{# minutes}}' => 'u {delta, plural, =1{un minut} other{# minuts}}', |
||||
'in {delta, plural, =1{a month} other{# months}}' => 'u {delta, plural, =1{un mes} other{# mesos}}', |
||||
'in {delta, plural, =1{a second} other{# seconds}}' => 'u {delta, plural, =1{un segon} other{# segons}}', |
||||
'in {delta, plural, =1{a year} other{# years}}' => 'u {delta, plural, =1{un any} other{# anys}}', |
||||
'in {delta, plural, =1{an hour} other{# hours}}' => 'u {delta, plural, =1{una hora} other{# hores}}', |
||||
'the input value' => 'ulazna vrijednost', |
||||
'{attribute} "{value}" has already been taken.' => '{attribute} "{value}" već se koristi.', |
||||
'{attribute} cannot be blank.' => '{attribute} nesmije biti prazno.', |
||||
'{attribute} is invalid.' => '{attribute} je neispravan.', |
||||
'{attribute} is not a valid URL.' => '{attribute} nije valjan URL.', |
||||
'{attribute} is not a valid email address.' => '{attribute} nije valjana email adresa.', |
||||
'{attribute} must be "{requiredValue}".' => '{attribute} mora biti "{requiredValue}".', |
||||
'{attribute} must be a number.' => '{attribute} mora biti broj.', |
||||
'{attribute} must be a string.' => '{attribute} mora biti string(riječ,tekst).', |
||||
'{attribute} must be an integer.' => '{attribute} mora biti cijeli broj.', |
||||
'{attribute} must be either "{true}" or "{false}".' => '{attribute} mora biti "{true}" ili "{false}".', |
||||
'{attribute} must be greater than "{compareValue}".' => '{attribute} mora biti veči od "{compareValue}', |
||||
'{attribute} must be greater than or equal to "{compareValue}".' => '{attribute} mora biti veči ili jednak "{compareValue}".', |
||||
'{attribute} must be less than "{compareValue}".' => '{attribute} mora biti manji od "{compareValue}".', |
||||
'{attribute} must be less than or equal to "{compareValue}".' => '{attribute} mora biti jednak "{compareValue}".', |
||||
'{attribute} must be no greater than {max}.' => '{attribute} nesmije biti veči od {max}.', |
||||
'{attribute} must be no less than {min}.' => '{attribute} nesmije biti manji od {min}.', |
||||
'{attribute} must be repeated exactly.' => '{attribute} mora biti ponovljeno.', |
||||
'{attribute} must not be equal to "{compareValue}".' => '{attribute} nesmije biti jednnak "{compareValue}".', |
||||
'{attribute} should contain at least {min, number} {min, plural, one{character} other{characters}}.' => '{attribute} mora najmanje sadržavati {min, number} {min, plural, one{znak} other{znakova}}.', |
||||
'{attribute} should contain at most {max, number} {max, plural, one{character} other{characters}}.' => '{attribute} moze sadržavati do {max, number} {max, plural, one{znak} other{znakova}}.', |
||||
'{attribute} should contain {length, number} {length, plural, one{character} other{characters}}.' => '{attribute} mora sadržavati {length, number} {length, plural, one{znak} other{znakova}}.', |
||||
'{delta, plural, =1{a day} other{# days}} ago' => '{delta, plural, =1{dan} other{# dana}}', |
||||
'{delta, plural, =1{a minute} other{# minutes}} ago' => '{delta, plural, =1{minuta} other{# minuta}}', |
||||
'{delta, plural, =1{a month} other{# months}} ago' => '{delta, plural, =1{mjesec} other{# mjeseci}}', |
||||
'{delta, plural, =1{a second} other{# seconds}} ago' => '{delta, plural, =1{sekunda} other{# sekundi}}', |
||||
'{delta, plural, =1{a year} other{# years}} ago' => '{delta, plural, =1{un godine} other{# godina}}', |
||||
'{delta, plural, =1{an hour} other{# hours}} ago' => ' {delta, plural, =1{sat} other{# sati}}', |
||||
'{n, plural, =1{# byte} other{# bytes}}' => '{n, plural, =1{# byte} other{# bytes}}', |
||||
'{n, plural, =1{# gigabyte} other{# gigabytes}}' => '{n, plural, =1{# gigabyte} other{# gigabytes}}', |
||||
'{n, plural, =1{# kilobyte} other{# kilobytes}}' => '{n, plural, =1{# kilobyte} other{# kilobytes}}', |
||||
'{n, plural, =1{# megabyte} other{# megabytes}}' => '{n, plural, =1{# megabyte} other{# megabytes}}', |
||||
'{n, plural, =1{# petabyte} other{# petabytes}}' => '{n, plural, =1{# petabyte} other{# petabytes}}', |
||||
'{n, plural, =1{# terabyte} other{# terabytes}}' => '{n, plural, =1{# terabyte} other{# terabytes}}', |
||||
'{n} B' => '{n} B', |
||||
'{n} GB' => '{n} GB', |
||||
'{n} KB' => '{n} KB', |
||||
'{n} MB' => '{n} MB', |
||||
'{n} PB' => '{n} PB', |
||||
'{n} TB' => '{n} TB', |
||||
]; |
@ -0,0 +1,35 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
namespace yii\web; |
||||
|
||||
/** |
||||
* UnprocessableEntityHttpException represents an "Unprocessable Entity" HTTP |
||||
* exception with status code 422. |
||||
* |
||||
* Use this exception to inform that the server understands the content type of |
||||
* the request entity and the syntax of that request entity is correct but the server |
||||
* was unable to process the contained instructions. For example, to return form |
||||
* validation errors. |
||||
* |
||||
* @link http://www.webdav.org/specs/rfc2518.html#STATUS_422 |
||||
* @author Jan Silva <janfrs3@gmail.com> |
||||
* @since 2.0.7 |
||||
*/ |
||||
class UnprocessableEntityHttpException extends HttpException |
||||
{ |
||||
/** |
||||
* Constructor. |
||||
* @param string $message error message |
||||
* @param integer $code error code |
||||
* @param \Exception $previous The previous exception used for the exception chaining. |
||||
*/ |
||||
public function __construct($message = null, $code = 0, \Exception $previous = null) |
||||
{ |
||||
parent::__construct(422, $message, $code, $previous); |
||||
} |
||||
} |
@ -0,0 +1,86 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
namespace yiiunit\framework\console; |
||||
|
||||
use Yii; |
||||
use yiiunit\TestCase; |
||||
use yiiunit\framework\di\stubs\Qux; |
||||
use yiiunit\framework\web\stubs\Bar; |
||||
use yiiunit\framework\web\stubs\OtherQux; |
||||
|
||||
/** |
||||
* @group console |
||||
*/ |
||||
class ControllerTest extends TestCase |
||||
{ |
||||
|
||||
public function testBindActionParams() |
||||
{ |
||||
$this->mockApplication([ |
||||
'components' => [ |
||||
'barBelongApp' => [ |
||||
'class' => Bar::className(), |
||||
'foo' => 'belong_app' |
||||
], |
||||
'quxApp' => [ |
||||
'class' => OtherQux::className(), |
||||
'b' => 'belong_app' |
||||
] |
||||
] |
||||
]); |
||||
|
||||
$controller = new FakeController('fake', Yii::$app); |
||||
|
||||
Yii::$container->set('yiiunit\framework\di\stubs\QuxInterface', [ |
||||
'class' => Qux::className(), |
||||
'a' => 'D426' |
||||
]); |
||||
Yii::$container->set(Bar::className(), [ |
||||
'foo' => 'independent' |
||||
]); |
||||
|
||||
$params = ['from params']; |
||||
list($bar, $fromParam, $other) = $controller->run('aksi1', $params); |
||||
$this->assertTrue($bar instanceof Bar); |
||||
$this->assertNotEquals($bar, Yii::$app->barBelongApp); |
||||
$this->assertEquals('independent', $bar->foo); |
||||
$this->assertEquals('from params', $fromParam); |
||||
$this->assertEquals('default', $other); |
||||
|
||||
$params = []; |
||||
list($barBelongApp, $qux) = $controller->run('aksi2', $params); |
||||
$this->assertTrue($barBelongApp instanceof Bar); |
||||
$this->assertEquals($barBelongApp, Yii::$app->barBelongApp); |
||||
$this->assertEquals('belong_app', $barBelongApp->foo); |
||||
$this->assertTrue($qux instanceof Qux); |
||||
$this->assertEquals('D426', $qux->a); |
||||
|
||||
$params = []; |
||||
list($quxApp) = $controller->run('aksi3', $params); |
||||
$this->assertTrue($quxApp instanceof OtherQux); |
||||
$this->assertEquals($quxApp, Yii::$app->quxApp); |
||||
$this->assertEquals('belong_app', $quxApp->b); |
||||
|
||||
$params = ['d426,mdmunir', 'single']; |
||||
$result = $controller->runAction('aksi4', $params); |
||||
$this->assertEquals(['independent', 'other_qux', ['d426', 'mdmunir'], 'single'], $result); |
||||
|
||||
$params = ['d426']; |
||||
$result = $controller->runAction('aksi5', $params); |
||||
$this->assertEquals(['d426', 'independent', 'other_qux'], $result); |
||||
|
||||
$params = ['mdmunir']; |
||||
$result = $controller->runAction('aksi6', $params); |
||||
$this->assertEquals(['mdmunir', false, true], $result); |
||||
|
||||
$params = ['avaliable']; |
||||
$message = Yii::t('yii', 'Missing required arguments: {params}', ['params' => implode(', ', ['missing'])]); |
||||
$this->setExpectedException('yii\console\Exception', $message); |
||||
$result = $controller->runAction('aksi7', $params); |
||||
} |
||||
} |
@ -0,0 +1,56 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
namespace yiiunit\framework\console; |
||||
|
||||
use yii\console\Controller; |
||||
use yiiunit\framework\di\stubs\QuxInterface; |
||||
use yiiunit\framework\web\stubs\Bar; |
||||
use yii\validators\EmailValidator; |
||||
|
||||
/** |
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com> |
||||
* @since 2.0 |
||||
*/ |
||||
class FakeController extends Controller |
||||
{ |
||||
|
||||
public function actionAksi1(Bar $bar, $fromParam, $other = 'default') |
||||
{ |
||||
return[$bar, $fromParam, $other]; |
||||
} |
||||
|
||||
public function actionAksi2(Bar $barBelongApp, QuxInterface $qux) |
||||
{ |
||||
return[$barBelongApp, $qux]; |
||||
} |
||||
|
||||
public function actionAksi3(QuxInterface $quxApp) |
||||
{ |
||||
return[$quxApp]; |
||||
} |
||||
|
||||
public function actionAksi4(Bar $bar, QuxInterface $quxApp, array $values, $value) |
||||
{ |
||||
return [$bar->foo, $quxApp->quxMethod(), $values, $value]; |
||||
} |
||||
|
||||
public function actionAksi5($q, Bar $bar, QuxInterface $quxApp) |
||||
{ |
||||
return [$q, $bar->foo, $quxApp->quxMethod()]; |
||||
} |
||||
|
||||
public function actionAksi6($q, EmailValidator $validator) |
||||
{ |
||||
return [$q, $validator->validate($q), $validator->validate('misbahuldmunir@gmail.com')]; |
||||
} |
||||
|
||||
public function actionAksi7(Bar $bar, $avaliable, $missing) |
||||
{ |
||||
|
||||
} |
||||
} |
@ -0,0 +1,81 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
namespace yiiunit\framework\web; |
||||
|
||||
use Yii; |
||||
use yiiunit\TestCase; |
||||
use yiiunit\framework\di\stubs\Qux; |
||||
use yiiunit\framework\web\stubs\Bar; |
||||
use yiiunit\framework\web\stubs\OtherQux; |
||||
use yii\base\InlineAction; |
||||
|
||||
/** |
||||
* @group web |
||||
*/ |
||||
class ControllerTest extends TestCase |
||||
{ |
||||
|
||||
public function testBindActionParams() |
||||
{ |
||||
$this->mockApplication([ |
||||
'components'=>[ |
||||
'barBelongApp'=>[ |
||||
'class'=> Bar::className(), |
||||
'foo'=>'belong_app' |
||||
], |
||||
'quxApp'=>[ |
||||
'class' => OtherQux::className(), |
||||
'b' => 'belong_app' |
||||
] |
||||
] |
||||
]); |
||||
|
||||
$controller = new FakeController('fake', Yii::$app); |
||||
$aksi1 = new InlineAction('aksi1', $controller, 'actionAksi1'); |
||||
$aksi2 = new InlineAction('aksi2', $controller, 'actionAksi2'); |
||||
$aksi3 = new InlineAction('aksi3', $controller, 'actionAksi3'); |
||||
|
||||
Yii::$container->set('yiiunit\framework\di\stubs\QuxInterface', [ |
||||
'class' => Qux::className(), |
||||
'a' => 'D426' |
||||
]); |
||||
Yii::$container->set(Bar::className(),[ |
||||
'foo' => 'independent' |
||||
]); |
||||
|
||||
$params = ['fromGet'=>'from query params','q'=>'d426','validator'=>'avaliable']; |
||||
|
||||
list($bar, $fromGet, $other) = $controller->bindActionParams($aksi1, $params); |
||||
$this->assertTrue($bar instanceof Bar); |
||||
$this->assertNotEquals($bar, Yii::$app->barBelongApp); |
||||
$this->assertEquals('independent', $bar->foo); |
||||
$this->assertEquals('from query params', $fromGet); |
||||
$this->assertEquals('default', $other); |
||||
|
||||
list($barBelongApp, $qux) = $controller->bindActionParams($aksi2, $params); |
||||
$this->assertTrue($barBelongApp instanceof Bar); |
||||
$this->assertEquals($barBelongApp, Yii::$app->barBelongApp); |
||||
$this->assertEquals('belong_app', $barBelongApp->foo); |
||||
$this->assertTrue($qux instanceof Qux); |
||||
$this->assertEquals('D426', $qux->a); |
||||
|
||||
list($quxApp) = $controller->bindActionParams($aksi3, $params); |
||||
$this->assertTrue($quxApp instanceof OtherQux); |
||||
$this->assertEquals($quxApp, Yii::$app->quxApp); |
||||
$this->assertEquals('belong_app', $quxApp->b); |
||||
|
||||
$result = $controller->runAction('aksi4', $params); |
||||
$this->assertEquals(['independent', 'other_qux', 'd426'], $result); |
||||
|
||||
$result = $controller->runAction('aksi5', $params); |
||||
$this->assertEquals(['d426', 'independent', 'other_qux'], $result); |
||||
|
||||
$result = $controller->runAction('aksi6', $params); |
||||
$this->assertEquals(['d426', false, true], $result); |
||||
} |
||||
} |
@ -0,0 +1,49 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
namespace yiiunit\framework\web; |
||||
|
||||
use yii\web\Controller; |
||||
use yiiunit\framework\di\stubs\QuxInterface; |
||||
use yiiunit\framework\web\stubs\Bar; |
||||
use yii\validators\EmailValidator; |
||||
|
||||
/** |
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com> |
||||
* @since 2.0 |
||||
*/ |
||||
class FakeController extends Controller |
||||
{ |
||||
public $enableCsrfValidation = false; |
||||
|
||||
public function actionAksi1(Bar $bar, $fromGet, $other = 'default') |
||||
{ |
||||
} |
||||
|
||||
public function actionAksi2(Bar $barBelongApp, QuxInterface $qux) |
||||
{ |
||||
} |
||||
|
||||
public function actionAksi3(QuxInterface $quxApp) |
||||
{ |
||||
} |
||||
|
||||
public function actionAksi4(Bar $bar, QuxInterface $quxApp, $q) |
||||
{ |
||||
return [$bar->foo, $quxApp->quxMethod(), $q]; |
||||
} |
||||
|
||||
public function actionAksi5($q, Bar $bar, QuxInterface $quxApp) |
||||
{ |
||||
return [$q, $bar->foo, $quxApp->quxMethod()]; |
||||
} |
||||
|
||||
public function actionAksi6($q, EmailValidator $validator) |
||||
{ |
||||
return [$q, $validator->validate($q), $validator->validate('misbahuldmunir@gmail.com')]; |
||||
} |
||||
} |
@ -0,0 +1,19 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
namespace yiiunit\framework\web\stubs; |
||||
|
||||
use yii\base\Object; |
||||
|
||||
/** |
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com> |
||||
* @since 2.0 |
||||
*/ |
||||
class Bar extends Object |
||||
{ |
||||
public $foo; |
||||
} |
@ -0,0 +1,24 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
namespace yiiunit\framework\web\stubs; |
||||
|
||||
use yii\base\Object; |
||||
use yiiunit\framework\di\stubs\QuxInterface; |
||||
|
||||
/** |
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com> |
||||
* @since 2.0 |
||||
*/ |
||||
class OtherQux extends Object implements QuxInterface |
||||
{ |
||||
public $b; |
||||
public function quxMethod() |
||||
{ |
||||
return 'other_qux'; |
||||
} |
||||
} |
Loading…
Reference in new issue