The Definitive Guide To Yii 2.0 Yii2 Guide.en
User Manual:
Open the PDF directly: View PDF
.
Page Count: 575
| Download | |
| Open PDF In Browser | View PDF |
The Denitive Guide
to
Yii 2.0
http://www.yiiframework.com/doc/guide
Qiang Xue,
Alexander Makarov,
Carsten Brandt,
Klimov Paul,
and
many contributors from the Yii community
This tutorial is released under the Terms of Yii Documentation.
Copyright 2014 Yii Software LLC. All Rights Reserved.
Contents
1
2
3
Introduction
1
1.1
What is Yii
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2
Upgrading from Version 1.1
. . . . . . . . . . . . . . . . . . .
Getting Started
1
2
13
2.1
Installing Yii
2.2
Running Applications
. . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3
Saying Hello . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
2.4
Working with Forms
26
2.5
Working with Databases . . . . . . . . . . . . . . . . . . . . .
32
2.6
Generating Code with Gii
. . . . . . . . . . . . . . . . . . . .
38
2.7
Looking Ahead
. . . . . . . . . . . . . . . . . . . . . . . . . .
44
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
13
19
Application Structure
47
3.1
Overview
47
3.2
Entry Scripts
. . . . . . . . . . . . . . . . . . . . . . . . . . .
48
3.3
Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . .
50
3.4
Application Components . . . . . . . . . . . . . . . . . . . . .
63
3.5
Controllers
65
3.6
Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
75
3.7
Views
86
3.8
Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
3.9
Filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.10 Widgets
3.11 Assets
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
3.12 Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
4
Handling Requests
149
4.1
Overview
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
4.2
Bootstrapping . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
4.3
Routing and URL Creation
4.4
Requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
4.5
Responses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
. . . . . . . . . . . . . . . . . . . 151
iii
iv
5
6
7
8
9
CONTENTS
4.6
Sessions and Cookies . . . . . . . . . . . . . . . . . . . . . . . 175
4.7
Handling Errors . . . . . . . . . . . . . . . . . . . . . . . . . . 182
4.8
Logging
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
Key Concepts
195
5.1
Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
5.2
Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
5.3
Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
5.4
Behaviors
5.5
Congurations
5.6
Aliases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
5.7
Class Autoloading
5.8
Service Locator . . . . . . . . . . . . . . . . . . . . . . . . . . 223
5.9
Dependency Injection Container . . . . . . . . . . . . . . . . . 225
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
. . . . . . . . . . . . . . . . . . . . . . . . . . 213
. . . . . . . . . . . . . . . . . . . . . . . . 221
Working with Databases
237
6.1
Database Access Objects . . . . . . . . . . . . . . . . . . . . . 237
6.2
Query Builder . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
6.3
Active Record . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
6.4
Database Migration . . . . . . . . . . . . . . . . . . . . . . . . 296
Getting Data from Users
321
7.1
Creating Forms . . . . . . . . . . . . . . . . . . . . . . . . . . 321
7.2
Validating Input
7.3
Uploading Files . . . . . . . . . . . . . . . . . . . . . . . . . . 342
7.4
Collecting tabular input
7.5
Getting Data for Multiple Models . . . . . . . . . . . . . . . . 349
. . . . . . . . . . . . . . . . . . . . . . . . . 326
Displaying Data
. . . . . . . . . . . . . . . . . . . . . 347
351
8.1
Data Formatting
8.2
Pagination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
8.3
Sorting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358
8.4
Data Providers
8.5
Data widgets
8.6
Working with Client Scripts . . . . . . . . . . . . . . . . . . . 380
8.7
Theming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385
Security
. . . . . . . . . . . . . . . . . . . . . . . . . 351
. . . . . . . . . . . . . . . . . . . . . . . . . . 360
. . . . . . . . . . . . . . . . . . . . . . . . . . . 366
389
9.1
Security
9.2
Authentication
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389
9.3
Authorization . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
9.4
Working with Passwords . . . . . . . . . . . . . . . . . . . . . 410
9.5
Cryptography . . . . . . . . . . . . . . . . . . . . . . . . . . . 410
9.6
Security best practices . . . . . . . . . . . . . . . . . . . . . . 413
. . . . . . . . . . . . . . . . . . . . . . . . . . 389
CONTENTS
v
10 Caching
10.1 Caching
419
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419
10.2 Data Caching . . . . . . . . . . . . . . . . . . . . . . . . . . . 419
10.3 Fragment Caching
. . . . . . . . . . . . . . . . . . . . . . . . 428
10.4 Page Caching . . . . . . . . . . . . . . . . . . . . . . . . . . . 432
10.5 HTTP Caching . . . . . . . . . . . . . . . . . . . . . . . . . . 433
11 RESTful Web Services
11.1 Quick Start
11.2 Resources
11.3 Controllers
11.4 Routing
437
. . . . . . . . . . . . . . . . . . . . . . . . . . . . 437
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441
. . . . . . . . . . . . . . . . . . . . . . . . . . . . 446
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450
11.5 Response Formatting . . . . . . . . . . . . . . . . . . . . . . . 452
11.6 Authentication
. . . . . . . . . . . . . . . . . . . . . . . . . . 455
11.7 Rate Limiting . . . . . . . . . . . . . . . . . . . . . . . . . . . 458
11.8 Versioning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 460
11.9 Error Handling
. . . . . . . . . . . . . . . . . . . . . . . . . . 462
12 Development Tools
465
13 Testing
469
13.1 Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469
13.2 Testing environment setup . . . . . . . . . . . . . . . . . . . . 471
13.3 Unit Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 472
13.4 Functional Tests
. . . . . . . . . . . . . . . . . . . . . . . . . 472
13.5 Acceptance Tests . . . . . . . . . . . . . . . . . . . . . . . . . 473
13.6 Fixtures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 473
13.7 Managing Fixtures
. . . . . . . . . . . . . . . . . . . . . . . . 478
14 Special Topics
483
14.1 Creating your own Application structure . . . . . . . . . . . . 485
14.2 Console applications
. . . . . . . . . . . . . . . . . . . . . . . 486
14.3 Core Validators . . . . . . . . . . . . . . . . . . . . . . . . . . 493
14.4 Internationalization . . . . . . . . . . . . . . . . . . . . . . . . 508
14.5 Mailing
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523
14.6 Performance Tuning
. . . . . . . . . . . . . . . . . . . . . . . 527
14.7 Shared Hosting Environment
. . . . . . . . . . . . . . . . . . 532
14.8 Using template engines . . . . . . . . . . . . . . . . . . . . . . 534
14.9 Working with Third-Party Code . . . . . . . . . . . . . . . . . 535
15 Widgets
539
vi
CONTENTS
16 Helpers
16.1 Helpers
549
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 549
16.2 ArrayHelper . . . . . . . . . . . . . . . . . . . . . . . . . . . . 550
16.3 Html helper . . . . . . . . . . . . . . . . . . . . . . . . . . . . 558
16.4 Url Helper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 566
Chapter 1
Introduction
1.1 What is Yii
Yii is a high performance, component-based PHP framework for rapidly
developing modern Web applications. The name Yii (pronounced
:])
Yee
or
[ji
means simple and evolutionary in Chinese. It can also be thought of
as an acronym for
Yes It Is!
1.1.1 What is Yii Best for?
Yii is a generic Web programming framework, meaning that it can be used
for developing all kinds of Web applications using PHP. Because of its
component-based architecture and sophisticated caching support, it is especially suitable for developing large-scale applications such as portals, forums, content management systems (CMS), e-commerce projects, RESTful
Web services, and so on.
1.1.2 How does Yii Compare with Other Frameworks?
If you're already familiar with another framework, you may appreciate knowing how Yii compares:
•
Like most PHP frameworks, Yii implements the MVC (Model-ViewController) architectural pattern and promotes code organization based
on that pattern.
•
Yii takes the philosophy that code should be written in a simple yet
elegant way.
Yii will never try to over-design things mainly for the
purpose of strictly following some design pattern.
•
Yii is a full-stack framework providing many proven and ready-touse features: query builders and ActiveRecord for both relational and
NoSQL databases; RESTful API development support; multi-tier caching support; and more.
1
2
CHAPTER 1.
•
INTRODUCTION
Yii is extremely extensible. You can customize or replace nearly every
piece of the core's code.
You can also take advantage of Yii's solid
extension architecture to use or develop redistributable extensions.
•
High performance is always a primary goal of Yii.
1
Yii is not a one-man show, it is backed up by a strong core developer team ,
as well as a large community of professionals constantly contributing to Yii's
development. The Yii developer team keeps a close eye on the latest Web
development trends and on the best practices and features found in other
frameworks and projects.
The most relevant best practices and features
found elsewhere are regularly incorporated into the core framework and exposed via simple and elegant interfaces.
1.1.3 Yii Versions
Yii currently has two major versions available: 1.1 and 2.0. Version 1.1 is
the old generation and is now in maintenance mode. Version 2.0 is a complete rewrite of Yii, adopting the latest technologies and protocols, including
Composer, PSR, namespaces, traits, and so forth. Version 2.0 represents the
current generation of the framework and will receive the main development
eorts over the next few years. This guide is mainly about version 2.0.
1.1.4 Requirements and Prerequisites
Yii 2.0 requires PHP 5.4.0 or above and runs best with the latest version of
PHP 7. You can nd more detailed requirements for individual features by
running the requirement checker included in every Yii release.
Using Yii requires basic knowledge of object-oriented programming (OOP),
as Yii is a pure OOP-based framework. Yii 2.0 also makes use of the latest
features of PHP, such as namespaces
2 and traits3 . Understanding these con-
cepts will help you more easily pick up Yii 2.0.
1.2 Upgrading from Version 1.1
There are many dierences between versions 1.1 and 2.0 of Yii as the framework was completely rewritten for 2.0. As a result, upgrading from version
1.1 is not as trivial as upgrading between minor versions. In this guide you'll
nd the major dierences between the two versions.
If you have not used Yii 1.1 before, you can safely skip this section and
turn directly to Getting started.
Please note that Yii 2.0 introduces more new features than are covered
in this summary. It is highly recommended that you read through the whole
1
http://www.yiiframework.com/team/
http://www.php.net/manual/en/language.namespaces.php
3
http://www.php.net/manual/en/language.oop5.traits.php
2
1.2.
UPGRADING FROM VERSION 1.1
3
denitive guide to learn about them all. Chances are that some features you
previously had to develop for yourself are now part of the core code.
1.2.1 Installation
4
Yii 2.0 fully embraces Composer , the de facto PHP package manager. Installation of the core framework, as well as extensions, are handled through
Composer. Please refer to the Installing Yii section to learn how to install
Yii 2.0. If you want to create new extensions, or turn your existing 1.1 extensions into 2.0-compatible extensions, please refer to the Creating Extensions
section of the guide.
1.2.2 PHP Requirements
Yii 2.0 requires PHP 5.4 or above, which is a huge improvement over PHP
version 5.2 that is required by Yii 1.1. As a result, there are many dierences
on the language level that you should pay attention to. Below is a summary
of the major changes regarding PHP:
•
•
•
5
Namespaces .
6
Anonymous functions .
Short array syntax
[...elements...]
is used instead of
array(...elements
...).
•
Short echo tags
=
are used in view les. This is safe to use starting
from PHP 5.4.
•
•
•
•
•
7
SPL classes and interfaces .
8
Late Static Bindings .
9
Date and Time .
10
Traits .
11 . Yii 2.0 makes use of the intl PHP extension to support inter-
intl
nationalization features.
1.2.3 Namespace
The most obvious change in Yii 2.0 is the use of namespaces. Almost every
core class is namespaced, e.g.,
yii\web\Request.
The C prex is no longer
used in class names. The naming scheme now follows the directory structure.
For example,
/Request.php
4
yii\web\Request
indicates that the corresponding class le is
under the Yii framework folder.
https://getcomposer.org/
http://php.net/manual/en/language.namespaces.php
6
http://php.net/manual/en/functions.anonymous.php
7
http://php.net/manual/en/book.spl.php
8
http://php.net/manual/en/language.oop5.late-static-bindings.php
9
http://php.net/manual/en/book.datetime.php
10
http://php.net/manual/en/language.oop5.traits.php
11
http://php.net/manual/en/book.intl.php
5
web
4
CHAPTER 1.
INTRODUCTION
(You can use any core class without explicitly including that class le,
thanks to the Yii class loader.)
1.2.4 Component and Object
yii\base\Object
yii\base\Object class is a lightweight base
class that allows dening object properties via getters and setters. The yii
\base\Component class extends from yii\base\Object and supports events
Yii 2.0 breaks the
and
CComponent
yii\base\Component.
class in 1.1 into two classes:
The
and behaviors.
If your class does not need the event or behavior feature, you should
consider using
yii\base\Object
as the base class. This is usually the case
for classes that represent basic data structures.
1.2.5 Object Conguration
yii\base\Object class introduces a uniform way of conguring objects.
Any descendant class of yii\base\Object should declare its constructor (if
The
needed) in the following way so that it can be properly congured:
class MyClass extends \yii\base\Object
{
public function __construct($param1, $param2, $config = [])
{
// ... initialization before configuration is applied
}
parent::__construct($config);
public function init()
{
parent::init();
}
}
// ... initialization after configuration is applied
In the above, the last parameter of the constructor must take a conguration
array that contains name-value pairs for initializing the properties at the end
of the constructor. You can override the
yii\base\Object::init() method
to do initialization work that should be done after the conguration has been
applied.
By following this convention, you will be able to create and congure
new objects using a conguration array:
$object = Yii::createObject([
'class' => 'MyClass',
'property1' => 'abc',
'property2' => 'cde',
], [$param1, $param2]);
1.2.
UPGRADING FROM VERSION 1.1
5
More details about congurations can be found in the Congurations section.
1.2.6 Events
In Yii 1, events were created by dening an
on-method
(e.g.,
onBeforeSave).
In Yii 2, you can now use any event name. You trigger an event by calling
the
yii\base\Component::trigger()
method:
$event = new \yii\base\Event;
$component->trigger($eventName, $event);
To attach a handler to an event, use the
yii\base\Component::on() method:
$component->on($eventName, $handler);
// To detach the handler, use:
// $component->off($eventName, $handler);
There are many enhancements to the event features. For more details, please
refer to the Events section.
1.2.7 Path Aliases
Yii 2.0 expands the usage of path aliases to both le/directory paths and
URLs. Yii 2.0 also now requires an alias name to start with the
@
character,
to dierentiate aliases from normal le/directory paths or URLs.
ample, the alias
@yii
For ex-
refers to the Yii installation directory. Path aliases are
supported in most places in the Yii core code. For example,
\FileCache::cachePath
yii\caching
can take both a path alias and a normal directory
path.
A path alias is also closely related to a class namespace.
It is recom-
mended that a path alias be dened for each root namespace, thereby allowing you to use Yii class autoloader without any further conguration.
For example, because
yii\web\Request
@yii
refers to the Yii installation directory, a class like
can be autoloaded. If you use a third party library, such as
the Zend Framework, you may dene a path alias
@Zend
that refers to that
framework's installation directory. Once you've done that, Yii will be able
to autoload any class in that Zend Framework library, too.
More on path aliases can be found in the Aliases section.
1.2.8 Views
The most signicant change about views in Yii 2 is that the special variable
$this
$this
in a view no longer refers to the current controller or widget. Instead,
now refers to a
object is of type
view
object, a new concept introduced in 2.0. The
yii\web\View,
view
which represents the view part of the MVC
pattern. If you want to access the controller or widget in a view, you can
use
$this->context.
6
CHAPTER 1.
INTRODUCTION
To render a partial view within another view, you use
$this->renderPartial(). The call to render also now
echoed, as the render() method returns the rendering
not
$this->render(),
has to be explicitly
result, rather than
directly displaying it. For example:
echo $this->render('_item', ['item' => $item]);
Besides using PHP as the primary template language, Yii 2.0 is also equipped
with ocial support for two popular template engines: Smarty and Twig.
The Prado template engine is no longer supported. To use these template
engines, you need to congure the
the
yii\base\View::$renderers
view
application component by setting
property.
Please refer to the Template
Engines section for more details.
1.2.9 Models
Yii 2.0 uses
The class
extend
yii\base\Model
CFormModel
as the base model, similar to
CModel
in 1.1.
has been dropped entirely. Instead, in Yii 2 you should
yii\base\Model
to create a form model class.
Yii 2.0 introduces a new method called
yii\base\Model::scenarios()
to declare supported scenarios, and to indicate under which scenario an
attribute needs to be validated, can be considered as safe or not, etc. For
example:
public function scenarios()
{
return [
'backend' => ['email', 'role'],
'frontend' => ['email', '!role'],
];
}
backend and frontend. For the
email and role attributes are safe, and can be
massively assigned. For the frontend scenario, email can be massively assigned
while role cannot. Both email and role should be validated using rules.
In the above, two scenarios are declared:
backend
The
scenario, both the
yii\base\Model::rules()
idation rules.
scenarios(),
method is still used to declare the val-
Note that due to the introduction of
there is no longer an
unsafe
In most cases, you do not need to override
if the
yii\base\Model::rules()
yii\base\Model::
validator.
yii\base\Model::scenarios()
method fully species the scenarios that
will exist, and if there is no need to declare
unsafe
attributes.
To learn more details about models, please refer to the Models section.
1.2.10 Controllers
Yii 2.0 uses
to
yii\web\Controller as the base controller class, which is similar
CController in Yii 1.1. yii\base\Action is the base class for action classes.
1.2.
UPGRADING FROM VERSION 1.1
7
The most obvious impact of these changes on your code is that a controller action should return the content that you want to render instead of
echoing it:
public function actionView($id)
{
$model = \app\models\Post::findOne($id);
if ($model) {
return $this->render('view', ['model' => $model]);
} else {
throw new \yii\web\NotFoundHttpException;
}
}
Please refer to the Controllers section for more details about controllers.
1.2.11 Widgets
Yii 2.0 uses
yii\base\Widget
as the base widget class, similar to
CWidget
in
Yii 1.1.
To get better support for the framework in IDEs, Yii 2.0 introduces a new
yii\base\Widget::begin(),
yii\base\Widget::widget() have been in-
syntax for using widgets. The static methods
yii\base\Widget::end(),
and
troduced, to be used like so:
use yii\widgets\Menu;
use yii\widgets\ActiveForm;
// Note that you have to "echo" the result to display it
echo Menu::widget(['items' => $items]);
// Passing an array to initialize the object properties
$form = ActiveForm::begin([
'options' => ['class' => 'form-horizontal'],
'fieldConfig' => ['inputOptions' => ['class' => 'input-xlarge']],
]);
... form input fields here ...
ActiveForm::end();
Please refer to the Widgets section for more details.
1.2.12 Themes
Themes work completely dierently in 2.0. They are now based on a path
mapping mechanism that maps a source view le path to a themed view
le path. For example, if the path map for a theme is
web/themes/basic'], then the themed version for the
/index.php will be /web/themes/basic/site/index.php.
['/web/views' => '/
/web/views/site
view le
For this reason, themes
can now be applied to any view le, even a view rendered outside of the
context of a controller or a widget.
8
CHAPTER 1.
INTRODUCTION
CThemeManager component. Instead, theme
view application component.
Also, there is no more
gurable property of the
is a con-
Please refer to the Theming section for more details.
1.2.13 Console Applications
Console applications are now organized as controllers, like Web applications.
Console controllers should extend from
to
CConsoleCommand
yii\console\Controller,
similar
in 1.1.
yii ,
To run a console command, use
controller route (e.g.
sitemap/index).
where
stands for a
Additional anonymous arguments are
passed as the parameters to the corresponding controller action method,
while named arguments are parsed according to the declarations in
\console\Controller::options().
yii
Yii 2.0 supports automatic generation of command help information from
comment blocks.
Please refer to the Console Commands section for more details.
1.2.14 I18N
Yii 2.0 removes the built-in date formatter and number formatter pieces in
favor of the PECL intl PHP module
12 .
Message translation is now performed via the
i18n
application compon-
ent. This component manages a set of message sources, which allows you to
use dierent message sources based on message categories.
Please refer to the Internationalization section for more details.
1.2.15 Action Filters
Action lters are implemented via behaviors now. To dene a new, custom
lter, extend from
yii\base\ActionFilter.
To use a lter, attach the lter
class to the controller as a behavior. For example, to use the
\AccessControl
yii\filters
lter, you would have the following code in a controller:
public function behaviors()
{
return [
'access' => [
'class' => 'yii\filters\AccessControl',
'rules' => [
['allow' => true, 'actions' => ['admin'], 'roles' => ['@']],
],
],
];
}
Please refer to the Filtering section for more details.
12
http://pecl.php.net/package/intl
1.2.
UPGRADING FROM VERSION 1.1
9
1.2.16 Assets
Yii 2.0 introduces a new concept called
asset bundle
that replaces the script
package concept found in Yii 1.1.
An asset bundle is a collection of asset les (e.g. JavaScript les, CSS
les, image les, etc.) within a directory. Each asset bundle is represented
yii\web\AssetBundle. By registering an asset bundle
yii\web\AssetBundle::register(), you make the assets in that bundle
as a class extending
via
accessible via the Web. Unlike in Yii 1, the page registering the bundle will
automatically contain the references to the JavaScript and CSS les specied
in that bundle.
Please refer to the Managing Assets section for more details.
1.2.17 Helpers
Yii 2.0 introduces many commonly used static helper classes, including.
•
•
•
•
•
yii\helpers\Html
yii\helpers\ArrayHelper
yii\helpers\StringHelper
yii\helpers\FileHelper
yii\helpers\Json
Please refer to the Helper Overview section for more details.
1.2.18 Forms
Yii 2.0 introduces the
\ActiveForm.
eld
concept for building a form using
yii\widgets
A eld is a container consisting of a label, an input, an er-
ror message, and/or a hint text. A eld is represented as an
\ActiveField
yii\widgets
object. Using elds, you can build a form more cleanly than
before:
= $form->field($model, 'username') ?>
= $form->field($model, 'password')->passwordInput() ?>
= Html::submitButton('Login') ?>
Please refer to the Creating Forms section for more details.
1.2.19 Query Builder
In 1.1, query building was scattered among several classes, including
,
CDbCriteria,
and
CDbCommandBuilder.
CDbCommand
Yii 2.0 represents a DB query in terms
yii\db\Query object that can be turned into a SQL statement with the
help of yii\db\QueryBuilder behind the scene. For example:
of a
10
CHAPTER 1.
INTRODUCTION
$query = new \yii\db\Query();
$query->select('id, name')
->from('user')
->limit(10);
$command = $query->createCommand();
$sql = $command->sql;
$rows = $command->queryAll();
Best of all, such query building methods can also be used when working with
Active Record.
Please refer to the Query Builder section for more details.
1.2.20 Active Record
Yii 2.0 introduces a lot of changes to Active Record. The two most obvious
ones involve query building and relational query handling.
The
yii\db\ActiveQuery in Yii 2.
yii\db\Query, and thus inherits all query building
You call yii\db\ActiveRecord::find() to start building a query:
CDbCriteria
class in 1.1 is replaced by
That class extends from
methods.
// To retrieve all *active* customers and order them by their ID:
$customers = Customer::find()
->where(['status' => $active])
->orderBy('id')
->all();
To declare a relation, simply dene a getter method that returns an
\ActiveQuery
yii\db
object. The property name dened by the getter represents
orders relation
place relations()):
the relation name. For example, the following code declares an
(in 1.1, you would have to declare relations in a central
class Customer extends \yii\db\ActiveRecord
{
public function getOrders()
{
return $this->hasMany('Order', ['customer_id' => 'id']);
}
}
Now you can use
$customer->orders
to access a customer's orders from the
related table. You can also use the following code to perform an on-the-y
relational query with a customized query condition:
$orders = $customer->getOrders()->andWhere('status=1')->all();
When eager loading a relation, Yii 2.0 does it dierently from 1.1. In particular, in 1.1 a JOIN query would be created to select both the primary and
the relational records. In Yii 2.0, two SQL statements are executed without
using JOIN: the rst statement brings back the primary records and the
second brings back the relational records by ltering with the primary keys
of the primary records.
1.2.
UPGRADING FROM VERSION 1.1
11
Instead of returning yii\db\ActiveRecord objects, you may chain the
yii\db\ActiveQuery::asArray() method when building a query to return
a large number of records. This will cause the query result to be returned
as arrays, which can signicantly reduce the needed CPU time and memory
if large number of records . For example:
$customers = Customer::find()->asArray()->all();
Another change is that you can't dene attribute default values through
public properties anymore.
If you need those, you should set them in the
init method of your record class.
public function init()
{
parent::init();
$this->status = self::STATUS_NEW;
}
There were some problems with overriding the constructor of an ActiveRecord
class in 1.1. These are not present in version 2.0 anymore. Note that when
adding parameters to the constructor you might have to override
\ActiveRecord::instantiate().
yii\db
There are many other changes and enhancements to Active Record.
Please refer to the Active Record section for more details.
1.2.21 Active Record Behaviors
In 2.0, we have dropped the base behavior class
CActiveRecordBehavior.
If you
want to create an Active Record Behavior, you will have to extend directly
from
yii\base\Behavior.
If the behavior class needs to respond to some events
of the owner, you have to override the
events()
method like the following:
namespace app\components;
use yii\db\ActiveRecord;
use yii\base\Behavior;
class MyBehavior extends Behavior
{
// ...
public function events()
{
return [
ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate',
];
}
public function beforeValidate($event)
{
// ...
}
12
CHAPTER 1.
INTRODUCTION
}
1.2.22 User and IdentityInterface
The
CWebUser class in 1.1 is
CUserIdentity class.
no more
\IdentityInterface
now replaced by
yii\web\User,
and there is
Instead, you should implement the
yii\web
which is much more straightforward to use. The ad-
vanced project template provides such an example.
Please refer to the Authentication, Authorization, and Advanced Project
Template
13 sections for more details.
1.2.23 URL Management
URL management in Yii 2 is similar to that in 1.1. A major enhancement
is that URL management now supports optional parameters. For example,
if you have a rule declared as follows, then it will match both
and
post/1/popular.
post/popular
In 1.1, you would have had to use two rules to achieve
the same goal.
[
]
'pattern' => 'post//',
'route' => 'post/index',
'defaults' => ['page' => 1],
Please refer to the Url manager docs section for more details.
An important change in the naming convention for routes is that camel
case names of controllers and actions are now converted to lower case where
each word is separated by a hypen, e.g. the controller id for the
will be
camel-case.
CamelCaseController
See the section about controller IDs and action IDs for
more details.
1.2.24 Using Yii 1.1 and 2.x together
If you have legacy Yii 1.1 code that you want to use together with Yii 2.0,
please refer to the Using Yii 1.1 and 2.0 Together section.
13
https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide/
README.md
Chapter 2
Getting Started
2.1 Installing Yii
1 package manager or by
You can install Yii in two ways, using the Composer
downloading an archive le. The former is the preferred way, as it allows you
to install new extensions or update Yii by simply running a single command.
Standard installations of Yii result in both the framework and a project
template being downloaded and installed. A project template is a working
Yii project implementing some basic features, such as login, contact form,
etc. Its code is organized in a recommended way. Therefore, it can serve as
a good starting point for your projects.
In this and the next few sections, we will describe how to install Yii with
the so-called
Basic Project Template
and how to implement new features on
top of this template. Yii also provides another template called the Advanced
Project Template
2 which is better used in a team development environment
to develop applications with multiple tiers.
Info: The Basic Project Template is suitable for developing 90
percent of Web applications. It diers from the Advanced Project
Template mainly in how their code is organized. If you are new
to Yii, we strongly recommend you stick to the Basic Project
Template for its simplicity yet sucient functionalities.
2.1.1 Installing via Composer
Installing Composer
If you do not already have Composer installed, you may do so by following
3
the instructions at getcomposer.org . On Linux and Mac OS X, you'll run
1
https://getcomposer.org/
https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide/
README.md
3
https://getcomposer.org/download/
2
13
14
CHAPTER 2.
GETTING STARTED
the following commands:
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
4
On Windows, you'll download and run Composer-Setup.exe .
Please refer to the Troubleshooting section of the Composer Documentation
5 if you encounter any problems.
If you are new to Composer, we
also recommend to read at least the Basic usage section
6 of the Composer
documentation.
In this guide all composer commands assume you have installed composer
globally
7 so that it is available as the composer command. If you are using the
composer.phar
in the local directory instead, you have to adjust the example
commands accordingly.
If you had Composer already installed before, make sure you use an up
to date version. You can update Composer by running
composer self-update.
Note: During the installation of Yii, Composer will need to request a lot of information from the Github API. The number of
requests depends on the number of dependencies your application has and may be bigger than the
Github API rate limit.
If you hit this limit, Composer may ask for your Github login
credentials to obtain a Github API access token. On fast connections you may hit this limit earlier than Composer can handle
so we recommend to congure the access token before installing
Yii. Please refer to the Composer documentation about Github
8 for instructions on how to do this.
API tokens
Installing Yii
With Composer installed, you can install Yii by running the following commands under a Web-accessible folder:
composer global require "fxp/composer-asset-plugin:^1.2.0"
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
The rst command installs the composer asset plugin
9 which allows man-
aging bower and npm package dependencies through Composer. You only
need to run this command once for all. The second command installs the
latest stable version of Yii in a directory named
basic.
You can choose a
dierent directory name if you want.
4
https://getcomposer.org/Composer-Setup.exe
https://getcomposer.org/doc/articles/troubleshooting.md
6
https://getcomposer.org/doc/01-basic-usage.md
7
https://getcomposer.org/doc/00-intro.md#globally
8
https://getcomposer.org/doc/articles/troubleshooting.md#
api-rate-limit-and-oauth-tokens
9
https://github.com/francoispluchino/composer-asset-plugin/
5
2.1.
INSTALLING YII
Info:
If the
15
composer create-project
command fails make sure
you have the composer asset plugin installed correctly. You can
composer global show,
fxp/composer-asset-plugin. You
do that by running
which should contain
an entry
may also refer to the
10 for
Troubleshooting section of the Composer Documentation
common errors. When you have xed the error, you can resume
the aborted installation by running
basic
composer update
inside of the
directory.
Tip: If you want to install the latest development version of
Yii, you may use the following command instead, which adds a
stability option
11 :
composer create-project --prefer-dist --stability=dev yiisoft/
yii2-app-basic basic
Note that the development version of Yii should not be used for
production as it may break your running code.
2.1.2 Installing from an Archive File
Installing Yii from an archive le involves three steps:
1. Download the archive le from yiiframework.com
12 .
2. Unpack the downloaded le to a Web-accessible folder.
3. Modify the
config/web.php le by entering a secret key for the cookieValidationKey
conguration item (this is done automatically if you are installing Yii
using Composer):
// !!! insert a secret key in the following (if it is empty) - this is
required by cookie validation
'cookieValidationKey' => 'enter your secret key here',
2.1.3 Other Installation Options
The above installation instructions show how to install Yii, which also creates
a basic Web application that works out of the box. This approach is a good
starting point for most projects, either small or big. It is especially suitable
if you just start learning Yii.
But there are other installation options available:
•
If you only want to install the core framework and would like to build
an entire application from scratch, you may follow the instructions as
explained in Building Application from Scratch.
10
https://getcomposer.org/doc/articles/troubleshooting.md
https://getcomposer.org/doc/04-schema.md#minimum-stability
12
http://www.yiiframework.com/download/
11
16
CHAPTER 2.
•
GETTING STARTED
If you want to start with a more sophisticated application, better suited
to team development environments, you may consider installing the
13 .
Advanced Project Template
2.1.4 Verifying the Installation
After installation is done, either congure your web server (see next section) or use the built-in PHP web server
command while in the project
web
14 by running the following console
directory:
php yii serve
Note: By default the HTTP-server will listen to port 8080. However if that port is already in use or you wish to serve multiple
applications this way, you might want to specify what port to
use. Just add the port argument:
php yii serve --port=8888
You can use your browser to access the installed Yii application with the
following URL:
http://localhost:8080/
You should see the above Congratulations! page in your browser.
If
not, please check if your PHP installation satises Yii's requirements. You
13
https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide/
README.md
14
https://secure.php.net/manual/en/features.commandline.webserver.php
2.1.
INSTALLING YII
17
can check if the minimum requirements are met using one of the following
approaches:
•
to
•
/requirements.php to /web/requirements.php and
access it via http://localhost/requirements.php
Copy
then use a browser
Run the following commands:
cd basic
php requirements.php
You should congure your PHP installation so that it meets the minimum
requirements of Yii. Most importantly, you should have PHP 5.4 or above.
15 and
Ideally latest PHP 7. You should also install the PDO PHP Extension
a corresponding database driver (such as
pdo_mysql
for MySQL databases),
if your application needs a database.
2.1.5 Conguring Web Servers
Info: You may skip this subsection for now if you are just test
driving Yii with no intention of deploying it to a production
server.
The application installed according to the above instructions should work out
of box with either an Apache HTTP server
16 or an Nginx HTTP server17 ,
on Windows, Mac OS X, or Linux running PHP 5.4 or higher. Yii 2.0 is also
18 . However, there are some edge cases
compatible with facebook's HHVM
where HHVM behaves dierent than native PHP, so you have to take some
extra care when using HHVM.
On a production server, you may want to congure your Web server
http://www.example.com
http://www.example.com/basic/web/index.php. Such con-
so that the application can be accessed via the URL
/index.php
instead of
guration requires pointing the document root of your Web server to the
basic/web
folder. You may also want to hide
index.php
from the URL, as de-
scribed in the Routing and URL Creation section. In this subsection, you'll
learn how to congure your Apache or Nginx server to achieve these goals.
Info: By setting basic/web as the document root, you also prevent end users from accessing your private application code and
sensitive data les that are stored in the sibling directories of
basic/web.
Denying access to those other folders is a security
improvement.
Info:
If your application will run in a shared hosting envir-
onment where you do not have permission to modify its Web
15
http://www.php.net/manual/en/pdo.installation.php
http://httpd.apache.org/
17
http://nginx.org/
18
http://hhvm.com/
16
18
CHAPTER 2.
GETTING STARTED
server conguration, you may still adjust the structure of your
application for better security. Please refer to the Shared Hosting
Environment section for more details.
Recommended Apache Conguration
Use the following conguration in Apache's
httpd.conf le or within
path/to/basic/web
host conguration. Note that you should replace
actual path for
a virtual
with the
basic/web.
# Set document root to be "basic/web"
DocumentRoot "path/to/basic/web"
# use mod_rewrite for pretty URL support
RewriteEngine on
# If a directory or a file exists, use the request directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Otherwise forward the request to index.php
RewriteRule . index.php
# ...other settings...
Recommended Nginx Conguration
To use Nginx
19 , you should install PHP as an FPM SAPI20 . You may use
the following Nginx conguration, replacing
path for
basic/web
and
mysite.local
path/to/basic/web with the actual
with the actual hostname to serve.
server {
charset utf-8;
client_max_body_size 128M;
listen 80; ## listen for ipv4
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6
server_name mysite.local;
root
/path/to/basic/web;
index
index.php;
access_log /path/to/basic/log/access.log;
error_log /path/to/basic/log/error.log;
location / {
# Redirect everything that isn't a real file to index.php
try_files $uri $uri/ /index.php$is_args$args;
}
19
20
http://wiki.nginx.org/
http://php.net/install.fpm
2.2.
RUNNING APPLICATIONS
19
# uncomment to avoid processing of calls to non-existing static files by
Yii
#location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
#
try_files $uri =404;
#}
#error_page 404 /404.html;
# deny accessing php files for the /assets directory
location ~ ^/assets/.*\.php$ {
deny all;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
#fastcgi_pass unix:/var/run/php5-fpm.sock;
try_files $uri =404;
}
}
location ~* /\. {
deny all;
}
When using this conguration, you should also set
php.ini
cgi.fix_pathinfo=0
stat() calls.
in the
le in order to avoid many unnecessary system
Also note that when running an HTTPS server, you need to add
HTTPS on;
fastcgi_param
so that Yii can properly detect if a connection is secure.
2.2 Running Applications
After installing Yii, you have a working Yii application that can be accessed via the URL
index.php,
http://hostname/basic/web/index.php
depending upon your conguration.
or
http://hostname/
This section will introduce
the application's built-in functionality, how the code is organized, and how
the application handles requests in general.
Info: For simplicity, throughout this Getting Started tutorial,
it's assumed that you have set
basic/web
as the document root
of your Web server, and congured the URL for accessing your
application to be
http://hostname/index.php
or something similar.
For your needs, please adjust the URLs in our descriptions accordingly.
Note that unlike framework itself, after project template is installed it's all
yours. You're free to add or delete code and overall modify it as you need.
20
CHAPTER 2.
GETTING STARTED
2.2.1 Functionality
The basic application installed contains four pages:
•
the homepage, displayed when you access the URL
•
•
the About page,
http://hostname/
index.php,
the Contact page, which displays a contact form that allows end users
to contact you via email,
•
and the Login page, which displays a login form that can be used to
authenticate end users. Try logging in with admin/admin, and you
will nd the Login main menu item will change to Logout.
These pages share a common header and footer. The header contains a main
menu bar to allow navigation among dierent pages.
You should also see a toolbar at the bottom of the browser window.
This is a useful debugger tool
21 provided by Yii to record and display a
lot of debugging information, such as log messages, response statuses, the
database queries run, and so on.
Additionally to the web application, there is a console script called
yii,
which is located in the applications base directory. This script can be used
to run background and maintenance tasks for the application, which are
described in the Console Application Section.
2.2.2 Application Structure
The most important directories and les in your application are (assuming
the application's root directory is
basic):
basic/
application base path
composer.json
used by Composer, describes package information
config/
contains application and other configurations
console.php
the console application configuration
web.php
the Web application configuration
commands/
contains console command classes
controllers/
contains controller classes
models/
contains model classes
runtime/
contains files generated by Yii during runtime, such
as logs and cache files
vendor/
contains the installed Composer packages, including
the Yii framework itself
views/
contains view files
web/
application Web root, contains Web accessible files
assets/
contains published asset files (javascript and css)
by Yii
index.php
the entry (or bootstrap) script for the application
yii
the Yii console command execution script
In general, the les in the application can be divided into two types: those
under
21
basic/web and those under other directories.
The former can be directly
https://github.com/yiisoft/yii2-debug/blob/master/docs/guide/README.md
2.2.
RUNNING APPLICATIONS
21
accessed via HTTP (i.e., in a browser), while the latter can not and should
not be.
22 architectural pattern,
Yii implements the model-view-controller (MVC)
which is reected in the above directory organization. The
contains all model classes, the
the
controllers
views
models
directory
directory contains all view scripts, and
directory contains all controller classes.
The following diagram shows the static structure of an application.
Each application has an entry script
web/index.php
which is the only Web
accessible PHP script in the application. The entry script takes an incoming
request and creates an application instance to handle it.
The application
resolves the request with the help of its components, and dispatches the
request to the MVC elements. Widgets are used in the views to help build
complex and dynamic user interface elements.
2.2.3 Request Lifecycle
The following diagram shows how an application handles a request.
22
http://wikipedia.org/wiki/Model-view-controller
22
CHAPTER 2.
1. A user makes a request to the entry script
GETTING STARTED
web/index.php.
2. The entry script loads the application conguration and creates an
application instance to handle the request.
3. The application resolves the requested route with the help of the request application component.
4. The application creates a controller instance to handle the request.
5. The controller creates an action instance and performs the lters for
the action.
6. If any lter fails, the action is cancelled.
7. If all lters pass, the action is executed.
8. The action loads a data model, possibly from a database.
9. The action renders a view, providing it with the data model.
10. The rendered result is returned to the response application component.
11. The response component sends the rendered result to the user's browser.
2.3.
SAYING HELLO
23
2.3 Saying Hello
This section describes how to create a new Hello page in your application.
To achieve this goal, you will create an action and a view:
•
•
The application will dispatch the page request to the action
and the action will in turn render the view that shows the word Hello
to the end user.
Through this tutorial, you will learn three things:
1. how to create an action to respond to requests,
2. how to create a view to compose the response's content, and
3. how an application dispatches requests to actions.
2.3.1 Creating an Action
For the Hello task, you will create a
say
action that reads a
message
para-
meter from the request and displays that message back to the user. If the
request does not provide a
message
parameter, the action will display the
default Hello message.
Info: Actions are the objects that end users can directly refer to
for execution. Actions are grouped by controllers. The execution
result of an action is the response that an end user will receive.
Actions must be declared in controllers. For simplicity, you may declare the
say
SiteController. This
controllers/SiteController.php. Here is
action in the existing
class le
controller is dened in the
the start of the new action:
render('say', ['message' => $message]);
}
In the above code, the
in the
SiteController
say
action is dened as a method named
class. Yii uses the prex
action
actionSay
to dierentiate action
methods from non-action methods in a controller class. The name after the
action
prex maps to the action's ID.
24
CHAPTER 2.
GETTING STARTED
When it comes to naming your actions, you should understand how Yii
treats action IDs. Action IDs are always referenced in lower case. If an action
ID requires multiple words, they will be concatenated by dashes (e.g.,
-comment).
create
Action method names are mapped to action IDs by removing any
dashes from the IDs, capitalizing the rst letter in each word, and prexing
action.
the resulting string with
The action method in our example
value defaults to
"Hello"
create-comment
actionCreateComment.
takes a parameter $message, whose
For example, the action ID
corresponds to the action method name
(in exactly the same way you set a default value for
any function or method argument in PHP). When the application receives a
request and determines that the
say
action is responsible for handling said
request, the application will populate this parameter with the same named
parameter found in the request.
In other words, if the request includes a
message
"Goodbye",
parameter with a value of
the
$message
variable within the
action will be assigned that value.
Within the action method,
render a view le named
say.
yii\web\Controller::render() is called to
The
message
parameter is also passed to the
view so that it can be used there. The rendering result is returned by the
action method. That result will be received by the application and displayed
to the end user in the browser (as part of a complete HTML page).
2.3.2 Creating a View
Views are scripts you write to generate a response's content. For the Hello
task, you will create a
say
view that prints the
message
parameter received
from the action method:
= Html::encode($message) ?>
The
say view should be saved in the le views/site/say.php.
When the method
yii\web\Controller::render() is called in an action, it will look for a PHP
le named as
Note that
::encode()
views/ControllerID/ViewName.php.
in the above code, the message parameter
is
yii\helpers\Html
before being printed. This is necessary as the parameter comes
23
from an end user, making it vulnerable to cross-site scripting (XSS) attacks
by embedding malicious JavaScript code in the parameter.
Naturally, you may put more content in the
say
view. The content can
consist of HTML tags, plain text, and even PHP statements. In fact, the
view is just a PHP script that is executed by the
render() method.
say
yii\web\Controller::
The content printed by the view script will be returned to
the application as the response's result. The application will in turn output
this result to the end user.
23
http://en.wikipedia.org/wiki/Cross-site_scripting
2.3.
SAYING HELLO
25
2.3.3 Trying it Out
After creating the action and the view, you may access the new page by
accessing the following URL:
http://hostname/index.php?r=site%2Fsay&message=Hello+World
This URL will result in a page displaying Hello World. The page shares
the same header and footer as the other application pages.
If you omit the
message
parameter in the URL, you would see the page
display just Hello. This is because
actionSay()
message
is passed as a parameter to the
method, and when it is omitted, the default value of
"Hello"
will
be used instead.
Info: The new page shares the same header and footer as other
pages because the
yii\web\Controller::render() method will
say view in a so-called
views/layouts/main.php.
automatically embed the result of the
layout which in this case is located at
The
r
parameter in the above URL requires more explanation. It stands for
route, an application wide unique ID that refers to an action. The route's
format is
ControllerID/ActionID.
When the application receives a request, it
will check this parameter, using the
ControllerID
part to determine which
controller class should be instantiated to handle the request.
controller will use the
ActionID
Then, the
part to determine which action should be
instantiated to do the real work.
In this example case, the route
SiteController controller class and the say
SiteController::actionSay() method will be called to
site/say
will be resolved to the
action. As
a result, the
handle the
request.
26
CHAPTER 2.
GETTING STARTED
Info: Like actions, controllers also have IDs that uniquely identify
them in an application. Controller IDs use the same naming rules
as action IDs. Controller class names are derived from controller
IDs by removing dashes from the IDs, capitalizing the rst letter
in each word, and suxing the resulting string with the word
Controller.
post-comment
PostCommentController.
For example, the controller ID
ponds to the controller class name
corres-
2.3.4 Summary
In this section, you have touched the controller and view parts of the MVC
architectural pattern. You created an action as part of a controller to handle
a specic request. And you also created a view to compose the response's
content.
In this simple example, no model was involved as the only data
used was the
message
parameter.
You have also learned about routes in Yii, which act as the bridge between
user requests and controller actions.
In the next section, you will learn how to create a model, and add a new
page containing an HTML form.
2.4 Working with Forms
This section describes how to create a new page with a form for getting data
from users.
The page will display a form with a name input eld and an
email input eld.
After getting those two pieces of information from the
user, the page will echo the entered values back for conrmation.
To achieve this goal, besides creating an action and two views, you will
also create a model.
Through this tutorial, you will learn how to:
•
•
•
create a model to represent the data entered by a user through a form,
declare rules to validate the data entered,
build an HTML form in a view.
2.4.1 Creating a Model
EntryForm
models/EntryForm.php. Please
The data to be requested from the user will be represented by an
model class as shown below and saved in the le
refer to the Class Autoloading section for more details about the class le
naming convention.
name = 'Qiang';
$model->email = 'bad';
if ($model->validate()) {
// Good!
} else {
// Failure!
// Use $model->getErrors()
}
2.4.2 Creating an Action
Next, you'll need to create an
entry
action in the
site
controller that will use
the new model. The process of creating and using actions was explained in
the Saying Hello section.
28
CHAPTER 2.
GETTING STARTED
load(Yii::$app->request->post()) && $model->validate())
{
// valid data received in $model
// do something meaningful here about $model ...
}
return $this->render('entry-confirm', ['model' => $model]);
} else {
// either the page is initially displayed or there is some
validation error
return $this->render('entry', ['model' => $model]);
}
}
The action rst creates an
model with the data from
post().
EntryForm object. It then tries to populate the
$_POST, provided in Yii by yii\web\Request::
If the model is successfully populated (i.e., if the user has submitted
the HTML form), the action will call
yii\base\Model::validate() to make
sure the values entered are valid.
Info:
The expression
Yii::$app
represents the application in-
stance, which is a globally accessible singleton. It is also a service locator that provides components such as
db, etc. to support
request component
the $_POST data.
request, response,
specic functionality. In the above code, the
of the application instance is used to access
If everything is ne, the action will render a view named
entry-confirm
to
conrm the successful submission of the data to the user. If no data is submitted or the data contains errors, the
entry
view will be rendered, wherein
the HTML form will be shown, along with any validation error messages.
Note:
In this very simple example we just render the con-
rmation page upon valid data submission.
In practice, you
2.4.
WORKING WITH FORMS
29
yii\web\Controller::refresh() or yii
\web\Controller::redirect() to avoid form resubmission prob-
should consider using
24 .
lems
2.4.3 Creating Views
Finally, create two view les named
rendered by the
The
entry
entry-confirm
and
entry.
These will be
action, as just described.
entry-confirm
view simply displays the name and email data.
should be stored in the le
It
views/site/entry-confirm.php.
You have entered the following information:
- : = Html::encode($model->name) ?>
- : = Html::encode($model->email) ?>
entry view displays
views/site/entry.php.
The
an HTML form.
It should be stored in the le
= $form->field($model, 'name') ?>
= $form->field($model, 'email') ?>
= Html::submitButton('Submit', ['class' => 'btn btn-primary']) ?>
The view uses a powerful widget called
the HTML form. The
begin()
and
yii\widgets\ActiveForm
end()
to build
methods of the widget render the
opening and closing form tags, respectively. Between the two method calls,
input elds are created by the
yii\widgets\ActiveForm::field() method.
The rst input eld is for the name data, and the second for the email
data. After the input elds, the
yii\helpers\Html::submitButton() method
is called to generate a submit button.
24
http://en.wikipedia.org/wiki/Post/Redirect/Get
30
CHAPTER 2.
GETTING STARTED
2.4.4 Trying it Out
To see how it works, use your browser to access the following URL:
http://hostname/index.php?r=site%2Fentry
You will see a page displaying a form with two input elds.
In front of
each input eld, a label indicates what data is to be entered. If you click
the submit button without entering anything, or if you do not provide a
valid email address, you will see an error message displayed next to each
problematic input eld.
After entering a valid name and email address and clicking the submit
button, you will see a new page displaying the data that you just entered.
2.4.
WORKING WITH FORMS
31
Magic Explained
You may wonder how the HTML form works behind the scene, because it
seems almost magical that it can display a label for each input eld and show
error messages if you do not enter the data correctly without reloading the
page.
Yes, the data validation is initially done on the client-side using JavaScript, and secondarily performed on the server-side via PHP.
\ActiveForm
declared in
yii\widgets
is smart enough to extract the validation rules that you have
EntryForm,
turn them into executable JavaScript code, and use the
JavaScript to perform data validation. In case you have disabled JavaScript
on your browser, the validation will still be performed on the server-side, as
shown in the
actionEntry()
method. This ensures data validity in all circum-
stances.
Warning: Client-side validation is a convenience that provides
for a better user experience. Server-side validation is always required, whether or not client-side validation is in place.
The labels for input elds are generated by the
field() method, using the
Name will be generated
property names from the model. For example, the label
for the
name
property.
You may customize a label within a view using the following code:
= $form->field($model, 'name')->label('Your Name') ?>
= $form->field($model, 'email')->label('Your Email') ?>
32
CHAPTER 2.
GETTING STARTED
Info: Yii provides many such widgets to help you quickly build
complex and dynamic views.
As you will learn later, writing
a new widget is also extremely easy.
You may want to turn
much of your view code into reusable widgets to simplify view
development in future.
2.4.5 Summary
In this section of the guide, you have touched every part in the MVC architectural pattern. You have learned how to create a model class to represent
the user data and validate said data.
You have also learned how to get data from users and how to display
data back in the browser. This is a task that could take you a lot of time
when developing an application, but Yii provides powerful widgets to make
this task very easy.
In the next section, you will learn how to work with databases, which
are needed in nearly every application.
2.5 Working with Databases
This section will describe how to create a new page that displays country
data fetched from a database table named
country.
To achieve this goal, you
will congure a database connection, create an Active Record class, dene
an action, and create a view.
Through this tutorial, you will learn how to:
•
•
•
•
congure a DB connection,
dene an Active Record class,
query data using the Active Record class,
display data in a view in a paginated fashion.
Note that in order to nish this section, you should have basic knowledge and
experience using databases. In particular, you should know how to create a
database, and how to execute SQL statements using a DB client tool.
2.5.1 Preparing the Database
To begin, create a database named
yii2basic,
from which you will fetch
data in your application. You may create an SQLite, MySQL, PostgreSQL,
MSSQL or Oracle database, as Yii has built-in support for many database
applications.
For simplicity, MySQL will be assumed in the following de-
scription.
Next, create a table named
country
in the database, and insert some
sample data. You may run the following SQL statements to do so:
CREATE TABLE `country` (
`code` CHAR(2) NOT NULL PRIMARY KEY,
2.5.
WORKING WITH DATABASES
33
`name` CHAR(52) NOT NULL,
`population` INT(11) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
`country`
`country`
`country`
`country`
`country`
`country`
`country`
`country`
`country`
`country`
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
('AU','Australia',24016400);
('BR','Brazil',205722000);
('CA','Canada',35985751);
('CN','China',1375210000);
('DE','Germany',81459000);
('FR','France',64513242);
('GB','United Kingdom',65097000);
('IN','India',1285400000);
('RU','Russia',146519759);
('US','United States',322976000);
At this point, you have a database named
yii2basic,
and within it a
country
table with three columns, containing ten rows of data.
2.5.2 Conguring a DB Connection
25 PHP ex-
Before proceeding, make sure you have installed both the PDO
tension and the PDO driver for the database you are using (e.g.
pdo_mysql
for MySQL). This is a basic requirement if your application uses a relational
database.
With those installed, open the le
config/db.php
meters to be correct for your database.
and change the para-
By default, the le contains the
following:
'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=yii2basic',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
];
The
config/db.php
le is a typical le-based conguration tool. This particu-
lar conguration le species the parameters needed to create and initialize
a
yii\db\Connection
instance through which you can make SQL queries
against the underlying database.
The DB connection congured above can be accessed in the application
code via the expression
Yii::$app->db.
Info: The config/db.php le will be included by the main application conguration
config/web.php,
which species how the
application instance should be initialized. For more information,
please refer to the Congurations section.
25
http://www.php.net/manual/en/book.pdo.php
34
CHAPTER 2.
GETTING STARTED
If you need to work with databases support for which isn't bundled with Yii,
check the following extensions:
26
•
•
•
Informix
27
IBM DB2
28
Firebird
2.5.3 Creating an Active Record
To represent and fetch the data in the
derived class named
Country,
country table,
and save it in the le
create an Active Record-
models/Country.php.
orderBy('name')->all();
// get the row whose primary key is "US"
$country = Country::findOne('US');
// displays "United States"
echo $country->name;
// modifies the country name to be "U.S.A." and save it to database
$country->name = 'U.S.A.';
$country->save();
26
https://github.com/edgardmessias/yii2-informix
https://github.com/edgardmessias/yii2-ibm-db2
28
https://github.com/edgardmessias/yii2-firebird
27
table,
2.5.
WORKING WITH DATABASES
35
Info: Active Record is a powerful way to access and manipulate
database data in an object-oriented fashion. You may nd more
detailed information in the Active Record section. Alternatively,
you may also interact with a database using a lower-level data
accessing method called Data Access Objects.
2.5.4 Creating an Action
To expose the country data to end users, you need to create a new action.
Instead of placing the new action in the
site
controller, like you did in the
previous sections, it makes more sense to create a new controller specically for all actions related to the country data.
CountryController,
and create an
index
Name this new controller
action in it, as shown in the following.
5,
'totalCount' => $query->count(),
]);
$countries = $query->orderBy('name')
->offset($pagination->offset)
->limit($pagination->limit)
->all();
}
}
return $this->render('index', [
'countries' => $countries,
'pagination' => $pagination,
]);
controllers/CountryController.php.
The index action calls Country::find(). This Active Record method builds
DB query and retrieves all of the data from the country table. To limit the
Save the above code in the le
a
number of countries returned in each request, the query is paginated with
the help of a
purposes:
yii\data\Pagination object.
The
Pagination
object serves two
36
CHAPTER 2.
•
Sets the
offset
and
limit
GETTING STARTED
clauses for the SQL statement represented
by the query so that it only returns a single page of data at a time (at
most 5 rows in a page).
•
It's used in the view to display a pager consisting of a list of page
buttons, as will be explained in the next subsection.
At the end of the code, the
index
action renders a view named
index,
and
passes the country data as well as the pagination information to it.
2.5.5 Creating a View
Under the
views
country. This
country controller.
index.php containing
directory, rst create a sub-directory named
folder will be used to hold all the views rendered by the
Within the
views/country
directory, create a le named
the following:
Countries
-
= Html::encode("{$country->name} ({$country->code})") ?>:
= $country->population ?>
= LinkPager::widget(['pagination' => $pagination]) ?>
The view has two sections relative to displaying the country data.
In the
rst part, the provided country data is traversed and rendered as an unordered HTML list. In the second part, a
yii\widgets\LinkPager
widget
is rendered using the pagination information passed from the action. The
LinkPager
widget displays a list of page buttons. Clicking on any of them will
refresh the country data in the corresponding page.
2.5.6 Trying it Out
To see how all of the above code works, use your browser to access the
following URL:
http://hostname/index.php?r=country%2Findex
2.5.
WORKING WITH DATABASES
37
At rst, you will see a page showing ve countries. Below the countries,
you will see a pager with four buttons. If you click on the button 2, you
will see the page display another ve countries in the database: the second
page of records. Observe more carefully and you will nd that the URL in
the browser also changes to
http://hostname/index.php?r=country%2Findex&page=2
Behind the scenes,
yii\data\Pagination
is providing all of the necessary
functionality to paginate a data set:
•
Initially,
yii\data\Pagination represents the rst page, which reects
the country SELECT query with the clause
LIMIT 5 OFFSET 0.
As a
result, the rst ve countries will be fetched and displayed.
•
The
yii\widgets\LinkPager widget renders the page buttons using
yii\data\Pagination::createUrl(). The URLs
the URLs created by
will contain the query parameter
page,
which represents the dierent
page numbers.
•
If you click the page button 2, a new request for the route country/
index will be triggered and handled. yii\data\Pagination reads the
page query parameter from the URL and sets the current page number
to 2. The new country query will thus have the clause LIMIT 5 OFFSET 5
and return the next ve countries for display.
38
CHAPTER 2.
GETTING STARTED
2.5.7 Summary
In this section, you learned how to work with a database. You also learned
how to fetch and display data in pages with the help of
and
yii\widgets\LinkPager.
yii\data\Pagination
In the next section, you will learn how to use the powerful code gen-
29 , to help you rapidly implement some commonly
eration tool, called Gii
required features, such as the Create-Read-Update-Delete (CRUD) operations for working with the data in a database table. As a matter of fact, the
code you have just written can all be automatically generated in Yii using
the Gii tool.
2.6 Generating Code with Gii
30 to automatically generate code
This section will describe how to use Gii
that implements some common Web site features. Using Gii to auto-generate
code is simply a matter of entering the right information per the instructions
shown on the Gii Web pages.
Through this tutorial, you will learn how to:
•
•
•
enable Gii in your application,
use Gii to generate an Active Record class,
use Gii to generate the code implementing the CRUD operations for a
DB table,
•
customize the code generated by Gii.
2.6.1 Starting Gii
Gii
31 is provided in Yii as a module. You can enable Gii by conguring it in
the
yii\base\Application::modules property of the application.
Depend-
ing upon how you created your application, you may nd the following code
is already provided in the
config/web.php
conguration le:
$config = [ ... ];
if (YII_ENV_DEV) {
$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = [
'class' => 'yii\gii\Module',
];
}
The above conguration states that when in development environment, the
application should include a module named
\Module.
29
gii,
which is of class
yii\gii
https://github.com/yiisoft/yii2-gii/blob/master/docs/guide/README.md
https://github.com/yiisoft/yii2-gii/blob/master/docs/guide/README.md
31
https://github.com/yiisoft/yii2-gii/blob/master/docs/guide/README.md
30
2.6.
GENERATING CODE WITH GII
If you check the entry script
web/index.php
nd the following line, which essentially makes
39
of your application, you will
YII_ENV_DEV
to be
true.
defined('YII_ENV') or define('YII_ENV', 'dev');
Thanks to that line, your application is in development mode, and will have
already enabled Gii, per the above conguration. You can now access Gii
via the following URL:
http://hostname/index.php?r=gii
Note: If you are accessing Gii from a machine other than localhost, the access will be denied by default for security purpose.
You can congure Gii to add the allowed IP addresses as follows,
'gii' => [
'class' => 'yii\gii\Module',
'allowedIPs' => ['127.0.0.1', '::1', '192.168.0.*', '
192.168.178.20'] // adjust this to your needs
],
2.6.2 Generating an Active Record Class
To use Gii to generate an Active Record class, select the Model Generator
(by clicking the link on the Gii index page). Then ll out the form as follows:
•
•
Table Name:
Model Class:
country
Country
40
CHAPTER 2.
GETTING STARTED
Next, click on the Preview button. You will see
models/Country.php
is
listed in the resulting class le to be created. You may click on the name of
the class le to preview its content.
When using Gii, if you have already created the same le and would be
overwriting it, click the
diff button next to the le name to see the dierences
between the code to be generated and the existing version.
2.6.
GENERATING CODE WITH GII
41
When overwriting an existing le, check the box next to overwrite and
then click the Generate button. If creating a new le, you can just click
Generate.
Next, you will see a conrmation page indicating the code has been
successfully generated. If you had an existing le, you'll also see a message
indicating that it was overwritten with the newly generated code.
2.6.3 Generating CRUD Code
CRUD stands for Create, Read, Update, and Delete, representing the four
common tasks taken with data on most Web sites. To create CRUD functionality using Gii, select the CRUD Generator (by clicking the link on the
Gii index page).
For the country example, ll out the resulting form as
follows:
•
•
•
app\models\Country
app\models\CountrySearch
Class: app\controllers\CountryController
Model Class:
Search Model Class:
Controller
42
CHAPTER 2.
Next, click on the Preview button.
GETTING STARTED
You will see a list of les to be
generated, as shown below.
If you previously created the
/country/index.php
controllers/CountryController.php
views
les (in the databases section of the guide), check the
overwrite box to replace them.
CRUD support.)
and
(The previous versions did not have full
2.6.
GENERATING CODE WITH GII
43
2.6.4 Trying it Out
To see how it works, use your browser to access the following URL:
http://hostname/index.php?r=country%2Findex
You will see a data grid showing the countries from the database table. You
may sort the grid, or lter it by entering lter conditions in the column
headers.
For each country displayed in the grid, you may choose to view its details,
update it, or delete it. You may also click on the Create Country button
on top of the grid to be provided with a form for creating a new country.
44
CHAPTER 2.
GETTING STARTED
The following is the list of the les generated by Gii, in case you want to
investigate how these features are implemented, or to customize them:
•
•
•
controllers/CountryController.php
models/Country.php and models/CountrySearch.php
views/country/*.php
Controller:
Models:
Views:
Info: Gii is designed to be a highly customizable and extensible
code generation tool. Using it wisely can greatly accelerate your
application development speed. For more details, please refer to
32 section.
the Gii
2.6.5 Summary
In this section, you have learned how to use Gii to generate the code that
implements complete CRUD functionality for content stored in a database
table.
2.7 Looking Ahead
If you've read through the entire Getting Started chapter, you have now
created a complete Yii application. In the process, you have learned how to
implement some commonly needed features, such as getting data from users
via an HTML form, fetching data from a database, and displaying data in a
32
https://github.com/yiisoft/yii2-gii/blob/master/docs/guide/README.md
2.7.
LOOKING AHEAD
45
33 to generate code
paginated fashion. You have also learned how to use Gii
automatically.
Using Gii for code generation turns the bulk of your Web
development process into a task as simple as just lling out some forms.
This section will summarize the Yii resources available to help you be
more productive when using the framework.
•
Documentation
The Denitive Guide34 : As the name indicates, the guide precisely
denes how Yii should work and provides general guidance about
using Yii. It is the single most important Yii tutorial, and one
that you should read before writing any Yii code.
The Class Reference35 : This species the usage of every class
provided by Yii.
It should be mainly used when you are writ-
ing code and want to understand the usage of a particular class,
method, property. Usage of the class reference is best only after
a contextual understanding of the entire framework.
The Wiki Articles36 : The wiki articles are written by Yii users
based on their own experiences.
Most of them are written like
cookbook recipes, and show how to solve particular problems using Yii. While the quality of these articles may not be as good as
the Denitive Guide, they are useful in that they cover broader
topics and can often provide ready-to-use solutions.
•
Books37
38
Extensions : Yii boasts a library of thousands of user-contributed
extensions that can be easily plugged into your applications, thereby
making your application development even faster and easier.
•
Community
Forum:
http://www.yiiframework.com/forum/
IRC chat: The #yii channel on the freenode network (irc://
irc.freenode.net/yii)
https://gitter.im/yiisoft/yii2
GitHub: https://github.com/yiisoft/yii2
Facebook: https://www.facebook.com/groups/yiitalk/
Twitter: https://twitter.com/yiiframework
LinkedIn: https://www.linkedin.com/groups/yii-framework-1483367
Stackoverow: http://stackoverflow.com/questions/tagged/
yii2
Gitter chat:
33
https://github.com/yiisoft/yii2-gii/blob/master/docs/guide/README.md
http://www.yiiframework.com/doc-2.0/guide-README.html
35
http://www.yiiframework.com/doc-2.0/index.html
36
http://www.yiiframework.com/wiki/?tag=yii2
37
http://www.yiiframework.com/doc/
38
http://www.yiiframework.com/extensions/
34
46
CHAPTER 2.
GETTING STARTED
Chapter 3
Application Structure
3.1 Overview
1
Yii applications are organized according to the model-view-controller (MVC)
architectural pattern. Models represent data, business logic and rules; views
are output representation of models; and controllers take input and convert
it to commands for models and views.
Besides MVC, Yii applications also have the following entities:
•
entry scripts: they are PHP scripts that are directly accessible by end
users. They are responsible for starting a request handling cycle.
•
applications: they are globally accessible objects that manage application components and coordinate them to fulll requests.
•
application components: they are objects registered with applications
and provide various services for fullling requests.
•
modules: they are self-contained packages that contain complete MVC
by themselves. An application can be organized in terms of multiple
modules.
•
lters: they represent code that need to be invoked before and after
the actual handling of each request by controllers.
•
widgets: they are objects that can be embedded in views. They may
contain controller logic and can be reused in dierent views.
The following diagram shows the static structure of an application:
1
http://wikipedia.org/wiki/Model-view-controller
47
48
CHAPTER 3.
APPLICATION STRUCTURE
3.2 Entry Scripts
Entry scripts are the rst step in the application bootstrapping process. An
application (either Web application or console application) has a single entry
script. End users make requests to entry scripts which instantiate application
instances and forward the requests to them.
Entry scripts for Web applications must be stored under Web accessible
directories so that they can be accessed by end users. They are often named
as
index.php,
but can also use any other names, provided Web servers can
locate them.
Entry scripts for console applications are usually stored under the base
path of applications and are named as
yii (with the .php sux).
They should
be made executable so that users can run console applications through the
command
./yii [arguments] [options].
Entry scripts mainly do the following work:
•
•
•
•
•
2
Dene global constants;
2
Register Composer autoloader ;
Include the
Yii
class le;
Load application conguration;
Create and congure an application instance;
https://getcomposer.org/doc/01-basic-usage.md#autoloading
3.2.
•
ENTRY SCRIPTS
Call
yii\base\Application::run()
49
to process the incoming request.
3.2.1 Web Applications
The following is the code in the entry script for the Basic Web Project
Template.
run();
3.2.2 Console Applications
Similarly, the following is the code for the entry script of a console application:
#!/usr/bin/env php
run();
50
CHAPTER 3.
APPLICATION STRUCTURE
exit($exitCode);
3.2.3 Dening Constants
Entry scripts are the best place for dening global constants. Yii supports
the following three constants:
• YII_DEBUG:
species whether the application is running in debug mode.
When in debug mode, an application will keep more log information,
and will reveal detailed error call stacks if exceptions are thrown. For
this reason, debug mode should be used mainly during development.
The default value of
• YII_ENV:
YII_DEBUG
is
false.
species which environment the application is running in. This
will be described in more detail in the Congurations section.
default value of
YII_ENV
is
'prod',
The
meaning the application is running
in production environment.
• YII_ENABLE_ERROR_HANDLER:
species whether to enable the error handler
provided by Yii. The default value of this constant is
true.
When dening a constant, we often use the code like the following:
defined('YII_DEBUG') or define('YII_DEBUG', true);
which is equivalent to the following code:
if (!defined('YII_DEBUG')) {
define('YII_DEBUG', true);
}
Clearly the former is more succinct and easier to understand.
Constant denitions should be done at the very beginning of an entry
script so that they can take eect when other PHP les are being included.
3.3 Applications
Applications are objects that govern the overall structure and lifecycle of Yii
application systems. Each Yii application system contains a single application object which is created in the entry script and is globally accessible
through the expression
\Yii::$app.
Info: Depending on the context, when we say an application, it
can mean either an application object or an application system.
There are two types of applications:
\Application.
yii\web\Application and yii\console
As the names indicate, the former mainly handles Web re-
quests, while the latter handles console command requests.
3.3.
APPLICATIONS
51
3.3.1 Application Congurations
When an entry script creates an application, it will load a conguration and
apply it to the application, as follows:
require(__DIR__ . '/../vendor/autoload.php');
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
// load application configuration
$config = require(__DIR__ . '/../config/web.php');
// instantiate and configure the application
(new yii\web\Application($config))->run();
Like normal congurations, application congurations specify how to initialize properties of application objects. Because application congurations
are often very complex, they usually are kept in conguration les, like the
web.php
le in the above example.
3.3.2 Application Properties
There are many important application properties that you should congure
in application congurations. These properties typically describe the environment that applications are running in. For example, applications need to
know how to load controllers, where to store temporary les, etc.
In the
following, we will summarize these properties.
Required Properties
In any application, you should at least congure two properties:
\Application::id
and
yii\base\Application::basePath.
yii\base\Application::id
The
yii\base\Application::id
yii\base
property
species a unique ID that dierentiates an application from others.
It is
mainly used programmatically. Although not a requirement, for best interoperability it is recommended that you use only alphanumeric characters
when specifying an application ID.
yii\base\Application::basePath
The
yii\base\Application::basePath
property species the root directory of an application.
It is the directory
that contains all protected source code of an application system. Under this
directory, you normally will see sub-directories such as
controllers,
models, views,
and
which contain source code corresponding to the MVC pattern.
You may congure the
yii\base\Application::basePath
property us-
ing a directory path or a path alias. In both forms, the corresponding directory must exist, or an exception will be thrown. The path will be normalized
by calling the
realpath()
function.
52
CHAPTER 3.
The
APPLICATION STRUCTURE
yii\base\Application::basePath property is often used to derive
other important paths (e.g. the runtime path). For this reason, a path alias
named
@app
is predened to represent this path. Derived paths may then be
formed using this alias (e.g.
@app/runtime
to refer to the runtime directory).
Important Properties
The properties described in this subsection often need to be congured because they dier across dierent applications.
yii\base\Application::aliases
This property allows you to dene a
set of aliases in terms of an array. The array keys are alias names, and the
array values are the corresponding path denitions. For example:
[
]
'aliases' => [
'@name1' => 'path/to/path1',
'@name2' => 'path/to/path2',
],
This property is provided so that you can dene aliases in terms of application congurations instead of by calling the
yii\base\Application::bootstrap
Yii::setAlias()
method.
This is a very useful property.
It
allows you to specify an array of components that should be run during
the application
yii\base\Application::bootstrap().
For example, if you
want a module to customize the URL rules, you may list its ID as an element
in this property.
Each component listed in this property may be specied in one of the
following formats:
•
•
•
•
•
an application component ID as specied via components,
a module ID as specied via modules,
a class name,
a conguration array,
an anonymous function that creates and returns a component.
For example:
[
'bootstrap' => [
// an application component ID or module ID
'demo',
// a class name
'app\components\Profiler',
// a configuration array
[
'class' => 'app\components\Profiler',
3.3.
APPLICATIONS
],
]
],
53
'level' => 3,
// an anonymous function
function () {
return new app\components\Profiler();
}
Info: If a module ID is the same as an application component ID,
the application component will be used during the bootstrapping
process. If you want to use the module instead, you may specify
it using an anonymous function like the following:
[
]
function () {
return Yii::$app->getModule('user');
},
During the bootstrapping process, each component will be instantiated. If
yii\base\BootstrapInterface, its yii
\base\BootstrapInterface::bootstrap() method will also be called.
the component class implements
Another practical example is in the application conguration for the Basic Project Template, where the
debug
and
gii
modules are congured as
bootstrapping components when the application is running in the development environment:
if (YII_ENV_DEV) {
// configuration adjustments for 'dev' environment
$config['bootstrap'][] = 'debug';
$config['modules']['debug'] = 'yii\debug\Module';
}
$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = 'yii\gii\Module';
Note: Putting too many components in bootstrap will degrade
the performance of your application because for each request, the
same set of components need to be run.
So use bootstrapping
components judiciously.
yii\web\Application::catchAll This property is supported by yii\web
\Application only. It species a controller action which should handle all
user requests. This is mainly used when the application is in maintenance
mode and needs to handle all incoming requests via a single action.
54
CHAPTER 3.
APPLICATION STRUCTURE
The conguration is an array whose rst element species the route of
the action.
The rest of the array elements (key-value pairs) specify the
parameters to be bound to the action. For example:
[
]
'catchAll' => [
'offline/notice',
'param1' => 'value1',
'param2' => 'value2',
],
Info: Debug panel on development environment will not work
when this property is enabled.
yii\base\Application::components
This is the single most important
property. It allows you to register a list of named components called application components that you can use in other places. For example:
[
]
'components' => [
'cache' => [
'class' => 'yii\caching\FileCache',
],
'user' => [
'identityClass' => 'app\models\User',
'enableAutoLogin' => true,
],
],
Each application component is specied as a key-value pair in the array. The
key represents the component ID, while the value represents the component
class name or conguration.
You can register any component with an application, and the component
can later be accessed globally using the expression
\Yii::$app->componentID.
Please read the Application Components section for details.
yii\base\Application::controllerMap
This property allows you to map
a controller ID to an arbitrary controller class. By default, Yii maps controller IDs to controller classes based on a convention (e.g. the ID
mapped to
app\controllers\PostController).
post
would be
By conguring this property, you
can break the convention for specic controllers. In the following example,
account
[
app\controllers\UserController,
app\controllers\PostController.
will be mapped to
be mapped to
'controllerMap' => [
'account' => 'app\controllers\UserController',
'article' => [
while
article
will
3.3.
APPLICATIONS
],
]
],
55
'class' => 'app\controllers\PostController',
'enableCsrfValidation' => false,
The array keys of this property represent the controller IDs, while the array
values represent the corresponding controller class names or congurations.
yii\base\Application::controllerNamespace
This property species
the default namespace under which controller classes should be located. It
defaults to
app\controllers.
If a controller ID is
post,
by convention the cor-
PostController
app\controllers\PostController.
responding controller class name (without namespace) would be
, and the fully qualied class name would be
Controller classes may also be located under sub-directories of the directory corresponding to this namespace. For example, given a controller ID
admin/post, the corresponding fully
controllers\admin\PostController.
qualied controller class would be
app\
It is important that the fully qualied controller classes should be autoloadable and the actual namespace of your controller classes match the value
of this property. Otherwise, you will receive a Page Not Found error when
accessing the application.
In case you want to break the convention as described above, you may
congure the controllerMap property.
yii\base\Application::language
This property species the language
in which the application should display content to end users. The default
value of this property is
en,
meaning English.
You should congure this
property if your application needs to support multiple languages.
The value of this property determines various internationalization aspects, including message translation, date formatting, number formatting,
etc.
For example, the
yii\jui\DatePicker
widget will use this property
value by default to determine in which language the calendar should be displayed and how the date should be formatted.
It is recommended that you specify a language in terms of an IETF
3
language tag .
For example,
en
stands for English, while
en-US
stands for
English (United States).
More details about this property can be found in the Internationalization
section.
yii\base\Application::modules
This property species the modules
that the application contains.
3
http://en.wikipedia.org/wiki/IETF_language_tag
56
CHAPTER 3.
APPLICATION STRUCTURE
The property takes an array of module classes or congurations with the
array keys being the module IDs. For example:
[
]
'modules' => [
// a "booking" module specified with the module class
'booking' => 'app\modules\booking\BookingModule',
],
// a "comment" module specified with a configuration array
'comment' => [
'class' => 'app\modules\comment\CommentModule',
'db' => 'db',
],
Please refer to the Modules section for more details.
yii\base\Application::name
This property species the application name
that may be displayed to end users. Unlike the
id
yii\base\Application::
property, which should take a unique value, the value of this property is
mainly for display purposes; it does not need to be unique.
You do not always need to congure this property if none of your code
is using it.
yii\base\Application::params
This property species an array of glob-
ally accessible application parameters. Instead of using hardcoded numbers
and strings everywhere in your code, it is a good practice to dene them as
application parameters in a single place and use the parameters in places
where needed. For example, you may dene the thumbnail image size as a
parameter like the following:
[
]
'params' => [
'thumbnail.size' => [128, 128],
],
Then in your code where you need to use the size value, you can simply use
code like the following:
$size = \Yii::$app->params['thumbnail.size'];
$width = \Yii::$app->params['thumbnail.size'][0];
Later if you decide to change the thumbnail size, you only need to modify
it in the application conguration; you don't need to touch any dependent
code.
yii\base\Application::sourceLanguage
This property species the lan-
guage that the application code is written in. The default value is
'en-US',
3.3.
APPLICATIONS
57
meaning English (United States). You should congure this property if the
text content in your code is not in English.
Like the language property, you should congure this property in terms
4
of an IETF language tag . For example,
en
stands for English, while
en-US
stands for English (United States).
More details about this property can be found in the Internationalization
section.
yii\base\Application::timeZone
This property is provided as an al-
ternative way of setting the default time zone of the PHP runtime. By cong-
5
uring this property, you are essentially calling the PHP function date_default_timezone_set() .
For example:
[
'timeZone' => 'America/Los_Angeles',
]
yii\base\Application::version
the application.
It defaults to
This property species the version of
'1.0'.
You do not need to congure this
property if none of your code is using it.
Useful Properties
The properties described in this subsection are not commonly congured
because their default values derive from common conventions. However, you
may still congure them in case you want to break the conventions.
yii\base\Application::charset
This property species the charset that
the application uses. The default value is
'UTF-8',
which should be kept as-is
for most applications unless you are working with a legacy system that uses
a lot of non-Unicode data.
yii\base\Application::defaultRoute
This property species the route
that an application should use when a request does not specify one.
The
route may consist of a child module ID, a controller ID, and/or an action
ID. For example,
help, post/create,
or
admin/post/create.
If an action ID is
not given, this property will take the default value specied in
\Controller::defaultAction.
For yii\web\Application, the
which means the
SiteController
yii\base
default value of this property is
'site',
controller and its default action should be
used. As a result, if you access the application without specifying a route,
it will show the result of
4
5
app\controllers\SiteController::actionIndex().
http://en.wikipedia.org/wiki/IETF_language_tag
http://php.net/manual/en/function.date-default-timezone-set.php
58
CHAPTER 3.
For
APPLICATION STRUCTURE
yii\console\Application, the default value is 'help', which means
yii\console\controllers\HelpController::actionIndex()
the core command
should be used. As a result, if you run the command
yii
without providing
any arguments, it will display the help information.
yii\base\Application::extensions
This property species the list of
extensions that are installed and used by the application.
will take the array returned by the le
extensions.php
By default, it
@vendor/yiisoft/extensions.php.
The
le is generated and maintained automatically when you use
6 to install extensions. So in most cases, you do not need to con-
Composer
gure this property.
In the special case when you want to maintain extensions manually, you
may congure this property as follows:
[
'extensions' => [
[
'name' => 'extension name',
'version' => 'version number',
'bootstrap' => 'BootstrapClassName',
configuration array
'alias' => [ // optional
'@alias1' => 'to/path1',
'@alias2' => 'to/path2',
],
],
// optional, may also be a
// ... more extensions like the above ...
],
]
As you can see, the property takes an array of extension specications. Each
name and version elements. If
bootstrap process, a bootstrap element
extension is specied with an array consisting of
an extension needs to run during the
may be specied with a bootstrapping class name or a conguration array.
An extension may also dene a few aliases.
yii\base\Application::layout
This property species the name of the
default layout that should be used when rendering a view. The default value
is
'main',
meaning the layout le
main.php
under the layout path should be
used. If both of the layout path and the view path are taking the default
values, the default layout le can be represented as the path alias
@app/views
/layouts/main.php.
You may congure this property to be
by default, although this is very rare.
6
https://getcomposer.org
false
if you want to disable layout
3.3.
APPLICATIONS
59
yii\base\Application::layoutPath
layout les should be looked for.
This property species the path where
The default value is the
layouts
sub-
directory under the view path. If the view path is taking its default value, the
default layout path can be represented as the path alias
@app/views/layouts.
You may congure it as a directory or a path alias.
yii\base\Application::runtimePath
This property species the path
where temporary les, such as log les and cache les, can be generated.
The default value is the directory represented by the alias
@app/runtime.
You may congure it as a directory or a path alias. Note that the runtime
path must be writable by the process running the application. And the path
should be protected from being accessed by end users, because the temporary
les under it may contain sensitive information.
To simplify access to this path, Yii has predened a path alias named
@runtime
for it.
yii\base\Application::viewPath
This property species the root dir-
ectory where view les are located. The default value is the directory represented by the alias
@app/views.
You may congure it as a directory or a
path alias.
yii\base\Application::vendorPath
7
This property species the vendor
directory managed by Composer . It contains all third party libraries used
by your application, including the Yii framework. The default value is the
directory represented by the alias
@app/vendor.
You may congure this property as a directory or a path alias. When you
modify this property, make sure you also adjust the Composer conguration
accordingly.
To simplify access to this path, Yii has predened a path alias named
@vendor
for it.
yii\console\Application::enableCoreCommands This property is
yii\console\Application only. It species whether the
ported by
supcore
commands included in the Yii release should be enabled. The default value
is
true.
3.3.3 Application Events
An application triggers several events during the lifecycle of handling a request. You may attach event handlers to these events in application congurations as follows:
7
https://getcomposer.org
60
[
]
CHAPTER 3.
APPLICATION STRUCTURE
'on beforeRequest' => function ($event) {
// ...
},
The use of the
on eventName
syntax is described in the Congurations section.
Alternatively, you may attach event handlers during the bootstrapping
process after the application instance is created. For example:
\Yii::$app->on(\yii\base\Application::EVENT_BEFORE_REQUEST, function ($event
) {
// ...
});
yii\base\Application::EVENT_BEFORE_REQUEST
This event is triggered
event name is
before
an application handles a request. The actual
beforeRequest.
When this event is triggered, the application instance has been congured
and initialized.
So it is a good place to insert your custom code via the
event mechanism to intercept the request handling process. For example, in
the event handler, you may dynamically set the
language
yii\base\Application::
property based on some parameters.
yii\base\Application::EVENT_AFTER_REQUEST
This event is triggered
before
after
an application nishes handling a request but
sending the response. The actual event name is
afterRequest.
When this event is triggered, the request handling is completed and you
may take this chance to do some postprocessing of the request or customize
the response.
Note that the
yii\web\Response
component also triggers some events
while it is sending out response content to end users.
triggered
after
Those events are
this event.
yii\base\Application::EVENT_BEFORE_ACTION
This event is triggered
event name is
before
running every controller action.
beforeAction.
yii\base\ActionEvent. An event
yii\base\ActionEvent::isValid property to be false
The event parameter is an instance of
handler may set the
to stop running the action. For example:
[
The actual
'on beforeAction' => function ($event) {
if (some condition) {
$event->isValid = false;
3.3.
]
APPLICATIONS
},
61
} else {
}
Note that the same
beforeAction
event is also triggered by modules and con-
trollers. Application objects are the rst ones triggering this event, followed
by modules (if any), and nally controllers.
\base\ActionEvent::isValid
to be
false,
If an event handler sets
yii
all of the subsequent events will
NOT be triggered.
yii\base\Application::EVENT_AFTER_ACTION
This event is triggered
event name is
after
running every controller action.
The actual
afterAction.
yii\base\ActionEvent. Through
yii\base\ActionEvent::result property, an event handler may access
The event parameter is an instance of
the
or modify the action result. For example:
[
]
'on afterAction' => function ($event) {
if (some condition) {
// modify $event->result
} else {
}
},
Note that the same
afterAction
event is also triggered by modules and con-
trollers. These objects trigger this event in the reverse order as for that of
beforeAction.
That is, controllers are the rst objects triggering this event,
followed by modules (if any), and nally applications.
62
CHAPTER 3.
APPLICATION STRUCTURE
3.3.4 Application Lifecycle
When an entry script is being executed to handle a request, an application
will undergo the following lifecycle:
1. The entry script loads the application conguration as an array.
2. The entry script creates a new instance of the application:
• yii\base\Application::preInit()
is called, which congures
some high priority application properties, such as
::basePath.
yii\base\Application
• Register the yii\base\Application::errorHandler.
• Congure application properties.
• yii\base\Application::init() is called which further calls yii
\base\Application::bootstrap() to run bootstrapping components.
3. The entry script calls
yii\base\Application::run()
to run the ap-
plication:
•
•
Trigger the
yii\base\Application::EVENT_BEFORE_REQUEST event.
Handle the request: resolve the request into a route and the associated parameters; create the module, controller, and action
objects as specied by the route; and run the action.
•
Trigger the
yii\base\Application::EVENT_AFTER_REQUEST event.
3.4.
APPLICATION COMPONENTS
•
63
Send response to the end user.
4. The entry script receives the exit status from the application and completes the request processing.
3.4 Application Components
Applications are service locators. They host a set of the so-called
tion components
example, the
applica-
that provide dierent services for processing requests. For
urlManager
component is responsible for routing Web requests
to appropriate controllers; the
db
component provides DB-related services;
and so on.
Each application component has an ID that uniquely identies itself
among other application components in the same application. You can access
an application component through the expression:
\Yii::$app->componentID
For example, you can use
\Yii::$app->cache
\Yii::$app->db
to get the
to get the
yii\caching\Cache
yii\db\Connection, and
registered with the applic-
ation.
An application component is created the rst time it is accessed through
the above expression. Any further accesses will return the same component
instance.
Application components can be any objects. You can register them by
conguring the
yii\base\Application::components
property in applica-
tion congurations. For example,
[
'components' => [
// register "cache" component using a class name
'cache' => 'yii\caching\ApcCache',
// register "db" component using a configuration array
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=demo',
'username' => 'root',
'password' => '',
],
]
],
// register "search" component using an anonymous function
'search' => function () {
return new app\components\SolrService;
},
64
CHAPTER 3.
APPLICATION STRUCTURE
Info: While you can register as many application components
as you want, you should do this judiciously.
ponents are like global variables.
Application com-
Using too many application
components can potentially make your code harder to test and
maintain. In many cases, you can simply create a local component and use it when needed.
3.4.1 Bootstrapping Components
As mentioned above, an application component will only be instantiated
when it is being accessed the rst time. If it is not accessed at all during a
request, it will not be instantiated. Sometimes, however, you may want to
instantiate an application component for every request, even if it is not explicitly accessed. To do so, you may list its ID in the
::bootstrap
yii\base\Application
property of the application.
For example, the following application conguration makes sure the
log
component is always loaded:
[
]
'bootstrap' => [
'log',
],
'components' => [
'log' => [
// configuration for "log" component
],
],
3.4.2 Core Application Components
Yii denes a set of
core
application components with xed IDs and default
congurations. For example, the
yii\web\Application::request compon-
ent is used to collect information about a user request and resolve it into
a route; the
yii\base\Application::db
component represents a database
connection through which you can perform database queries. It is with help
of these core application components that Yii applications are able to handle
user requests.
Below is the list of the predened core application components. You may
congure and customize them like you do with normal application components. When you are conguring a core application component, if you do not
specify its class, the default one will be used.
• yii\web\AssetManager:
manages asset bundles and asset publishing.
Please refer to the Managing Assets section for more details.
• yii\db\Connection:
represents a database connection through which
you can perform DB queries. Note that when you congure this component, you must specify the component class as well as other required
3.5.
CONTROLLERS
65
component properties, such as
yii\db\Connection::dsn.
Please refer
to the Data Access Objects section for more details.
• yii\base\Application::errorHandler:
handles PHP errors and ex-
ceptions. Please refer to the Handling Errors section for more details.
• yii\i18n\Formatter:
formats data when they are displayed to end
users. For example, a number may be displayed with thousand separator, a date may be formatted in long format. Please refer to the Data
Formatting section for more details.
• yii\i18n\I18N:
supports message translation and formatting. Please
refer to the Internationalization section for more details.
• yii\log\Dispatcher:
manages log targets. Please refer to the Logging
section for more details.
• yii\swiftmailer\Mailer:
supports mail composing and sending. Please
refer to the Mailing section for more details.
• yii\base\Application::response:
represents the response being sent
to end users. Please refer to the Responses section for more details.
• yii\base\Application::request:
represents the request received from
end users. Please refer to the Requests section for more details.
• yii\web\Session:
represents the session information. This compon-
ent is only available in
yii\web\Application.
Please refer to the
Sessions and Cookies section for more details.
• yii\web\UrlManager:
supports URL parsing and creation.
Please
refer to the Routing and URL Creation section for more details.
• yii\web\User:
represents the user authentication information. This
component is only available in
yii\web\Application.
Please refer to
the Authentication section for more details.
• yii\web\View:
supports view rendering.
Please refer to the Views
section for more details.
3.5 Controllers
Controllers are part of the MVC
extending from
8 architecture. They are objects of classes
yii\base\Controller
and are responsible for processing
requests and generating responses. In particular, after taking over the control
from applications, controllers will analyze incoming request data, pass them
to models, inject model results into views, and nally generate outgoing
responses.
3.5.1 Actions
Controllers are composed of
actions
which are the most basic units that end
users can address and request for execution. A controller can have one or
8
http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
66
CHAPTER 3.
APPLICATION STRUCTURE
multiple actions.
The following example shows a
post
controller with two actions:
view
and
create:
namespace app\controllers;
use
use
use
use
Yii;
app\models\Post;
yii\web\Controller;
yii\web\NotFoundHttpException;
class PostController extends Controller
{
public function actionView($id)
{
$model = Post::findOne($id);
if ($model === null) {
throw new NotFoundHttpException;
}
}
return $this->render('view', [
'model' => $model,
]);
public function actionCreate()
{
$model = new Post;
}
}
In the
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
view
action (dened by the
actionView()
method), the code rst loads
the model according to the requested model ID; If the model is loaded successfully, it will display it using a view named
view.
Otherwise, it will throw
an exception.
In the
create
action (dened by the
actionCreate()
method), the code
is similar. It rst tries to populate a new instance of the model using the
request data and save the model. If both succeed it will redirect the browser
to the
view
display the
action with the ID of the newly created model. Otherwise it will
create
view through which users can provide the needed input.
3.5.
CONTROLLERS
67
3.5.2 Routes
End users address actions through the so-called
routes.
A route is a string
that consists of the following parts:
•
a module ID: this exists only if the controller belongs to a non-application
module;
•
a controller ID: a string that uniquely identies the controller among
all controllers within the same application (or the same module if the
controller belongs to a module);
•
an action ID: a string that uniquely identies the action among all
actions within the same controller.
Routes take the following format:
ControllerID/ActionID
or the following format if the controller belongs to a module:
ModuleID/ControllerID/ActionID
So if a user requests with the URL
the
index
action in the
site
http://hostname/index.php?r=site/index,
controller will be executed. For more details on
how routes are resolved into actions, please refer to the Routing and URL
Creation section.
3.5.3 Creating Controllers
yii\web\Application, controllers should extend from yii\web\Controller
Similarly in yii\console\Application, controllers
should extend from yii\console\Controller or its child classes. The fol-
In
or its child classes.
lowing code denes a
site
controller:
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
}
Controller IDs
Usually, a controller is designed to handle the requests regarding a particular
type of resource. For this reason, controller IDs are often nouns referring to
the types of the resources that they are handling. For example, you may use
article
as the ID of a controller that handles article data.
By default, controller IDs should contain these characters only: English
letters in lower case, digits, underscores, hyphens, and forward slashes. For
article and post-comment
?, PostComment, admin\post are not.
example,
are both valid controller IDs, while
article
68
CHAPTER 3.
APPLICATION STRUCTURE
A controller ID may also contain a subdirectory prex.
admin/article
der the
stands for an
article
controller in the
admin
For example,
subdirectory un-
yii\base\Application::controllerNamespace.
Valid characters
for subdirectory prexes include: English letters in lower and upper cases,
digits, underscores, and forward slashes, where forward slashes are used as
separators for multi-level subdirectories (e.g.
panels/admin).
Controller Class Naming
Controller class names can be derived from controller IDs according to the
following procedure:
1. Turn the rst letter in each word separated by hyphens into upper case.
Note that if the controller ID contains slashes, this rule only applies to
the part after the last slash in the ID.
2. Remove hyphens and replace any forward slashes with backward slashes.
3. Append the sux
4. Prepend the
Controller.
yii\base\Application::controllerNamespace.
The following are some examples, assuming the
yii\base\Application::
controllerNamespace takes the default value app\controllers:
• article becomes app\controllers\ArticleController;
• post-comment becomes app\controllers\PostCommentController;
• admin/post-comment becomes app\controllers\admin\PostCommentController
;
• adminPanels/post-comment becomes app\controllers\adminPanels\PostCommentController
.
Controller classes must be autoloadable. For this reason, in the above ex-
article controller class should be saved in the le whose alias is
@app/controllers/ArticleController.php; while the admin/post-comment controller should be in @app/controllers/admin/PostCommentController.php.
amples, the
Info: The last example admin/post-comment shows how you can
put a controller under a sub-directory of the
::controllerNamespace.
yii\base\Application
This is useful when you want to organ-
ize your controllers into several categories and you do not want
to use modules.
Controller Map
You can congure the
yii\base\Application::controllerMap to overcome
the constraints of the controller IDs and class names described above. This
3.5.
CONTROLLERS
69
is mainly useful when you are using third-party controllers and you do not
have control over their class names.
You may congure the
yii\base\Application::controllerMap
in the
application conguration. For example:
[
]
'controllerMap' => [
// declares "account" controller using a class name
'account' => 'app\controllers\UserController',
// declares "article" controller using a configuration array
'article' => [
'class' => 'app\controllers\PostController',
'enableCsrfValidation' => false,
],
],
Default Controller
Each application has a default controller specied via the
::defaultRoute
property.
When a request does not specify a route, the
route specied by this property will be used. For
value is
a URL
yii\base\Application
yii\web\Application, its
'site', while for yii\console\Application, it is help. Therefore, if
is http://hostname/index.php, then the site controller will handle the
request.
You may change the default controller with the following application
conguration:
[
]
'defaultRoute' => 'main',
3.5.4 Creating Actions
Creating actions can be as simple as dening the so-called
a controller class. An action method is a
with the word
action.
public
action methods
in
method whose name starts
The return value of an action method represents the
response data to be sent to end users. The following code denes two actions,
index
and
hello-world:
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
public function actionIndex()
{
return $this->render('index');
70
CHAPTER 3.
APPLICATION STRUCTURE
}
public function actionHelloWorld()
{
return 'Hello World';
}
}
Action IDs
An action is often designed to perform a particular manipulation of a resource. For this reason, action IDs are usually verbs, such as
view, update,
etc.
By default, action IDs should contain these characters only:
English
letters in lower case, digits, underscores, and hyphens (you can use hyphens
view, update2,
Update are not.
to separate words). For example,
action IDs, while
view?
and
and
comment-post
are all valid
You can create actions in two ways: inline actions and standalone actions. An inline action is dened as a method in the controller class, while a
standalone action is a class extending
yii\base\Action
or its child classes.
Inline actions take less eort to create and are often preferred if you have
no intention to reuse these actions. Standalone actions, on the other hand,
are mainly created to be used in dierent controllers or be redistributed as
extensions.
Inline Actions
Inline actions refer to the actions that are dened in terms of action methods
as we just described.
The names of the action methods are derived from action IDs according
to the following procedure:
1. Turn the rst letter in each word of the action ID into upper case.
2. Remove hyphens.
3. Prepend the prex
For example,
action.
index becomes actionIndex, and hello-world becomes actionHelloWorld
.
Note: The names of the action methods are
you have a method named
ActionIndex,
case-sensitive.
If
it will not be considered
as an action method, and as a result, the request for the
index
action will result in an exception. Also note that action methods
must be public. A private or protected method does NOT dene
an inline action.
3.5.
CONTROLLERS
71
Inline actions are the most commonly dened actions because they take little
eort to create. However, if you plan to reuse the same action in dierent
places, or if you want to redistribute an action, you should consider dening
it as a
standalone action.
Standalone Actions
Standalone actions are dened in terms of action classes extending yii\base
\Action or its child classes. For example, in the Yii releases, there are yii
\web\ViewAction and yii\web\ErrorAction, both of which are standalone
actions.
To use a standalone action, you should declare it in the
overriding the
action map
by
yii\base\Controller::actions() method in your controller
classes like the following:
public function actions()
{
return [
// declares "error" action using a class name
'error' => 'yii\web\ErrorAction',
}
];
// declares "view" action using a configuration array
'view' => [
'class' => 'yii\web\ViewAction',
'viewPrefix' => '',
],
As you can see, the
actions()
method should return an array whose keys are
action IDs and values the corresponding action class names or congurations.
Unlike inline actions, action IDs for standalone actions can contain arbitrary
characters, as long as they are declared in the
actions()
method.
To create a standalone action class, you should extend
or a child class, and implement a public method named
the
run()
yii\base\Action
run().
The role of
method is similar to that of an action method. For example,
redirect('http://example.com');
}
Action Parameters
The action methods for inline actions and the
actions can take parameters, called
tained from requests. For
yii\web\Application,
parameter is retrieved from
for
run()
$_GET
yii\console\Application,
methods for standalone
action parameters.
Their values are ob-
the value of each action
using the parameter name as the key;
they correspond to the command line argu-
ments.
view
$version.
In the following example, the
two parameters:
$id
and
action (an inline action) has declared
namespace app\controllers;
use yii\web\Controller;
class PostController extends Controller
{
public function actionView($id, $version = null)
{
// ...
}
}
The action parameters will be populated as follows for dierent requests:
3.5.
CONTROLLERS
73
• http://hostname/index.php?r=post/view&id=123:
lled with the value
'123',
while
$version
the
is still
$id parameter will be
null because there is
version query parameter.
• http://hostname/index.php?r=post/view&id=123&version=2: the $id and $version
parameters will be lled with '123' and '2', respectively.
• http://hostname/index.php?r=post/view: a yii\web\BadRequestHttpException
exception will be thrown because the required $id parameter is not
no
provided in the request.
• http://hostname/index.php?r=post/view&id[]=123:
exception will be thrown because
pected array value
$id
a
yii\web\BadRequestHttpException
parameter is receiving an unex-
['123'].
If you want an action parameter to accept array values, you should type-hint
it with
array,
like the following:
public function actionView(array $id, $version = null)
{
// ...
}
http://hostname/index.php?r=post/view&id[]=123, the $id
['123']. If the request is http://hostname
/index.php?r=post/view&id=123, the $id parameter will still receive the same
array value because the scalar value '123' will be automatically turned into
Now if the request is
parameter will take the value of
an array.
The above examples mainly show how action parameters work for Web
applications. For console applications, please refer to the Console Commands
section for more details.
Default Action
Each controller has a default action specied via the
::defaultAction
yii\base\Controller
property. When a route contains the controller ID only,
it implies that the default action of the specied controller is requested.
By default, the default action is set as
index.
If you want to change the
default value, simply override this property in the controller class, like the
following:
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
public $defaultAction = 'home';
public function actionHome()
{
return $this->render('home');
}
74
CHAPTER 3.
APPLICATION STRUCTURE
}
3.5.5 Controller Lifecycle
When processing a request, an application will create a controller based on
the requested route. The controller will then undergo the following lifecycle
to fulll the request:
1. The
yii\base\Controller::init()
method is called after the con-
troller is created and congured.
2. The controller creates an action object based on the requested action
ID:
•
If the action ID is not specied, the
defaultAction
•
yii\base\Controller::
will be used.
If the action ID is found in the
yii\base\Controller::actions(),
a standalone action will be created;
•
If the action ID is found to match an action method, an inline
action will be created;
•
Otherwise an
yii\base\InvalidRouteException
exception will
be thrown.
3. The controller sequentially calls the
beforeAction()
method of the ap-
plication, the module (if the controller belongs to a module), and the
controller.
•
If one of the calls returns
()
false, the rest of the uncalled beforeAction
methods will be skipped and the action execution will be can-
celled.
•
By default, each
beforeAction() method call will trigger a beforeAction
event to which you can attach a handler.
4. The controller runs the action.
•
The action parameters will be analyzed and populated from the
request data.
5. The controller sequentially calls the
afterAction()
method of the con-
troller, the module (if the controller belongs to a module), and the
application.
•
By default, each
afterAction() method call will trigger an afterAction
event to which you can attach a handler.
6. The application will take the action result and assign it to the response.
3.6.
MODELS
75
3.5.6 Best Practices
In a well-designed application, controllers are often very thin, with each
action containing only a few lines of code. If your controller is rather complicated, it usually indicates that you should refactor it and move some code
to other classes.
Here are some specic best practices. Controllers
•
•
may access the request data;
may call methods of models and other service components with request
data;
•
•
may use views to compose responses;
should NOT process the request data - this should be done in the model
layer;
•
should avoid embedding HTML or other presentational code - this is
better done in views.
3.6 Models
9 architecture. They are objects representing
Models are part of the MVC
business data, rules and logic.
You can create model classes by extending
classes. The base class
•
yii\base\Model
yii\base\Model
or its child
supports many useful features:
Attributes: represent the business data and can be accessed like normal
object properties or array elements;
•
•
Attribute labels: specify the display labels for attributes;
Massive assignment: supports populating multiple attributes in a single
step;
•
Validation rules: ensures input data based on the declared validation
rules;
•
Data Exporting: allows model data to be exported in terms of arrays
with customizable formats.
The
Model
class is also the base class for more advanced models, such as
Active Record. Please refer to the relevant documentation for more details
about these advanced models.
Info: You are not required to base your model classes on
\base\Model.
yii
However, because there are many Yii components
built to support
yii\base\Model, it is usually the preferable base
class for a model.
9
http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
76
CHAPTER 3.
APPLICATION STRUCTURE
3.6.1 Attributes
Models represent business data in terms of
attributes.
Each attribute is like
a publicly accessible property of a model. The method
attributes()
yii\base\Model::
species what attributes a model class has.
You can access an attribute like accessing a normal object property:
$model = new \app\models\ContactForm;
// "name" is an attribute of ContactForm
$model->name = 'example';
echo $model->name;
You can also access attributes like accessing array elements, thanks to the
10 and Traversable11 by
support for ArrayAccess
yii\base\Model:
$model = new \app\models\ContactForm;
// accessing attributes like array elements
$model['name'] = 'example';
echo $model['name'];
// Model is traversable using foreach.
foreach ($model as $name => $value) {
echo "$name: $value\n";
}
Dening Attributes
By default, if your model class extends directly from
its
non-static public
yii\base\Model,
member variables are attributes.
all
For example, the
ContactForm model class below has four attributes: name, email, subject and
body. The ContactForm model is used to represent the input data received
from an HTML form.
namespace app\models;
use yii\base\Model;
class ContactForm extends Model
{
public $name;
public $email;
public $subject;
public $body;
}
You may override
yii\base\Model::attributes() to dene attributes in a
dierent way. The method should return the names of the attributes in a
model. For example,
10
11
yii\db\ActiveRecord does so by returning the column
http://php.net/manual/en/class.arrayaccess.php
http://php.net/manual/en/class.traversable.php
3.6.
MODELS
77
names of the associated database table as its attribute names. Note that you
may also need to override the magic methods such as
__get(), __set()
so that
the attributes can be accessed like normal object properties.
Attribute Labels
When displaying values or getting input for attributes, you often need to display some labels associated with attributes. For example, given an attribute
named
firstName,
you may want to display a label
First Name
which is more
user-friendly when displayed to end users in places such as form inputs and
error messages.
You can get the label of an attribute by calling
yii\base\Model::getAttributeLabel().
For example,
$model = new \app\models\ContactForm;
// displays "Name"
echo $model->getAttributeLabel('name');
By default, attribute labels are automatically generated from attribute names.
The generation is done by the method
yii\base\Model::generateAttributeLabel().
It will turn camel-case variable names into multiple words with the rst letter in each word in upper case. For example,
firstName
becomes
username
becomes
Username,
and
First Name.
If you do not want to use automatically generated labels, you may override
yii\base\Model::attributeLabels()
labels. For example,
namespace app\models;
use yii\base\Model;
class ContactForm extends Model
{
public $name;
public $email;
public $subject;
public $body;
}
public function attributeLabels()
{
return [
'name' => 'Your name',
'email' => 'Your email address',
'subject' => 'Subject',
'body' => 'Content',
];
}
to explicitly declare attribute
78
CHAPTER 3.
APPLICATION STRUCTURE
For applications supporting multiple languages, you may want to translate
attribute labels. This can be done in the
yii\base\Model::attributeLabels()
method as well, like the following:
public function attributeLabels()
{
return [
'name' => \Yii::t('app', 'Your name'),
'email' => \Yii::t('app', 'Your email address'),
'subject' => \Yii::t('app', 'Subject'),
'body' => \Yii::t('app', 'Content'),
];
}
You may even conditionally dene attribute labels. For example, based on
the scenario the model is being used in, you may return dierent labels for
the same attribute.
Info: Strictly speaking, attribute labels are part of views. But
declaring labels in models is often very convenient and can result
in very clean and reusable code.
3.6.2 Scenarios
A model may be used in dierent
scenarios.
For example, a
User
model
may be used to collect user login inputs, but it may also be used for the
user registration purpose. In dierent scenarios, a model may use dierent
business rules and logic. For example, the
email
attribute may be required
during user registration, but not so during user login.
A model uses the
yii\base\Model::scenario
property to keep track of
the scenario it is being used in. By default, a model supports only a single
scenario named
default.
The following code shows two ways of setting the
scenario of a model:
// scenario is set as a property
$model = new User;
$model->scenario = User::SCENARIO_LOGIN;
// scenario is set through configuration
$model = new User(['scenario' => User::SCENARIO_LOGIN]);
By default, the scenarios supported by a model are determined by the validation rules declared in the model. However, you can customize this behavior
by overriding the
yii\base\Model::scenarios()
ing:
namespace app\models;
use yii\db\ActiveRecord;
class User extends ActiveRecord
method, like the follow-
3.6.
MODELS
{
79
const SCENARIO_LOGIN = 'login';
const SCENARIO_REGISTER = 'register';
public function scenarios()
{
return [
self::SCENARIO_LOGIN => ['username', 'password'],
self::SCENARIO_REGISTER => ['username', 'email', 'password'],
];
}
}
Info: In the above and following examples, the model classes
are extending from
yii\db\ActiveRecord
because the usage of
multiple scenarios usually happens to Active Record classes.
The
scenarios()
method returns an array whose keys are the scenario names
and values the corresponding
active attributes.
An active attribute can be
massively assigned and is subject to validation. In the above example, the
username
register
password attributes are active in the login scenario; while
scenario, email is also active besides username and password.
and
The default implementation of
scenarios()
in the validation rule declaration method
overriding
scenarios(),
in the
will return all scenarios found
yii\base\Model::rules().
When
if you want to introduce new scenarios in addition to
the default ones, you may write code like the following:
namespace app\models;
use yii\db\ActiveRecord;
class User extends ActiveRecord
{
const SCENARIO_LOGIN = 'login';
const SCENARIO_REGISTER = 'register';
}
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios[self::SCENARIO_LOGIN] = ['username', 'password'];
$scenarios[self::SCENARIO_REGISTER] = ['username', 'email', '
password'];
return $scenarios;
}
The scenario feature is primarily used by validation and massive attribute
assignment. You can, however, use it for other purposes. For example, you
may declare attribute labels dierently based on the current scenario.
80
CHAPTER 3.
APPLICATION STRUCTURE
3.6.3 Validation Rules
When the data for a model is received from end users, it should be validated
to make sure it satises certain rules (called
as
business rules ).
For example, given a
validation rules,
also known
ContactForm model, you may want
email attribute contains
to make sure all attributes are not empty and the
a valid email address.
If the values for some attributes do not satisfy the
corresponding business rules, appropriate error messages should be displayed
to help the user to x the errors.
You may call
yii\base\Model::validate()
to validate the received
data. The method will use the validation rules declared in
::rules()
return
errors
yii\base\Model
to validate every relevant attribute. If no error is found, it will
true.
Otherwise, it will keep the errors in the
property and return
false.
yii\base\Model::
For example,
$model = new \app\models\ContactForm;
// populate model attributes with user inputs
$model->attributes = \Yii::$app->request->post('ContactForm');
if ($model->validate()) {
// all inputs are valid
} else {
// validation failed: $errors is an array containing error messages
$errors = $model->errors;
}
To declare validation rules associated with a model, override the
\Model::rules()
yii\base
method by returning the rules that the model attributes
should satisfy. The following example shows the validation rules declared for
the
ContactForm
model:
public function rules()
{
return [
// the name, email, subject and body attributes are required
[['name', 'email', 'subject', 'body'], 'required'],
}
];
// the email attribute should be a valid email address
['email', 'email'],
A rule can be used to validate one or multiple attributes, and an attribute
may be validated by one or multiple rules.
Please refer to the Validating
Input section for more details on how to declare validation rules.
Sometimes, you may want a rule to be applied only in certain scenarios.
To do so, you can specify the
public function rules()
{
return [
on
property of a rule, like the following:
3.6.
MODELS
81
// username, email and password are all required in "register"
scenario
[['username', 'email', 'password'], 'required', 'on' => self::
SCENARIO_REGISTER],
}
],
];
// username and password are required in "login" scenario
[['username', 'password'], 'required', 'on' => self::SCENARIO_LOGIN
If you do not specify the
arios. A rule is called an
\base\Model::scenario.
on
property, the rule would be applied in all scen-
active rule
if it can be applied in the current
yii
An attribute will be validated if and only if it is an active attribute
declared in
declared in
scenarios()
rules().
and is associated with one or multiple active rules
3.6.4 Massive Assignment
Massive assignment is a convenient way of populating a model with user
inputs using a single line of code.
It populates the attributes of a model
by assigning the input data directly to the
yii\base\Model::$attributes
property. The following two pieces of code are equivalent, both trying to assign the form data submitted by end users to the attributes of the
ContactForm
model. Clearly, the former, which uses massive assignment, is much cleaner
and less error prone than the latter:
$model = new \app\models\ContactForm;
$model->attributes = \Yii::$app->request->post('ContactForm');
$model = new \app\models\ContactForm;
$data = \Yii::$app->request->post('ContactForm', []);
$model->name = isset($data['name']) ? $data['name'] : null;
$model->email = isset($data['email']) ? $data['email'] : null;
$model->subject = isset($data['subject']) ? $data['subject'] : null;
$model->body = isset($data['body']) ? $data['body'] : null;
Safe Attributes
Massive assignment only applies to the so-called
safe attributes
which are
yii\base\Model::scenarios() for the current yii
\base\Model::scenario of a model. For example, if the User model has the
the attributes listed in
following scenario declaration, then when the current scenario is
the
username
and
password
login,
only
can be massively assigned. Any other attributes
will be kept untouched.
public function scenarios()
{
return [
82
}
CHAPTER 3.
];
APPLICATION STRUCTURE
self::SCENARIO_LOGIN => ['username', 'password'],
self::SCENARIO_REGISTER => ['username', 'email', 'password'],
Info: The reason that massive assignment only applies to safe
attributes is because you want to control which attributes can be
modied by end user data. For example, if the
a
permission
User
model has
attribute which determines the permission assigned
to the user, you would like this attribute to be modiable by
administrators through a backend interface only.
Because the default implementation of
yii\base\Model::scenarios() will
yii\base\Model::rules(), if
return all scenarios and attributes found in
you do not override this method, it means an attribute is safe as long as it
appears in one of the active validation rules.
For this reason, a special validator aliased
safe is provided so that you can
declare an attribute to be safe without actually validating it. For example,
the following rules declare that both
title and description are safe attributes.
public function rules()
{
return [
[['title', 'description'], 'safe'],
];
}
Unsafe Attributes
As described above, the
two purposes:
yii\base\Model::scenarios()
method serves for
determining which attributes should be validated, and de-
termining which attributes are safe. In some rare cases, you may want to
validate an attribute but do not want to mark it safe.
prexing an exclamation mark
scenarios(),
like the
secret
!
You can do so by
to the attribute name when declaring it in
attribute in the following:
public function scenarios()
{
return [
self::SCENARIO_LOGIN => ['username', 'password', '!secret'],
];
}
login scenario, all three attributes will be validated.
username and password attributes can be massively assigned.
input value to the secret attribute, you have to do it explicitly
When the model is in the
However, only the
To assign an
as follows,
$model->secret = $secret;
3.6.
MODELS
83
The same can be done in
rules()
method:
public function rules()
{
return [
[['username', 'password', '!secret'], 'required', 'on' => 'login']
];
}
In this case attributes
username, password
and
secret
are required, but
secret
must be assigned explicitly.
3.6.5 Data Exporting
Models often need to be exported in dierent formats.
For example, you
may want to convert a collection of models into JSON or Excel format. The
exporting process can be broken down into two independent steps:
•
•
models are converted into arrays;
the arrays are converted into target formats.
You may just focus on the rst step, because the second step can be achieved
by generic data formatters, such as
yii\web\JsonResponseFormatter.
The simplest way of converting a model into an array is to use the
\base\Model::$attributes
yii
property. For example,
$post = \app\models\Post::findOne(100);
$array = $post->attributes;
By default, the
ues of
all
yii\base\Model::$attributes property will return the valyii\base\Model::attributes().
attributes declared in
A more exible and powerful way of converting a model into an array is
to use the
yii\base\Model::toArray() method.
yii\base\Model::$attributes.
same as that of
Its default behavior is the
However, it allows you to
choose which data items, called
elds,
how they should be formatted.
In fact, it is the default way of exporting
to be put in the resulting array and
models in RESTful Web service development, as described in the Response
Formatting.
Fields
A eld is simply a named element in the array that is obtained by calling
the
yii\base\Model::toArray()
method of a model.
By default, eld names are equivalent to attribute names. However, you
can change this behavior by overriding the
d/or
yii\base\Model::extraFields()
yii\base\Model::fields()
turn a list of eld denitions. The elds dened by
meaning that
toArray()
an-
methods. Both methods should re-
fields() are default elds,
extraFields()
will return these elds by default. The
method denes additionally available elds which can also be returned by
84
CHAPTER 3.
toArray()
APPLICATION STRUCTURE
as long as you specify them via the
$expand
parameter.
For ex-
fields() and
extraFields().
ample, the following code will return all elds dened in
prettyName
and
fullAddress
elds if they are dened in
the
$array = $model->toArray([], ['prettyName', 'fullAddress']);
fields() to add, remove, rename or redene elds.
fields() should be an array. The array keys are the
You can override
The
return value of
eld
names, and the array values are the corresponding eld denitions which
can be either property/attribute names or anonymous functions returning
the corresponding eld values. In the special case when a eld name is the
same as its dening attribute name, you can omit the array key. For example,
// explicitly list every field, best used when you want to make sure the
changes
// in your DB table or model attributes do not cause your field changes (to
keep API backward compatibility).
public function fields()
{
return [
// field name is the same as the attribute name
'id',
// field name is "email", the corresponding attribute name is "
email_address"
'email' => 'email_address',
}
];
// field name is "name", its value is defined by a PHP callback
'name' => function () {
return $this->first_name . ' ' . $this->last_name;
},
// filter out some fields, best used when you want to inherit the parent
implementation
// and blacklist some sensitive fields.
public function fields()
{
$fields = parent::fields();
// remove fields that contain sensitive information
unset($fields['auth_key'], $fields['password_hash'], $fields['
password_reset_token']);
}
return $fields;
Warning: Because by default all attributes of a model will be
included in the exported array, you should examine your data
to make sure they do not contain sensitive information. If there
is such information, you should override
fields()
to lter them
3.6.
MODELS
out.
85
In the above example, we choose to lter out
password_hash
and
auth_key,
password_reset_token.
3.6.6 Best Practices
Models are the central places to represent business data, rules and logic.
They often need to be reused in dierent places. In a well-designed application, models are usually much fatter than controllers.
In summary, models
•
•
•
•
may contain attributes to represent business data;
may contain validation rules to ensure the data validity and integrity;
may contain methods implementing business logic;
should NOT directly access request, session, or any other environmental data. These data should be injected by controllers into models;
•
should avoid embedding HTML or other presentational code - this is
better done in views;
•
avoid having too many scenarios in a single model.
You may usually consider the last recommendation above when you are developing large complex systems. In these systems, models could be very fat
because they are used in many places and may thus contain many sets of
rules and business logic. This often ends up in a nightmare in maintaining
the model code because a single touch of the code could aect several dierent places. To make the model code more maintainable, you may take the
following strategy:
•
Dene a set of base model classes that are shared by dierent applications or modules. These model classes should contain minimal sets of
rules and logic that are common among all their usages.
•
In each application or module that uses a model, dene a concrete
model class by extending from the corresponding base model class.
The concrete model classes should contain rules and logic that are
specic for that application or module.
For example, in the Advanced Project Template
model class
common\models\Post.
12 , you may dene a base
Then for the front end application, you
dene and use a concrete model class
frontend\models\Post
which extends
common\models\Post. And similarly for the back end application, you
backend\models\Post. With this strategy, you will be sure that the code
frontend\models\Post is only specic to the front end application, and if
from
dene
in
you make any change to it, you do not need to worry if the change may
break the back end application.
12
https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide/
README.md
86
CHAPTER 3.
APPLICATION STRUCTURE
3.7 Views
Views are part of the MVC
13 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 les containing mainly
HTML code and presentational PHP code. They are managed by the
\web\View
yii
application component which provides commonly used methods
to facilitate view composition and rendering.
For simplicity, we often call
view templates or view template les as views.
3.7.1 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.
title = 'Login';
?>
= Html::encode($this->title) ?>
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
man-
aging and rendering this view template.
Besides
as
$model
pushed
$this,
there may be other predened variables in a view, such
in the above example. These variables represent the data that are
into the view by controllers or other objects which trigger the view
rendering.
Tip: The predened 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 way of documenting your views.
13
http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
3.7.
VIEWS
87
Security
When creating views that generate HTML pages, it is important that you
encode and/or lter the data coming from end users before presenting them.
Otherwise, your application may be subject to cross-site scripting
To display a plain text, encode it rst by calling
encode().
14 attacks.
yii\helpers\Html::
For example, the following code encodes the user name before
displaying it:
= Html::encode($user->name) ?>
To display HTML content, use
tent rst.
yii\helpers\HtmlPurifier to lter the con-
For example, the following code lters the post content before
displaying it:
= HtmlPurifier::process($post->text) ?>
Tip: While HTMLPurier does excellent job in making output
safe, it is not fast. You should consider caching the ltering result
if your application requires high performance.
Organizing Views
Like controllers and models, there are conventions to organize views.
•
For views rendered by a controller, they should be put under the directory
@app/views/ControllerID
by default, where
ControllerID refers to
PostController,
PostCommentController,
the controller ID. For example, if the controller class is
@app/views/post; if it is
@app/views/post-comment. In case the controller
the directory would be views/ControllerID under
the directory would be
the directory would be
belongs to a module,
the
•
yii\base\Module::basePath.
For views rendered in a widget, they should be put under the
/views
directory by default, where
WidgetPath
WidgetPath
stands for the directory
containing the widget class le.
•
For views rendered by other objects, it is recommended that you follow
the similar convention as that for widgets.
14
http://en.wikipedia.org/wiki/Cross-site_scripting
88
CHAPTER 3.
APPLICATION STRUCTURE
You may customize these default view directories by overriding the yii\base
\ViewContextInterface::getViewPath() method of controllers or widgets.
3.7.2 Rendering Views
You can render views in controllers, widgets, or any other places by calling
view rendering methods. These methods share a similar signature shown as
follows,
/**
* @param string $view view
rendering method
* @param array $params the
* @return string rendering
*/
methodName($view, $params =
name or file path, depending on the actual
data to be passed to the view
result
[])
Rendering in Controllers
Within controllers, you may call the following controller methods to render
views:
• yii\base\Controller::render():
renders a named view and applies
a layout to the rendering result.
• yii\base\Controller::renderPartial():
renders a named view without
any layout.
• yii\web\Controller::renderAjax():
renders a named view without
any layout, and injects all registered JS/CSS scripts and les.
It is
usually used in response to AJAX Web requests.
• yii\base\Controller::renderFile():
renders a view specied in
terms of a view le path or alias.
• yii\base\Controller::renderContent():
renders a static string by
embedding it into the currently applicable layout.
available since version 2.0.1.
For example,
namespace app\controllers;
use
use
use
use
Yii;
app\models\Post;
yii\web\Controller;
yii\web\NotFoundHttpException;
class PostController extends Controller
{
public function actionView($id)
{
$model = Post::findOne($id);
if ($model === null) {
throw new NotFoundHttpException;
This method is
3.7.
VIEWS
89
}
}
}
// renders a view named "view" and applies a layout to it
return $this->render('view', [
'model' => $model,
]);
Rendering in Widgets
Within widgets, you may call the following widget methods to render views.
• yii\base\Widget::render(): renders a named view.
• yii\base\Widget::renderFile(): renders a view specied
in terms
of a view le path or alias.
For example,
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 Views
You can render a view within another view by calling one of the following
yii\base\View:
• yii\base\View::render(): renders a named view.
• yii\web\View::renderAjax(): renders a named view
methods provided by the
and injects all
registered JS/CSS scripts and les. It is usually used in response to
AJAX Web requests.
• yii\base\View::renderFile():
renders a view specied in terms of
a view le path or alias.
For example, the following code in a view renders the
_overview.php
view
le which is in the same directory as the view being currently rendered.
Remember that
$this
in a view refers to the
= $this->render('_overview') ?>
yii\base\View
component:
90
CHAPTER 3.
APPLICATION STRUCTURE
Rendering in Other Places
In any place, you can get access to the
ponent by the expression
yii\base\View
Yii::$app->view
application com-
and then call its aforementioned
methods to render a view. For example,
// displays the view file "@app/views/site/license.php"
echo \Yii::$app->view->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 le path/alias. In most cases, you would use the former because it
is more concise and exible. We call views specied using names as
views.
named
A view name is resolved into the corresponding view le path according
to the following rules:
•
A view name may omit the le extension name. In this case,
used as the extension. For example, the view name
to the le name
•
about
.php will be
corresponds
about.php.
If the view name starts with double slashes
le path would be
@app/views/ViewName.
//,
the corresponding view
That is, the view is looked for
yii\base\Application::viewPath.
For example, //site/
@app/views/site/about.php.
• If the view name starts with a single slash /, the view le path is formed
under the
about
will be resolved into
by prexing the view name with the
yii\base\Module::viewPath
the currently active module. If there is no active module,
of
@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 le path would be @app/
views/user/create.php.
•
yii\base\View::context and the context implements yii\base\ViewContextInterface, the view le path
is formed by prexing the yii\base\ViewContextInterface::getViewPath()
If the view is rendered with a
of the context to the view name.
This mainly applies to the views
rendered within controllers and widgets.
@app/views/site/about.php
SiteController.
resolved into
•
For example,
about
will be
if the context is the controller
If a view is rendered within another view, the directory containing the
other view le will be prexed to the new view name to form the actual
@app/views/post
@app/views/post/index.php.
According to the above rules, calling $this->render('view') in a controller app
\controllers\PostController will actually render the view le @app/views/post/
view.php, while calling $this->render('_overview') in that view will render the
view le path. For example,
/item.php
item
will be resolved into
if it is being rendered in the view
3.7.
VIEWS
view le
91
@app/views/post/_overview.php.
Accessing Data in Views
There are two approaches to access data within a view: push and pull.
By passing the data as the second parameter to the view rendering methods, you are using the push approach. The data should be represented as
an array of name-value pairs. When the view is being rendered, the PHP
extract()
function will be called on this array so that the array is extracted
into variables in the view. For example, the following view rendering code in
a controller will push two variables to the
report
and
$bar = 2.
yii\base\View
or other
view:
$foo = 1
echo $this->render('report', [
'foo' => 1,
'bar' => 2,
]);
The pull approach actively retrieves data from the
objects accessible in views (e.g.
Yii::$app).
Using the code below as an
example, within the view you can get the controller object by the expression
$this->context.
And as a result, it is possible for you to access any properties
or methods of the controller in the
report
view, such as the controller ID
shown in the following:
The controller ID is: = $this->context->id ?>
The push approach is usually the preferred way of accessing data in views,
because it makes views less dependent on context objects. Its drawback is
that you need to manually build the data array all the time, which could
become tedious and error prone if a view is shared and rendered in dierent
places.
Sharing Data among Views
The
yii\base\View
provides the
yii\base\View::params
property that
you can use to share data among views.
For example, in an
about
view, you can have the following code which
species the current segment of the breadcrumbs.
$this->params['breadcrumbs'][] = 'About Us';
Then, in the layout le, which is also a view, you can display the breadcrumbs
using the data passed along
yii\base\View::params:
= yii\widgets\Breadcrumbs::widget([
'links' => isset($this->params['breadcrumbs']) ? $this->params['
breadcrumbs'] : [],
]) ?>
92
CHAPTER 3.
APPLICATION STRUCTURE
3.7.3 Layouts
Layouts are a special type of views that represent the common parts of
multiple views. For example, the pages for most Web applications share the
same page header and footer. While you can repeat the same page header
and footer in every view, a better way is to do this once in a layout and
embed the rendering result of a content view at an appropriate place in the
layout.
Creating Layouts
Because layouts are also views, they can be created in the similar way as
normal views.
layouts. For
views/layouts
By default, layouts are stored in the directory
@app/views/
layouts used within a module, they should be stored in the
yii\base\Module::basePath. You may
directory by conguring the yii\base\Module
directory under the
customize the default layout
::layoutPath
property of the application or modules.
The following example shows how a layout looks like.
Note that for
illustrative purpose, we have greatly simplied the code in the layout.
In
practice, you may want to add more content to it, such as head tags, main
menu, etc.
beginPage() ?>
= Html::csrfMetaTags() ?>
= Html::encode($this->title) ?>
head() ?>
beginBody() ?>
My Company
= $content ?>
endBody() ?>
endPage() ?>
As you can see, the layout generates the HTML tags that are common to
all pages. Within the
section, the layout echoes the
$content
variable
which represents the rendering result of content views and is pushed into the
3.7.
VIEWS
layout when
93
yii\base\Controller::render()
is called.
Most layouts should call the following methods like shown in the above
code. These methods mainly trigger events about the rendering process so
that scripts and tags registered in other places can be properly injected into
the places where these methods are called.
• yii\base\View::beginPage():
This method should be called at the
very beginning of the layout. It triggers the
yii\base\View::EVENT_BEGIN_PAGE
event which indicates the beginning of a page.
• yii\base\View::endPage():
of the layout. It triggers the
This method should be called at the end
yii\base\View::EVENT_END_PAGE
event
which indicates the end of a page.
• yii\web\View::head():
head>
This method should be called within the
<
section of an HTML page. It generates a placeholder which will
be replaced with the registered head HTML code (e.g. link tags, meta
tags) when a page nishes rendering.
• yii\web\View::beginBody():
ginning of the
section.
This method should be called at the be-
It triggers the
yii\web\View::EVENT_BEGIN_BODY
event and generates a placeholder which will be replaced by the registered HTML code (e.g.
JavaScript) targeted at the body begin
position.
• yii\web\View::endBody():
of the
This method should be called at the end
section. It triggers the
yii\web\View::EVENT_END_BODY
event and generates a placeholder which will be replaced by the registered HTML code (e.g. JavaScript) targeted at the body end position.
Accessing Data in Layouts
Within a layout, you have access to two predened variables:
$content.
The former refers to the
yii\base\View
$this
and
component, like in nor-
mal views, while the latter contains the rendering result of a content view
which is rendered by calling the
yii\base\Controller::render()
method
in controllers.
If you want to access other data in layouts, you have to use the pull
method as described in the Accessing Data in Views subsection. If you want
to pass data from a content view to a layout, you may use the method
described in the Sharing Data among Views subsection.
Using Layouts
As described in the Rendering in Controllers subsection, when you render a
view by calling the
yii\base\Controller::render()
method in a control-
ler, a layout will be applied to the rendering result. By default, the layout
@app/views/layouts/main.php
will be used.
94
CHAPTER 3.
APPLICATION STRUCTURE
You may use a dierent layout by conguring either
::layout
or
yii\base\Controller::layout.
yii\base\Application
The former governs the lay-
out used by all controllers, while the latter overrides the former for individual
controllers. For example, the following code makes the
@app/views/layouts/post.php
post
layout property is untouched,
@app/views/layouts/main.php as the layout.
controllers, assuming their
default
controller to use
as the layout when rendering its views.
Other
will still use the
namespace app\controllers;
use yii\web\Controller;
class PostController extends Controller
{
public $layout = 'post';
}
// ...
For controllers belonging to a module, you may also congure the module's
yii\base\Module::layout property to use a particular layout for these controllers.
Because the
layout property may be congured at dierent levels (control-
lers, modules, application), behind the scene Yii takes two steps to determine
what is the actual layout le being used for a particular controller.
In the rst step, it determines the layout value and the context module:
•
If the
null,
yii\base\Controller::layout property of the controller is not
yii\base\Controller::module
use it as the layout value and the
of the controller as the context module.
•
If the
yii\base\Controller::layout property of the controller is null
, search through all ancestor modules (including the application itself )
of the controller and nd the rst module whose
::layout property is not null. Use that module
\Module::layout value as the context module and
yii\base\Module
and its yii\base
the chosen layout
value. If such a module cannot be found, it means no layout will be
applied.
In the second step, it determines the actual layout le according to the layout
value and the context module determined in the rst step. The layout value
can be:
•
•
a path alias (e.g.
@app/views/layouts/main).
/main): the layout value
an absolute path (e.g.
starts with a slash. The
actual layout le will be looked for under the application's
\Application::layoutPath
•
a relative path (e.g.
main):
the context module's
the
@app/views/layouts.
the actual layout le will be looked for under
yii\base\Module::layoutPath
which defaults
views/layouts directory under the yii\base\Module::basePath.
boolean value false: no layout will be applied.
to the
•
which defaults to
yii\base
3.7.
VIEWS
95
If the layout value does not contain a le extension, it will use the default
one
.php.
Nested Layouts
Sometimes you may want to nest one layout in another.
For example, in
dierent sections of a Web site, you want to use dierent layouts, while
all these layouts share the same basic layout that generates the overall
HTML5 page structure. You can achieve this goal by calling
yii\base\View
::beginContent() and yii\base\View::endContent() in the child layouts
like the following:
beginContent('@app/views/layouts/base.php'); ?>
...child layout content here...
endContent(); ?>
yii
\base\View::beginContent() and yii\base\View::endContent(). The
parameter passed to yii\base\View::beginContent() species what is the
As shown above, the child layout content should be enclosed within
parent layout. It can be either a layout le or alias.
Using the above approach, you can nest layouts in more than one levels.
Using Blocks
Blocks allow you to specify the view content in one place while displaying
it in another. They are often used together with layouts. For example, you
can dene a block in a content view and display it in the layout.
You call
yii\base\View::beginBlock() and yii\base\View::endBlock()
to dene a block. The block can then be accessed via
],
where
$blockID
$view->blocks[$blockID
stands for a unique ID that you assign to the block when
dening it.
The following example shows how you can use blocks to customize specic
parts of a layout in a content view.
First, in a content view, dene one or multiple blocks:
...
beginBlock('block1'); ?>
...content of block1...
endBlock(); ?>
...
beginBlock('block3'); ?>
...content of block3...
96
CHAPTER 3.
APPLICATION STRUCTURE
endBlock(); ?>
Then, in the layout view, render the blocks if they are available, or display
some default content if a block is not dened.
...
blocks['block1'])): ?>
= $this->blocks['block1'] ?>
... default content for block1 ...
...
blocks['block2'])): ?>
= $this->blocks['block2'] ?>
... default content for block2 ...
...
blocks['block3'])): ?>
= $this->blocks['block3'] ?>
... default content for block3 ...
...
3.7.4 Using View Components
yii\base\View provides many view-related features. While you can get view
components by creating individual instances of yii\base\View or its child
class, in most cases you will mainly use the
view
application component. You
can congure this component in application congurations like the following:
[
]
// ...
'components' => [
'view' => [
'class' => 'app\components\View',
],
// ...
],
View components provide the following useful view-related features, each
described in more details in a separate section:
•
theming: allows you to develop and change the theme for your Web
site.
•
fragment caching: allows you to cache a fragment within a Web page.
3.7.
VIEWS
•
97
client script handling: supports CSS and JavaScript registration and
rendering.
•
asset bundle handling:
supports registering and rendering of asset
bundles.
•
alternative template engines: allows you to use other template engines,
15 , Smarty16 .
such as Twig
You may also frequently use the following minor yet useful features when
you are developing Web pages.
Setting Page Titles
Every Web page should have a title. Normally the title tag is being displayed
in a layout.
However, in practice the title is often determined in content
views rather than layouts.
the
yii\web\View::title
To solve this problem,
yii\web\View
provides
property for you to pass the title information
from content views to layouts.
To make use of this feature, in each content view, you can set the page
title like the following:
title = 'My page title';
?>
Then in the layout, make sure you have the following code in the
section:
= Html::encode($this->title) ?>
Registering Meta Tags
Web pages usually need to generate various meta tags needed by dierent
parties.
Like page titles, meta tags appear in the
section and are
usually generated in layouts.
If you want to specify what meta tags to generate in content views,
you can call
yii\web\View::registerMetaTag() in a content view, like the
following:
registerMetaTag(['name' => 'keywords', 'content' => 'yii, framework,
php']);
?>
The above code will register a keywords meta tag with the view component.
The registered meta tag is rendered after the layout nishes rendering. The
following HTML code will be generated and inserted at the place where you
call
15
16
yii\web\View::head()
in the layout:
http://twig.sensiolabs.org/
http://www.smarty.net/
98
CHAPTER 3.
APPLICATION STRUCTURE
Note that if you call
yii\web\View::registerMetaTag()
multiple times, it
will register multiple meta tags, regardless whether the meta tags are the
same or not.
To make sure there is only a single instance of a meta tag type, you can
specify a key as a second parameter when calling the method. For example,
the following code registers two description meta tags. However, only the
second one will be rendered.
$this->registerMetaTag(['name' => 'description', 'content' => 'This is my
cool website made with Yii!'], 'description');
$this->registerMetaTag(['name' => 'description', 'content' => 'This website
is about funny raccoons.'], 'description');
Registering Link Tags
Like meta tags, link tags are useful in many cases, such as customizing
favicon, pointing to RSS feed or delegating OpenID to another server. You
can work with link tags in the similar way as meta tags by using
\View::registerLinkTag().
yii\web
For example, in a content view, you can re-
gister a link tag like follows,
$this->registerLinkTag([
'title' => 'Live News for Yii',
'rel' => 'alternate',
'type' => 'application/rss+xml',
'href' => 'http://www.yiiframework.com/rss.xml/',
]);
The code above will result in
yii\web\View::registerMetaTag(), you can specify a key when
yii\web\View::registerLinkTag() to avoid generating repeated
Similar as
calling
link tags.
3.7.5 View Events
yii\base\View trigger several events during the view rendering process.
You
may respond to these events to inject content into views or process the
rendering results before they are sent to end users.
• yii\base\View::EVENT_BEFORE_RENDER: triggered at the beginning of
rendering a le in a controller. Handlers of this event may set yii\base
\ViewEvent::isValid to be false to cancel the rendering process.
• yii\base\View::EVENT_AFTER_RENDER: triggered after rendering a le
by the call of yii\base\View::afterRender(). Handlers of this event
3.7.
VIEWS
99
may obtain the rendering result through
yii\base\ViewEvent::output
and may modify this property to change the rendering result.
• yii\base\View::EVENT_BEGIN_PAGE: triggered by the call of yii\base
\View::beginPage() in layouts.
• yii\base\View::EVENT_END_PAGE: triggered by the call of yii\base
\View::endPage() in layouts.
• yii\web\View::EVENT_BEGIN_BODY: triggered by the call of yii\web
\View::beginBody() in layouts.
• yii\web\View::EVENT_END_BODY: triggered by the call of yii\web\View
::endBody() in layouts.
For example, the following code injects the current date at the end of the
page body:
\Yii::$app->view->on(View::EVENT_END_BODY, function () {
echo date('Y-m-d');
});
3.7.6 Rendering Static Pages
Static pages refer to those Web pages whose main content are mostly static
without the need of accessing dynamic data pushed from controllers.
You can output static pages by putting their code in the view, and then
using the code like the following in a controller:
public function actionAbout()
{
return $this->render('about');
}
If a Web site contains many static pages, it would be very tedious repeating
the similar code many times. To solve this problem, you may introduce a
standalone action called
yii\web\ViewAction
in a controller. For example,
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
public function actions()
{
return [
'page' => [
'class' => 'yii\web\ViewAction',
],
];
}
}
Now if you create a view named
pages,
about
under the directory
@app/views/site/
you will be able to display this view by the following URL:
100
CHAPTER 3.
APPLICATION STRUCTURE
http://localhost/index.php?r=site%2Fpage&view=about
The
GET
parameter
view
tells
yii\web\ViewAction
which view is requested.
The action will then look for this view under the directory
pages.
You may congure
@app/views/site/
yii\web\ViewAction::viewPrefix to change the
directory for searching these views.
3.7.7 Best Practices
Views are responsible for presenting models in the format that end users
desire. In general, views
•
should mainly contain presentational code, such as HTML, and simple
PHP code to traverse, format and render data.
•
should not contain code that performs DB queries. Such code should
be done in models.
•
should avoid direct access to request data, such as
$_GET, $_POST.
This
belongs to controllers. If request data is needed, they should be pushed
into views by controllers.
•
may read model properties, but should not modify them.
To make views more manageable, avoid creating views that are too complex
or contain too much redundant code. You may use the following techniques
to achieve this goal:
•
use layouts to represent common presentational sections (e.g.
page
header, footer).
•
divide a complicated view into several smaller ones. The smaller views
can be rendered and assembled into a bigger one using the rendering
methods that we have described.
•
•
create and use widgets as building blocks of views.
create and use helper classes to transform and format data in views.
3.8 Modules
Modules are self-contained software units that consist of models, views, controllers, and other supporting components.
End users can access the con-
trollers of a module when it is installed in application. For these reasons,
modules are often viewed as mini-applications. Modules dier from applications in that modules cannot be deployed alone and must reside within
applications.
3.8.1 Creating Modules
A module is organized as a directory which is called the
::basePath
such as
yii\base\Module
of the module. Within the directory, there are sub-directories,
controllers, models, views,
which hold controllers, models, views, and
3.8.
MODULES
101
other code, just like in an application.
The following example shows the
content within a module:
forum/
Module.php
controllers/
DefaultController.php
models/
views/
layouts/
default/
index.php
the module class file
containing controller class files
the default controller class file
containing model class files
containing controller view and layout files
containing layout view files
containing view files for DefaultController
the index view file
Module Classes
yii
\base\Module. The class should be located directly under the module's yii
\base\Module::basePath and should be autoloadable. When a module is
Each module should have a unique module class which extends from
being accessed, a single instance of the corresponding module class will be
created. Like application instances, module instances are used to share data
and components for code within modules.
The following is an example how a module class may look like:
namespace app\modules\forum;
class Module extends \yii\base\Module
{
public function init()
{
parent::init();
}
}
If the
$this->params['foo'] = 'bar';
// ... other initialization code ...
init()
method contains a lot of code initializing the module's proper-
ties, you may also save them in terms of a conguration and load it with the
following code in
init():
public function init()
{
parent::init();
// initialize the module with the configuration loaded from config.php
\Yii::configure($this, require(__DIR__ . '/config.php'));
}
where the conguration le
config.php
may contain the following content,
similar to that in an application conguration.
[
102
];
CHAPTER 3.
APPLICATION STRUCTURE
// list of component configurations
],
'params' => [
// list of parameters
],
Controllers in Modules
When creating controllers in a module, a convention is to put the controller classes under the
module class.
the
controllers
controllers
sub-namespace of the namespace of the
This also means the controller class les should be put in
directory within the module's
For example, to create a
post
yii\base\Module::basePath.
controller in the
forum
module shown in the
last subsection, you should declare the controller class like the following:
namespace app\modules\forum\controllers;
use yii\web\Controller;
class PostController extends Controller
{
// ...
}
You may customize the namespace of controller classes by conguring the
yii\base\Module::controllerNamespace
property.
In case some of the
controllers are outside of this namespace, you may make them accessible
by conguring the
yii\base\Module::controllerMap
property, similar to
what you do in an application.
Views in Modules
Views in a module should be put in the
yii\base\Module::basePath.
views
directory within the module's
For views rendered by a controller in the
views/ControllerID, where
ControllerID refers to the controller ID. For example, if the controller class
is PostController, the directory would be views/post within the module's yii
module, they should be put under the directory
\base\Module::basePath.
A module can specify a layout that is applied to the views rendered by
the module's controllers. The layout should be put in the
ectory by default, and you should congure the
property to point to the layout name.
views/layouts
dir-
yii\base\Module::layout
If you do not congure the
property, the application's layout will be used instead.
layout
3.8.
MODULES
103
Console commands in Modules
Your module may also declare commands, that will be available through the
Console mode.
In order for the command line utility to see your commands, you will need
to change the
yii\base\Module::controllerNamespace property, when Yii
is executed in the console mode, and point it to your commands namespace.
One way to achieve that is to test the instance type of the Yii application
in the module's
init()
method:
public function init()
{
parent::init();
if (Yii::$app instanceof \yii\console\Application) {
$this->controllerNamespace = 'app\modules\forum\commands';
}
}
Your commands will then be available from the command line using the
following route:
yii //
3.8.2 Using Modules
To use a module in an application, simply congure the application by listing
the module in the
ation.
yii\base\Application::modules property of the applic-
The following code in the application conguration uses the
forum
module:
[
]
The
'modules' => [
'forum' => [
'class' => 'app\modules\forum\Module',
// ... other configurations for the module ...
],
],
yii\base\Application::modules
property takes an array of module
congurations. Each array key represents a
module ID which uniquely identi-
es the module among all modules in the application, and the corresponding
array value is a conguration for creating the module.
Routes
Like accessing controllers in an application, routes are used to address controllers in a module. A route for a controller within a module must begin
with the module ID followed by the controller ID and action ID. For example, if an application uses a module named
forum,
then the route
forum/
104
CHAPTER 3.
post/index
would represent the
index
APPLICATION STRUCTURE
action of the
post
controller in the mod-
ule. If the route only contains the module ID, then the
::defaultRoute
property, which defaults to
default,
controller/action should be used. This means a route
the
default
controller in the
forum
yii\base\Module
will determine which
forum
would represent
module.
Accessing Modules
Within a module, you may often need to get the instance of the module
class so that you can access the module ID, module parameters, module
components, etc. You can do so by using the following statement:
$module = MyModuleClass::getInstance();
MyModuleClass refers to the name
interested in. The getInstance() method
where
of the module class that you are
will return the currently requested
instance of the module class. If the module is not requested, the method will
return
null.
Note that you do not want to manually create a new instance
of the module class because it will be dierent from the one created by Yii
in response to a request.
Info: When developing a module, you should not assume the
module will use a xed ID. This is because a module can be
associated with an arbitrary ID when used in an application or
within another module. In order to get the module ID, you should
use the above approach to get the module instance rst, and then
get the ID via
$module->id.
You may also access the instance of a module using the following approaches:
// get the child module whose ID is "forum"
$module = \Yii::$app->getModule('forum');
// get the module to which the currently requested controller belongs
$module = \Yii::$app->controller->module;
The rst approach is only useful when you know the module ID, while the
second approach is best used when you know about the controllers being
requested.
Once you have the module instance, you can access parameters and components registered with the module. For example,
$maxPostCount = $module->params['maxPostCount'];
Bootstrapping Modules
Some modules may need to be run for every request. The
yii\debug\Module
module is such an example. To do so, list the IDs of such modules in the
yii\base\Application::bootstrap
property of the application.
3.8.
MODULES
105
For example, the following application conguration makes sure the
debug
module is always loaded:
[
]
'bootstrap' => [
'debug',
],
'modules' => [
'debug' => 'yii\debug\Module',
],
3.8.3 Nested Modules
Modules can be nested in unlimited levels. That is, a module can contain
another module which can contain yet another module. We call the former
parent module
in the
while the latter
child module.
yii\base\Module::modules
Child modules must be declared
property of their parent modules.
For
example,
namespace app\modules\forum;
class Module extends \yii\base\Module
{
public function init()
{
parent::init();
}
}
$this->modules = [
'admin' => [
// you should consider using a shorter namespace here!
'class' => 'app\modules\forum\modules\admin\Module',
],
];
For a controller within a nested module, its route should include the IDs of
forum/admin/dashboard/index
the dashboard controller in the admin module
forum module.
all its ancestor modules. For example, the route
represents the
index
action of
which is a child module of the
Info:
The
yii\base\Module::getModule()
method only re-
turns the child module directly belonging to its parent.
The
yii\base\Application::loadedModules property keeps a list of
loaded modules, including both direct children and nested ones,
indexed by their class names.
106
CHAPTER 3.
APPLICATION STRUCTURE
3.8.4 Best Practices
Modules are best used in large applications whose features can be divided
into several groups, each consisting of a set of closely related features. Each
such feature group can be developed as a module which is developed and
maintained by a specic developer or team.
Modules are also a good way of reusing code at the feature group level.
Some commonly used features, such as user management, comment management, can all be developed in terms of modules so that they can be reused
easily in future projects.
3.9 Filters
Filters are objects that run before and/or after controller actions. For example, an access control lter may run before actions to ensure that they are
allowed to be accessed by particular end users; a content compression lter
may run after actions to compress the response content before sending them
out to end users.
A lter may consist of a pre-lter (ltering logic applied
and/or a post-lter (logic applied
after
before
actions)
actions).
3.9.1 Using Filters
Filters are essentially a special kind of behaviors. Therefore, using lters is
the same as using behaviors. You can declare lters in a controller class by
overriding its
yii\base\Controller::behaviors()
method like the follow-
ing:
public function behaviors()
{
return [
[
'class' => 'yii\filters\HttpCache',
'only' => ['index', 'view'],
'lastModified' => function ($action, $params) {
$q = new \yii\db\Query();
return $q->from('user')->max('updated_at');
},
],
];
}
By default, lters declared in a controller class will be applied to
in that controller.
only
property. In the above example, the
index
and
::except
actions
You can, however, explicitly specify which actions the
lter should be applied to by conguring the
view
all
yii\base\ActionFilter::
HttpCache
actions. You can also congure the
lter only applies to the
yii\base\ActionFilter
property to blacklist some actions from being ltered.
3.9.
FILTERS
107
Besides controllers, you can also declare lters in a module or application.
When you do so, the lters will be applied to
all
controller actions
belonging to that module or application, unless you congure the lters'
yii
\base\ActionFilter::only and yii\base\ActionFilter::except properties like described above.
Note: When declaring lters in modules or applications, you
yii\base\ActionFilter
yii\base\ActionFilter::except properties. This
should use routes instead of action IDs in the
::only
and
is because action IDs alone cannot fully specify actions within
the scope of a module or application.
When multiple lters are congured for a single action, they are applied
according to the rules described below:
•
Pre-ltering
Apply lters declared in the application in the order they are
listed in
behaviors().
Apply lters declared in the module in the order they are listed
in
behaviors().
Apply lters declared in the controller in the order they are listed
in
behaviors().
If any of the lters cancel the action execution, the lters (both
pre-lters and post-lters) after it will not be applied.
•
•
Running the action if it passes the pre-ltering.
Post-ltering
Apply lters declared in the controller in the reverse order they
are listed in
behaviors().
Apply lters declared in the module in the reverse order they are
listed in
behaviors().
Apply lters declared in the application in the reverse order they
are listed in
behaviors().
3.9.2 Creating Filters
yii\base\ActionFilter and
yii\base\ActionFilter::beforeAction() and/or yii\base
\ActionFilter::afterAction() methods. The former will be executed beTo create a new action lter, extend from
override the
fore an action runs while the latter after an action runs. The return value of
yii\base\ActionFilter::beforeAction()
should be executed or not.
If it is
false,
determines whether an action
the lters after this one will be
skipped and the action will not be executed.
The following example shows a lter that logs the action execution time:
namespace app\components;
use Yii;
108
CHAPTER 3.
APPLICATION STRUCTURE
use yii\base\ActionFilter;
class ActionTimeFilter extends ActionFilter
{
private $_startTime;
public function beforeAction($action)
{
$this->_startTime = microtime(true);
return parent::beforeAction($action);
}
}
public function afterAction($action, $result)
{
$time = microtime(true) - $this->_startTime;
Yii::trace("Action '{$action->uniqueId}' spent $time second.");
return parent::afterAction($action, $result);
}
3.9.3 Core Filters
Yii provides a set of commonly used lters, found primarily under the
filters
yii\
namespace. In the following, we will briey introduce these lters.
yii\filters\AccessControl
AccessControl provides simple access control based on a set of
\AccessControl::rules.
yii\filters
In particular, before an action is executed, Ac-
cessControl will examine the listed rules and nd the rst one that matches
the current context variables (such as user IP address, user login status, etc.)
The matching rule will dictate whether to allow or deny the execution of the
requested action. If no rule matches, the access will be denied.
The following example shows how to allow authenticated users to access
the
create
and
update
actions while denying all other users from accessing
these two actions.
use yii\filters\AccessControl;
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['create', 'update'],
'rules' => [
// allow authenticated users
[
'allow' => true,
'roles' => ['@'],
],
3.9.
FILTERS
];
}
],
],
109
// everything else is denied by default
For more details about access control in general, please refer to the Authorization section.
Authentication Method Filters
Authentication method lters are used to authenticate a user using various
methods, such as HTTP Basic Auth
all under the
yii\filters\auth
17 , OAuth 218 . These lter classes are
namespace.
The following example shows how you can use
yii\filters\auth\HttpBasicAuth
to authenticate a user using an access token based on HTTP Basic Auth
yii\web\User::identityClass
must implement the yii\web\IdentityInterface::findIdentityByAccessToken()
method. Note that in order for this to work, your
method.
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
return [
'basicAuth' => [
'class' => HttpBasicAuth::className(),
],
];
}
Authentication method lters are commonly used in implementing RESTful
APIs. For more details, please refer to the RESTful Authentication section.
yii\filters\ContentNegotiator
ContentNegotiator supports response format negotiation and application
language negotiation. It will try to determine the response format and/or
language by examining
GET
parameters and
Accept
HTTP header.
In the following example, ContentNegotiator is congured to support
JSON and XML response formats, and English (United States) and German
languages.
use yii\filters\ContentNegotiator;
use yii\web\Response;
public function behaviors()
{
17
18
http://en.wikipedia.org/wiki/Basic_access_authentication
http://oauth.net/2/
110
}
CHAPTER 3.
APPLICATION STRUCTURE
return [
[
'class' => ContentNegotiator::className(),
'formats' => [
'application/json' => Response::FORMAT_JSON,
'application/xml' => Response::FORMAT_XML,
],
'languages' => [
'en-US',
'de',
],
],
];
Response formats and languages often need to be determined much earlier
during the application lifecycle.
For this reason, ContentNegotiator is de-
signed in a way such that it can also be used as a bootstrapping component
besides being used as a lter.
For example, you may congure it in the
application conguration like the following:
use yii\filters\ContentNegotiator;
use yii\web\Response;
[
];
'bootstrap' => [
[
'class' => ContentNegotiator::className(),
'formats' => [
'application/json' => Response::FORMAT_JSON,
'application/xml' => Response::FORMAT_XML,
],
'languages' => [
'en-US',
'de',
],
],
],
Info: In case the preferred content type and language cannot be
determined from a request, the rst format and language listed
in
formats
and
languages
will be used.
yii\filters\HttpCache
HttpCache implements client-side caching by utilizing the
Etag
HTTP headers. For example,
use yii\filters\HttpCache;
public function behaviors()
Last-Modified
and
3.9.
{
FILTERS
111
return [
[
'class' => HttpCache::className(),
'only' => ['index'],
'lastModified' => function ($action, $params) {
$q = new \yii\db\Query();
return $q->from('user')->max('updated_at');
},
],
];
}
Please refer to the HTTP Caching section for more details about using HttpCache.
yii\filters\PageCache
PageCache implements server-side caching of whole pages. In the following
example, PageCache is applied to the
index action to cache the whole page for
post table changes. It
maximum 60 seconds or until the count of entries in the
also stores dierent versions of the page depending on the chosen application
language.
use yii\filters\PageCache;
use yii\caching\DbDependency;
public function behaviors()
{
return [
'pageCache' => [
'class' => PageCache::className(),
'only' => ['index'],
'duration' => 60,
'dependency' => [
'class' => DbDependency::className(),
'sql' => 'SELECT COUNT(*) FROM post',
],
'variations' => [
\Yii::$app->language,
]
],
];
}
Please refer to the Page Caching section for more details about using PageCache.
yii\filters\RateLimiter
RateLimiter implements a rate limiting algorithm based on the leaky bucket
19 . It is primarily used in implementing RESTful APIs. Please
algorithm
19
http://en.wikipedia.org/wiki/Leaky_bucket
112
CHAPTER 3.
APPLICATION STRUCTURE
refer to the Rate Limiting section for details about using this lter.
yii\filters\VerbFilter
VerbFilter checks if the HTTP request methods are allowed by the requested
actions. If not allowed, it will throw an HTTP 405 exception. In the following
example, VerbFilter is declared to specify a typical set of allowed request
methods for CRUD actions.
use yii\filters\VerbFilter;
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'index' => ['get'],
'view' => ['get'],
'create' => ['get', 'post'],
'update' => ['get', 'put', 'post'],
'delete' => ['post', 'delete'],
],
],
];
}
yii\filters\Cors
Cross-origin resource sharing CORS
20 is a mechanism that allows many re-
sources (e.g. fonts, JavaScript, etc.) on a Web page to be requested from
another domain outside the domain the resource originated from. In particular, JavaScript's AJAX calls can use the XMLHttpRequest mechanism. Such
cross-domain requests would otherwise be forbidden by Web browsers, per
the same origin security policy. CORS denes a way in which the browser
and the server can interact to determine whether or not to allow the crossorigin request.
The
yii\filters\Cors
should be dened before Authentication / Au-
thorization lters to make sure the CORS headers will always be sent.
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
public function behaviors()
{
return ArrayHelper::merge([
[
'class' => Cors::className(),
],
20
https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS
3.9.
}
FILTERS
113
], parent::behaviors());
Also check the section on REST Controllers if you want to add the CORS
lter to an
yii\rest\ActiveController
class in your API.
The Cors ltering could be tuned using the
yii\filters\Cors::$cors
property.
• cors['Origin']:
['*'
] (everyone) or ['http://www.myserver.net', 'http://www.myotherserver.
com']. Default to ['*'].
• cors['Access-Control-Request-Method']: array of allowed verbs like ['
GET', 'OPTIONS', 'HEAD']. Default to ['GET', 'POST', 'PUT', 'PATCH', '
DELETE', 'HEAD', 'OPTIONS'].
• cors['Access-Control-Request-Headers']: array of allowed headers. Can
be ['*'] all headers or specic ones ['X-Request-With']. Default to ['*
'].
• cors['Access-Control-Allow-Credentials']: dene if current request can
be made using credentials. Can be true, false or null (not set). Default
to null.
• cors['Access-Control-Max-Age']: dene lifetime of pre-ight request. Default to 86400.
For example, allowing CORS for origin : http://www.myserver.net with method
GET, HEAD and OPTIONS :
array used to dene allowed origins.
Can be
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
public function behaviors()
{
return ArrayHelper::merge([
[
'class' => Cors::className(),
'cors' => [
'Origin' => ['http://www.myserver.net'],
'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'
],
],
],
], parent::behaviors());
}
You may tune the CORS headers by overriding default parameters on a per
action basis.
the
login
For example adding the
Access-Control-Allow-Credentials
action could be done like this :
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
public function behaviors()
{
for
114
}
CHAPTER 3.
APPLICATION STRUCTURE
return ArrayHelper::merge([
[
'class' => Cors::className(),
'cors' => [
'Origin' => ['http://www.myserver.net'],
'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'
],
],
'actions' => [
'login' => [
'Access-Control-Allow-Credentials' => true,
]
]
],
], parent::behaviors());
3.10 Widgets
Widgets are reusable building blocks used in views to create complex and
congurable user interface elements in an object-oriented fashion.
For ex-
ample, a date picker widget may generate a fancy date picker that allows
users to pick a date as their input. All you need to do is just to insert the
code in a view like the following:
= DatePicker::widget(['name' => 'date']) ?>
There are a good number of widgets bundled with Yii, such as
\ActiveForm, yii\widgets\Menu,
yii\widgets
jQuery UI widgets, Twitter Bootstrap
widgets. In the following, we will introduce the basic knowledge about widgets. Please refer to the class API documentation if you want to learn about
the usage of a particular widget.
3.10.1 Using Widgets
Widgets are primarily used in views. You can call the
widget()
yii\base\Widget::
method to use a widget in a view. The method takes a congura-
tion array for initializing the widget and returns the rendering result of the
widget. For example, the following code inserts a date picker widget which
is congured to use the Russian language and keep the input in the
attribute of
$model.
= DatePicker::widget([
'model' => $model,
from_date
3.10.
WIDGETS
115
'attribute' => 'from_date',
'language' => 'ru',
'clientOptions' => [
'dateFormat' => 'yy-mm-dd',
],
]) ?>
Some widgets can take a block of content which should be enclosed between
the invocation of
yii\base\Widget::begin() and yii\base\Widget::end().
yii\widgets\ActiveForm widget
For example, the following code uses the
to generate a login form.
ing
Source Exif Data:
File Type : PDF File Type Extension : pdf MIME Type : application/pdf PDF Version : 1.5 Linearized : No Page Count : 575 Page Mode : None Page Layout : SinglePage Author : " Qiang Xue, Alexander Makarov, Carsten Brandt, Klimov Paul, and many contributors from the Yii community " Title : "The definitive Guide to Yii 2.0" Subject : Creator : LaTeX with hyperref package Producer : pdfTeX-1.40.15 Create Date : 2017:02:10 22:47:40+01:00 Modify Date : 2017:02:10 22:47:40+01:00 Trapped : False PTEX Fullbanner : This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2015/dev/Debian) kpathsea version 6.2.1devEXIF Metadata provided by EXIF.tools