Views ===== > Note: This section is under development. Views are part of the [MVC](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) architecture. They are code responsible for presenting data to end users. In a Web application, views are usually created in terms of *view templates* which are PHP script files containing mainly HTML code and presentational PHP code. They are managed by the [[yii\web\View|view]] application component which provides commonly used methods to facilitate view composition and rendering. For simplicity, we often call view templates or view template files as views. ## Creating Views As aforementioned, a view is simply a PHP script mixed with HTML and PHP code. The following is the view that presents a login form. As you can see, PHP code is used to generate the dynamic content, such as the page title and the form, while HTML code organizes them into a presentable HTML page. ```php title = 'Login'; ?>
Please fill out the following fields to login:
= $form->field($model, 'username') ?> = $form->field($model, 'password')->passwordInput() ?> = Html::submitButton('Login') ?> ``` Within a view, you can access `$this` which refers to the [[yii\web\View|view component]] managing and rendering this view template. Besides `$this`, there may be other predefined variables in a view, such as `$form` and `$model` in the above example. These variables represent the data that are *pushed* into the view by [controllers](structure-controllers.md) or other objects whose trigger the [view rendering](#rendering-views). > Tip: The predefined variables are listed in a comment block at beginning of a view so that they can be recognized by IDEs. It is also a good practice to document your views. TODO: features in creating views ## Organizing Views Like [controllers](structure-controllers.md) and [models](structure-models.md), there are conventions to organize views. * For views rendered in a controller, they should be put under the directory `@app/views/ControllerID` by default, where `ControllerID` refers to [the ID of the controller](structure-controllers.md#routes). For example, if the controller class is `PostController`, the directory would be `@app/views/post`; If the class is `PostCommentController`, the directory would be `@app/views/post-comment`. In case the controller belongs to a module, the directory would be `views/ControllerID` under the [[yii\base\Module::basePath|module directory]]. * For views rendered in a [widget](structure-widgets.md), they should be put under the `WidgetPath/views` directory by default, where `WidgetPath` stands for the directory containing the widget class file. * For views rendered by other objects, it is recommended that you follow the similar convention as that for widgets. You may customize these default view directories by overriding the [[yii\base\ViewContextInterface::getViewPath()]] method of controllers or widgets. ## Rendering Views You can render views in [controllers](structure-controllers.md), [widgets](structure-widgets.md), or any other places. There are different view rendering methods provided by different classes. However, they share the similar method signature as follows, ``` /** * @param string $view view name or file path, depending on the actual rendering method * @param array $params the parameters to be pushed into the view */ methodName($view, $params = []) ``` ### Passing Data to Views As you can see, the first parameter specifies which view to be rendered. We will describe more about it in the [Named Views](#named-views) subsection. The second parameter specifies what data should be "pushed" into the view and made accessible there. When the rendering method renders a view, it will "extract" the `$params` array so that each keyed array element is turned into a variable of the same name in the view. For example, if `$params` is `['a' => 1, 'b' => 2]`, in the view you will be able to access variable `$a` and `$b` whose values are 1 and 2, respectively. ### Rendering in Controllers Within [controllers](structure-controllers.md), you may call the following controller methods to render views. * [[yii\base\Controller::render()|render()]]: renders a [named view](#named-views) and applies a [layout](#layouts) to the rendering result. * [[yii\base\Controller::renderPartial()|renderPartial()]]: renders a [named view](#named-views) without any layout. * [[yii\base\Controller::renderFile()|renderFile()]]: renders a view specified in terms of a view file path or [alias](concept-aliases.md). For example, ```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; } // renders a view named "view" and applies a layout to it return $this->render('view', [ 'model' => $model, ]); } } ``` ### Rendering in Widgets Within [widgets](structure-widgets.md), you may call the following widget methods to render views. * [[yii\base\Widget::render()|render()]]: renders a [named view](#named-views). * [[yii\base\Widget::renderFile()|renderFile()]]: renders a view specified in terms of a view file path or [alias](concept-aliases.md). For example, ```php namespace app\components; use yii\base\Widget; use yii\helpers\Html; class ListWidget extends Widget { public $items = []; public function run() { // renders a view named "list" return $this->render('list', [ 'items' => $this->items, ]); } } ``` ### Rendering in Other Places In any place, you can render views by calling the following methods of the [[yii\base\View|view]] application component. * [[yii\base\View::render()|render()]]: renders a [named view](#named-views). * [[yii\base\View::renderFile()|renderFile()]]: renders a view specified in terms of a view file path or [alias](concept-aliases.md). For example, ```php // displays the view file "@app/views/site/license.php" echo \Yii::$app->view->renderFile('@app/views/site/license.php'); ``` If you are rendering a view within another view, you can use the following code, because `$this` in a view refers to the [[yii\base\View|view]] component: ```php = $this->renderFile('@app/views/site/license.php') ?> ``` ## Named Views When you render a view, you can specify the view using either a view name or a view file path/alias. In most cases, you would use the former because it is more concise and flexible. We call views specified using names as *named views*. A view name is resolved into the corresponding view file path according to the following rules: * A view name may omit the file extension name. In this case, `.php` will be used as the extension. For example, the view name `about` corresponds to the file name `about.php`. * If the view name starts with double slashes `//`, the corresponding view file path would be `@app/views/ViewName`. That is, the view is looked for under the [[yii\base\Application::viewPath|application's view path]]. For example, `//site/about` will be resolved into `@app/views/site/about.php`. * If the view name starts with a single slash `/`, the view file path is formed by prefixing the view name with the [[yii\base\Module::viewPath|view path]] of the currently active [module](structure-modules.md). If there is no active module, `@app/views/ViewName` will be used. For example, `/user/create` will be resolved into `@app/modules/user/views/user/create.php`, if the currently active module is `user`. If there is no active module, the view file path would be `@app/views/user/create.php`. * If the view is rendered with a [[yii\base\View::context|context]] and the context implements [[yii\base\ViewContextInterface]], the view file path is formed by prefixing the [[yii\base\ViewContextInterface::getViewPath()|view path]] of the context to the view name. This mainly applies to the views rendered within controllers and widgets. For example, `site/about` will be resolved into `@app/views/site/about.php` if the context is the controller `SiteController`. * If a view is rendered within another view, the directory containing the other view file will be prefixed to the new view name to form the actual view file path. For example, `item` will be resolved into `@app/views/post/item` if it is being rendered in the view `@app/views/post/index.php`. According to the above rules, the following code in a controller is actually rendering the view file `@app/views/post/view.php` ```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; } // renders a view named "view" and applies a layout to it return $this->render('view', [ 'model' => $model, ]); } } ``` And the following code in the view `@app/views/post/view.php` is actually rendering the view file `@app/views/post/overview.php`: ```php = $this->render('overview', ['model' => $model]) ?> ``` ## Layouts ### Nested Layouts ## View Components ## Creating Views ### Setting page title ### Adding meta tags ### Registering link tags ### Registering CSS ### Registering scripts ### Static Pages ### Assets ## Alternative Template Engines Basics ------ 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. The view is typically called from controller action using the [[yii\base\Controller::render()|render()]] method: ```php public function actionIndex() { return $this->render('index', ['username' => 'samdark']); } ``` 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` is the controller ID. For details on how the view name is resolved, refer to the [[yii\base\Controller::render()]] method. 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. The view for the action above would be `views/site/index.php` and can be something like: ```phpHello, = $username ?>!
``` Any data type can be passed to the view, including arrays or objects. 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 of the view instead of the view name. Widgets ------- 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), breadcrumbs, menu, and [wrappers around bootstrap component framework](bootstrap-widgets.md). Additionally there are extensions that provide more widgets, such as the official widget for [jQueryUI](http://www.jqueryui.com) components. In order to use a widget, your view file would do the following: ```php // Note that you have to "echo" the result to display it echo \yii\widgets\Menu::widget(['items' => $items]); // Passing an array to initialize the object properties $form = \yii\widgets\ActiveForm::begin([ 'options' => ['class' => 'form-horizontal'], 'fieldConfig' => ['inputOptions' => ['class' => 'input-xlarge']], ]); ... form inputs here ... \yii\widgets\ActiveForm::end(); ``` 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 widget that wraps content between method calls with its own output. In case of the form this output is the `