You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
464 lines
17 KiB
464 lines
17 KiB
11 years ago
|
View
|
||
|
====
|
||
|
|
||
11 years ago
|
The view component is an important part of MVC. The view acts as the interface to the application, making it responsible
|
||
|
for presenting data to end users, displaying forms, and so forth.
|
||
11 years ago
|
|
||
11 years ago
|
|
||
|
Basics
|
||
|
------
|
||
|
|
||
11 years ago
|
By default, Yii uses PHP in view templates to generate content and elements. A web application view typically contains
|
||
|
some combination of HTML, along with PHP `echo`, `foreach`, `if`, and other basic constructs.
|
||
|
Using complex PHP code in views is considered to be bad practice. When complex logic and functionality is needed,
|
||
|
such code should either be moved to a controller or a widget.
|
||
11 years ago
|
|
||
11 years ago
|
The view is typically called from controller action using the [[yii\base\Controller::render()|render()]] method:
|
||
11 years ago
|
|
||
|
```php
|
||
|
public function actionIndex()
|
||
|
{
|
||
11 years ago
|
return $this->render('index', ['username' => 'samdark']);
|
||
11 years ago
|
}
|
||
|
```
|
||
|
|
||
11 years ago
|
The first argument to [[yii\base\Controller::render()|render()]] is the name of the view to display.
|
||
|
In the context of the controller, Yii will search for its views in `views/site/` where `site`
|
||
11 years ago
|
is the controller ID. For details on how the view name is resolved, refer to the [[yii\base\Controller::render()]] method.
|
||
11 years ago
|
|
||
11 years ago
|
The second argument to [[yii\base\Controller::render()|render()]] is a data array of key-value pairs.
|
||
|
Through this array, data can be passed to the view, making the value available in the view as a variable
|
||
|
named the same as the corresponding key.
|
||
11 years ago
|
|
||
|
The view for the action above would be `views/site/index.php` and can be something like:
|
||
11 years ago
|
|
||
|
```php
|
||
11 years ago
|
<p>Hello, <?= $username ?>!</p>
|
||
11 years ago
|
```
|
||
|
|
||
11 years ago
|
Any data type can be passed to the view, including arrays or objects.
|
||
11 years ago
|
|
||
11 years ago
|
Besides the above [[yii\web\Controller::render()|render()]] method, the [[yii\web\Controller]] class also provides
|
||
|
several other rendering methods. Below is a summary of these methods:
|
||
|
|
||
|
* [[yii\web\Controller::render()|render()]]: renders a view and applies the layout to the rendering result.
|
||
|
This is most commonly used to render a complete page.
|
||
|
* [[yii\web\Controller::renderPartial()|renderPartial()]]: renders a view without applying any layout.
|
||
|
This is often used to render a fragment of a page.
|
||
|
* [[yii\web\Controller::renderAjax()|renderAjax()]]: renders a view without applying any layout, and injects all
|
||
|
registered JS/CSS scripts and files. It is most commonly used to render an HTML output to respond to an AJAX request.
|
||
|
* [[yii\web\Controller::renderFile()|renderFile()]]: renders a view file. This is similar to
|
||
|
[[yii\web\Controller::renderPartial()|renderPartial()]] except that it takes the file path
|
||
11 years ago
|
of the view instead of the view name.
|
||
|
|
||
|
|
||
11 years ago
|
Widgets
|
||
|
-------
|
||
|
|
||
11 years ago
|
Widgets are self-contained building blocks for your views, a way to combine complex logic, display, and functionality into a single component. A widget:
|
||
|
|
||
|
* May contain advanced PHP programming
|
||
|
* Is typically configurable
|
||
|
* Is often provided data to be displayed
|
||
|
* Returns HTML to be shown within the context of the view
|
||
|
|
||
|
There are a good number of widgets bundled with Yii, such as [active form](form.md),
|
||
11 years ago
|
breadcrumbs, menu, and [wrappers around bootstrap component framework](bootstrap-widgets.md). Additionally there are
|
||
11 years ago
|
extensions that provide more widgets, such as the official widget for [jQueryUI](http://www.jqueryui.com) components.
|
||
11 years ago
|
|
||
11 years ago
|
In order to use a widget, your view file would do the following:
|
||
11 years ago
|
|
||
|
```php
|
||
|
// Note that you have to "echo" the result to display it
|
||
11 years ago
|
echo \yii\widgets\Menu::widget(['items' => $items]);
|
||
11 years ago
|
|
||
|
// Passing an array to initialize the object properties
|
||
11 years ago
|
$form = \yii\widgets\ActiveForm::begin([
|
||
11 years ago
|
'options' => ['class' => 'form-horizontal'],
|
||
|
'fieldConfig' => ['inputOptions' => ['class' => 'input-xlarge']],
|
||
11 years ago
|
]);
|
||
11 years ago
|
... form inputs here ...
|
||
|
\yii\widgets\ActiveForm::end();
|
||
|
```
|
||
|
|
||
11 years ago
|
In the first example in the code above, the [[yii\base\Widget::widget()|widget()]] method is used to invoke a widget
|
||
|
that just outputs content. In the second example, [[yii\base\Widget::begin()|begin()]] and [[yii\base\Widget::end()|end()]]
|
||
|
are used for a
|
||
11 years ago
|
widget that wraps content between method calls with its own output. In case of the form this output is the `<form>` tag
|
||
|
with some properties set.
|
||
|
|
||
11 years ago
|
|
||
11 years ago
|
Security
|
||
|
--------
|
||
|
|
||
|
One of the main security principles is to always escape output. If violated it leads to script execution and,
|
||
|
most probably, to cross-site scripting known as XSS leading to leaking of admin passwords, making a user to automatically
|
||
|
perform actions etc.
|
||
|
|
||
11 years ago
|
Yii provides a good tool set in order to help you escape your output. The very basic thing to escape is a text without any
|
||
11 years ago
|
markup. You can deal with it like the following:
|
||
|
|
||
|
```php
|
||
|
<?php
|
||
|
use yii\helpers\Html;
|
||
|
?>
|
||
|
|
||
|
<div class="username">
|
||
11 years ago
|
<?= Html::encode($user->name) ?>
|
||
11 years ago
|
</div>
|
||
|
```
|
||
|
|
||
|
When you want to render HTML it becomes complex so we're delegating the task to excellent
|
||
11 years ago
|
[HTMLPurifier](http://htmlpurifier.org/) library which is wrapped in Yii as a helper [[yii\helpers\HtmlPurifier]]:
|
||
11 years ago
|
|
||
|
```php
|
||
|
<?php
|
||
|
use yii\helpers\HtmlPurifier;
|
||
|
?>
|
||
|
|
||
|
<div class="post">
|
||
11 years ago
|
<?= HtmlPurifier::process($post->text) ?>
|
||
11 years ago
|
</div>
|
||
|
```
|
||
|
|
||
|
Note that besides HTMLPurifier does excellent job making output safe it's not very fast so consider
|
||
|
[caching result](caching.md).
|
||
|
|
||
|
Alternative template languages
|
||
|
------------------------------
|
||
|
|
||
11 years ago
|
There are official extensions for [Smarty](http://www.smarty.net/) and [Twig](http://twig.sensiolabs.org/). In order
|
||
11 years ago
|
to learn more refer to [Using template engines](template.md) section of the guide.
|
||
11 years ago
|
|
||
11 years ago
|
Using View object in templates
|
||
|
------------------------------
|
||
11 years ago
|
|
||
11 years ago
|
An instance of [[yii\web\View]] component is available in view templates as `$this` variable. Using it in templates you
|
||
11 years ago
|
can do many useful things including setting page title and meta, registering scripts and accessing the context.
|
||
11 years ago
|
|
||
|
### Setting page title
|
||
|
|
||
|
A common place to set page title are view templates. Since we can access view object with `$this`, setting a title
|
||
|
becomes as easy as:
|
||
|
|
||
|
```php
|
||
|
$this->title = 'My page title';
|
||
|
```
|
||
|
|
||
|
### Adding meta tags
|
||
|
|
||
11 years ago
|
Adding meta tags such as encoding, description, keywords is easy with view object as well:
|
||
11 years ago
|
|
||
|
```php
|
||
11 years ago
|
$this->registerMetaTag(['encoding' => 'utf-8']);
|
||
11 years ago
|
```
|
||
|
|
||
|
The first argument is an map of `<meta>` tag option names and values. The code above will produce:
|
||
|
|
||
|
```html
|
||
|
<meta encoding="utf-8">
|
||
|
```
|
||
|
|
||
|
Sometimes there's a need to have only a single tag of a type. In this case you need to specify the second argument:
|
||
|
|
||
|
```html
|
||
11 years ago
|
$this->registerMetaTag(['name' => 'description', 'content' => 'This is my cool website made with Yii!'], 'meta-description');
|
||
|
$this->registerMetaTag(['name' => 'description', 'content' => 'This website is about funny raccoons.'], 'meta-description');
|
||
11 years ago
|
```
|
||
|
|
||
11 years ago
|
If there are multiple calls with the same value of the second argument (`meta-description` in this case), the latter will
|
||
11 years ago
|
override the former and only a single tag will be rendered:
|
||
11 years ago
|
|
||
|
```html
|
||
11 years ago
|
<meta name="description" content="This website is about funny raccoons.">
|
||
11 years ago
|
```
|
||
|
|
||
|
### Registering link tags
|
||
|
|
||
11 years ago
|
`<link>` tag is useful in many cases such as customizing favicon, pointing to RSS feed or delegating OpenID to another
|
||
11 years ago
|
server. Yii view object has a method to work with these:
|
||
|
|
||
|
```php
|
||
11 years ago
|
$this->registerLinkTag([
|
||
11 years ago
|
'title' => 'Lives News for Yii Framework',
|
||
|
'rel' => 'alternate',
|
||
|
'type' => 'application/rss+xml',
|
||
|
'href' => 'http://www.yiiframework.com/rss.xml/',
|
||
11 years ago
|
]);
|
||
11 years ago
|
```
|
||
|
|
||
|
The code above will result in
|
||
|
|
||
|
```html
|
||
|
<link title="Lives News for Yii Framework" rel="alternate" type="application/rss+xml" href="http://www.yiiframework.com/rss.xml/" />
|
||
|
```
|
||
|
|
||
|
Same as with meta tags you can specify additional argument to make sure there's only one link of a type registered.
|
||
|
|
||
|
### Registering CSS
|
||
|
|
||
11 years ago
|
You can register CSS using [[yii\web\View::registerCss()|registerCss()]] or [[yii\web\View::registerCssFile()|registerCssFile()]].
|
||
|
The former registers a block of CSS code while the latter registers an external CSS file. For example,
|
||
11 years ago
|
|
||
|
```php
|
||
|
$this->registerCss("body { background: #f00; }");
|
||
|
```
|
||
|
|
||
|
The code above will result in adding the following to the head section of the page:
|
||
|
|
||
|
```html
|
||
|
<style>
|
||
|
body { background: #f00; }
|
||
|
</style>
|
||
|
```
|
||
|
|
||
11 years ago
|
If you want to specify additional properties of the style tag, pass an array of name-values to the third argument.
|
||
11 years ago
|
If you need to make sure there's only a single style tag use fourth argument as was mentioned in meta tags description.
|
||
11 years ago
|
|
||
|
```php
|
||
11 years ago
|
$this->registerCssFile("http://example.com/css/themes/black-and-white.css", [BootstrapAsset::className()], ['media' => 'print'], 'css-print-theme');
|
||
11 years ago
|
```
|
||
|
|
||
11 years ago
|
The code above will add a link to CSS file to the head section of the page.
|
||
|
|
||
|
* The first argument specifies the CSS file to be registered.
|
||
11 years ago
|
* The second argument specifies that this CSS file depends on [[yii\bootstrap\BootstrapAsset|BootstrapAsset]], meaning it will be added
|
||
|
AFTER the CSS files in [[yii\bootstrap\BootstrapAsset|BootstrapAsset]]. Without this dependency specification, the relative order
|
||
|
between this CSS file and the [[yii\bootstrap\BootstrapAsset|BootstrapAsset]] CSS files would be undefined.
|
||
11 years ago
|
* The third argument specifies the attributes for the resulting `<link>` tag.
|
||
|
* The last argument specifies an ID identifying this CSS file. If it is not provided, the URL of the CSS file will be
|
||
|
used instead.
|
||
|
|
||
|
|
||
|
It is highly recommended that you use [asset bundles](assets.md) to register external CSS files rather than
|
||
11 years ago
|
using [[yii\web\View::registerCssFile()|registerCssFile()]]. Using asset bundles allows you to combine and compress
|
||
|
multiple CSS files, which is desirable for high traffic websites.
|
||
11 years ago
|
|
||
11 years ago
|
|
||
|
### Registering scripts
|
||
|
|
||
11 years ago
|
With the [[yii\web\View]] object you can register scripts. There are two dedicated methods for it:
|
||
|
[[yii\web\View::registerJs()|registerJs()]] for inline scripts and
|
||
|
[[yii\web\View::registerJsFile()|registerJsFile()]] for external scripts.
|
||
|
Inline scripts are useful for configuration and dynamically generated code.
|
||
11 years ago
|
The method for adding these can be used as follows:
|
||
11 years ago
|
|
||
11 years ago
|
```php
|
||
11 years ago
|
$this->registerJs("var options = ".json_encode($options).";", View::POS_END, 'my-options');
|
||
11 years ago
|
```
|
||
|
|
||
11 years ago
|
The first argument is the actual JS code we want to insert into the page. The second argument
|
||
|
determines where script should be inserted into the page. Possible values are:
|
||
11 years ago
|
|
||
11 years ago
|
- [[yii\web\View::POS_HEAD|View::POS_HEAD]] for head section.
|
||
|
- [[yii\web\View::POS_BEGIN|View::POS_BEGIN]] for right after opening `<body>`.
|
||
|
- [[yii\web\View::POS_END|View::POS_END]] for right before closing `</body>`.
|
||
|
- [[yii\web\View::POS_READY|View::POS_READY]] for executing code on document `ready` event. This will register [[yii\web\JqueryAsset|jQuery]] automatically.
|
||
|
- [[yii\web\View::POS_LOAD|View::POS_LOAD]] for executing code on document `load` event. This will register [[yii\web\JqueryAsset|jQuery]] automatically.
|
||
11 years ago
|
|
||
11 years ago
|
The last argument is a unique script ID that is used to identify code block and replace existing one with the same ID
|
||
|
instead of adding a new one. If you don't provide it, the JS code itself will be used as the ID.
|
||
11 years ago
|
|
||
11 years ago
|
An external script can be added like the following:
|
||
11 years ago
|
|
||
|
```php
|
||
11 years ago
|
$this->registerJsFile('http://example.com/js/main.js', [JqueryAsset::className()]);
|
||
11 years ago
|
```
|
||
|
|
||
11 years ago
|
The arguments for [[yii\web\View::registerJsFile()|registerJsFile()]] are similar to those for
|
||
|
[[yii\web\View::registerCssFile()|registerCssFile()]]. In the above example,
|
||
11 years ago
|
we register the `main.js` file with the dependency on `JqueryAsset`. This means the `main.js` file
|
||
|
will be added AFTER `jquery.js`. Without this dependency specification, the relative order between
|
||
|
`main.js` and `jquery.js` would be undefined.
|
||
|
|
||
11 years ago
|
Like for [[yii\web\View::registerCssFile()|registerCssFile()]], it is also highly recommended that you use
|
||
|
[asset bundles](assets.md) to register external JS files rather than using [[yii\web\View::registerJsFile()|registerJsFile()]].
|
||
11 years ago
|
|
||
11 years ago
|
|
||
|
### Registering asset bundles
|
||
|
|
||
|
As was mentioned earlier it's preferred to use asset bundles instead of using CSS and JavaScript directly. You can get
|
||
|
details on how to define asset bundles in [asset manager](assets.md) section of the guide. As for using already defined
|
||
|
asset bundle, it's very straightforward:
|
||
|
|
||
|
```php
|
||
11 years ago
|
\frontend\assets\AppAsset::register($this);
|
||
11 years ago
|
```
|
||
|
|
||
|
### Layout
|
||
|
|
||
11 years ago
|
A layout is a very convenient way to represent the part of the page that is common for all or at least for most pages
|
||
|
generated by your application. Typically it includes `<head>` section, footer, main menu and alike elements.
|
||
11 years ago
|
You can find a fine example of the layout in a [basic application template](apps-basic.md). Here we'll review the very
|
||
11 years ago
|
basic one without any widgets or extra markup.
|
||
|
|
||
|
```php
|
||
|
<?php
|
||
|
use yii\helpers\Html;
|
||
|
?>
|
||
11 years ago
|
<?php $this->beginPage() ?>
|
||
11 years ago
|
<!DOCTYPE html>
|
||
11 years ago
|
<html lang="<?= Yii::$app->language ?>">
|
||
11 years ago
|
<head>
|
||
11 years ago
|
<meta charset="<?= Yii::$app->charset ?>"/>
|
||
|
<title><?= Html::encode($this->title) ?></title>
|
||
|
<?php $this->head() ?>
|
||
11 years ago
|
</head>
|
||
|
<body>
|
||
11 years ago
|
<?php $this->beginBody() ?>
|
||
11 years ago
|
<div class="container">
|
||
|
<?= $content ?>
|
||
|
</div>
|
||
|
<footer class="footer">© 2013 me :)</footer>
|
||
11 years ago
|
<?php $this->endBody() ?>
|
||
11 years ago
|
</body>
|
||
|
</html>
|
||
11 years ago
|
<?php $this->endPage() ?>
|
||
11 years ago
|
```
|
||
|
|
||
|
In the markup above there's some code. First of all, `$content` is a variable that will contain result of views rendered
|
||
|
with controller's `$this->render()` method.
|
||
|
|
||
11 years ago
|
We are importing [[yii\helpers\Html|Html]] helper via standard PHP `use` statement. This helper is typically used for almost all views
|
||
11 years ago
|
where one need to escape outputted data.
|
||
|
|
||
11 years ago
|
Several special methods such as [[yii\web\View::beginPage()|beginPage()]]/[[yii\web\View::endPage()|endPage()]],
|
||
|
[[yii\web\View::head()|head()]], [[yii\web\View::beginBody()|beginBody()]]/[[yii\web\View::endBody()|endBody()]]
|
||
|
are triggering page rendering events that are used for registering scripts, links and process page in many other ways.
|
||
|
Always include these in your layout in order for the rendering to work correctly.
|
||
11 years ago
|
|
||
11 years ago
|
### Partials
|
||
|
|
||
|
Often you need to reuse some HTML markup in many views and often it's too simple to create a full-featured widget for it.
|
||
|
In this case you may use partials.
|
||
|
|
||
|
Partial is a view as well. It resides in one of directories under `views` and by convention is often started with `_`.
|
||
|
For example, we need to render a list of user profiles and, at the same time, display individual profile elsewhere.
|
||
|
|
||
|
First we need to define a partial for user profile in `_profile.php`:
|
||
|
|
||
|
```php
|
||
|
<?php
|
||
|
use yii\helpers\Html;
|
||
|
?>
|
||
|
|
||
|
<div class="profile">
|
||
11 years ago
|
<h2><?= Html::encode($username) ?></h2>
|
||
|
<p><?= Html::encode($tagline) ?></p>
|
||
11 years ago
|
</div>
|
||
|
```
|
||
|
|
||
|
Then we're using it in `index.php` view where we display a list of users:
|
||
|
|
||
|
```php
|
||
|
<div class="user-index">
|
||
11 years ago
|
<?php
|
||
|
foreach ($users as $user) {
|
||
|
echo $this->render('_profile', [
|
||
|
'username' => $user->name,
|
||
|
'tagline' => $user->tagline,
|
||
|
]);
|
||
|
}
|
||
|
?>
|
||
11 years ago
|
</div>
|
||
|
```
|
||
|
|
||
|
Same way we can reuse it in another view displaying a single user profile:
|
||
|
|
||
|
```php
|
||
11 years ago
|
echo $this->render('_profile', [
|
||
11 years ago
|
'username' => $user->name,
|
||
|
'tagline' => $user->tagline,
|
||
11 years ago
|
]);
|
||
11 years ago
|
```
|
||
|
|
||
11 years ago
|
|
||
|
When you call `render()` to render a partial in a current view, you may use different formats to refer to the partial.
|
||
|
The most commonly used format is the so-called relative view name which is as shown in the above example.
|
||
|
The partial view file is relative to the directory containing the current view. If the partial is located under
|
||
|
a subdirectory, you should include the subdirectory name in the view name, e.g., `public/_profile`.
|
||
|
|
||
|
You may use path alias to specify a view, too. For example, `@app/views/common/_profile`.
|
||
|
|
||
|
And you may also use the so-called absolute view names, e.g., `/user/_profile`, `//user/_profile`.
|
||
|
An absolute view name starts with a single slashes or double slashes. If it starts with a single slash,
|
||
|
the view file will be looked for under the view path of the currently active module. Otherwise, it will
|
||
|
will be looked for under the application view path.
|
||
|
|
||
|
|
||
11 years ago
|
### Accessing context
|
||
|
|
||
|
Views are generally used either by controller or by widget. In both cases the object that called view rendering is
|
||
|
available in the view as `$this->context`. For example if we need to print out the current internal request route in a
|
||
|
view rendered by controller we can use the following:
|
||
|
|
||
|
```php
|
||
|
echo $this->context->getRoute();
|
||
|
```
|
||
|
|
||
11 years ago
|
### Static Pages
|
||
|
|
||
11 years ago
|
If you need to render static pages you can use class `ViewAction`. It represents an action that displays a view according
|
||
|
to a user-specified parameter.
|
||
11 years ago
|
|
||
11 years ago
|
Usage of the class is simple. In your controller use the class via `actions` method:
|
||
11 years ago
|
|
||
|
```php
|
||
|
class SiteController extends Controller
|
||
|
{
|
||
|
public function actions()
|
||
|
{
|
||
|
return [
|
||
|
'static' => [
|
||
|
'class' => '\yii\web\ViewAction',
|
||
|
],
|
||
|
];
|
||
|
}
|
||
|
|
||
|
//...
|
||
|
}
|
||
|
```
|
||
|
|
||
11 years ago
|
Then create `index.php` in `@app/views/site/pages/`:
|
||
|
|
||
11 years ago
|
```php
|
||
|
//index.php
|
||
11 years ago
|
<h1>Hello, I am a static page!</h1>
|
||
11 years ago
|
```
|
||
|
|
||
11 years ago
|
That's it. Now you can try it using `/index.php?r=site/static`.
|
||
11 years ago
|
|
||
|
By default, the view being displayed is specified via the `view` GET parameter.
|
||
11 years ago
|
If you open `/index.php?r=site/static?&view=about` then `@app/views/site/pages/about.php` view file will be used.
|
||
11 years ago
|
|
||
11 years ago
|
If not changed or specified via GET defaults are the following:
|
||
11 years ago
|
|
||
11 years ago
|
- GET parameter name: `view`.
|
||
|
- View file used if parameter is missing: `index.php`.
|
||
|
- Directory where views are stored (`viewPrefix`): `pages`.
|
||
|
- Layout for the page rendered matches the one used in controller.
|
||
11 years ago
|
|
||
11 years ago
|
For more information see [[yii\web\ViewAction]].
|
||
11 years ago
|
|
||
11 years ago
|
### Caching blocks
|
||
|
|
||
11 years ago
|
To learn about caching of view fragments please refer to [caching](caching.md) section of the guide.
|
||
11 years ago
|
|
||
|
Customizing View component
|
||
|
--------------------------
|
||
|
|
||
|
Since view is also an application component named `view` you can replace it with your own component that extends
|
||
11 years ago
|
from [[yii\base\View]] or [[yii\web\View]]. It can be done via application configuration file such as `config/web.php`:
|
||
11 years ago
|
|
||
|
```php
|
||
11 years ago
|
return [
|
||
11 years ago
|
// ...
|
||
|
'components' => [
|
||
|
'view' => [
|
||
|
'class' => 'app\components\View',
|
||
|
],
|
||
|
// ...
|
||
|
],
|
||
11 years ago
|
];
|
||
11 years ago
|
```
|