mirror of
				https://github.com/yiisoft/yii2.git
				synced 2025-11-04 06:37:55 +08:00 
			
		
		
		
	new translation
This commit is contained in:
		@ -1,27 +1,17 @@
 | 
			
		||||
控制器
 | 
			
		||||
Controllers
 | 
			
		||||
===========
 | 
			
		||||
 | 
			
		||||
控制器是 [MVC](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) 模式中的一部分,
 | 
			
		||||
是继承[[yii\base\Controller]]类的对象,负责处理请求和生成响应。
 | 
			
		||||
具体来说,控制器从[应用主体](structure-applications.md)接管控制后会分析请求数据并传送到[模型](structure-models.md),
 | 
			
		||||
传送模型结果到[视图](structure-views.md),最后生成输出响应信息。
 | 
			
		||||
Controllers are part of the [MVC](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) architecture.
 | 
			
		||||
They are objects of classes extending from [[yii\base\Controller]] and are responsible for processing requests and
 | 
			
		||||
generating responses. In particular, after taking over the control from [applications](structure-applications.md),
 | 
			
		||||
controllers will analyze incoming request data, pass them to [models](structure-models.md), inject model results
 | 
			
		||||
into [views](structure-views.md), and finally generate outgoing responses.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 操作 <a name="actions"></a>
 | 
			
		||||
## Actions <a name="actions"></a>
 | 
			
		||||
 | 
			
		||||
控制器由 *操作* 组成,它是执行终端用户请求的最基础的单元,一个控制器可有一个或多个操作。
 | 
			
		||||
Controllers are composed by *actions* which are the most basic units that end users can address and request for
 | 
			
		||||
execution. A controller can have one or multiple actions.
 | 
			
		||||
 | 
			
		||||
如下示例显示包含两个操作`view` and `create` 的控制器`post`:
 | 
			
		||||
The following example shows a `post` controller with two actions: `view` and `create`:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
namespace app\controllers;
 | 
			
		||||
@ -62,41 +52,26 @@ class PostController extends Controller
 | 
			
		||||
 | 
			
		||||
在操作 `view` (定义为 `actionView()` 方法)中, 代码首先根据请求模型ID加载 [模型](structure-models.md),
 | 
			
		||||
如果加载成功,会渲染名称为`view`的[视图](structure-views.md)并显示,否则会抛出一个异常。
 | 
			
		||||
 the `view` action (defined by the `actionView()` method), the code first loads the [model](structure-models.md)
 | 
			
		||||
according to the requested model ID; If the model is loaded successfully, it will display it using
 | 
			
		||||
a [view](structure-views.md) named `view`. Otherwise, it will throw an exception.
 | 
			
		||||
 | 
			
		||||
在操作 `create` (定义为 `actionCreate()` 方法)中, 代码相似. 先将请求数据填入[模型](structure-models.md),
 | 
			
		||||
然后保存模型,如果两者都成功,会跳转到ID为新创建的模型的`view`操作,否则显示提供用户输入的`create`视图。
 | 
			
		||||
In the `create` action (defined by the `actionCreate()` method), the code is similar. It first tries to populate
 | 
			
		||||
the [model](structure-models.md) using the request data and save the model. If both succeed it will redirect
 | 
			
		||||
the browser to the `view` action with the ID of the newly created model. Otherwise it will display
 | 
			
		||||
the `create` view through which users can provide the needed input.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 路由 <a name="routes"></a>
 | 
			
		||||
## Routes <a name="routes"></a>
 | 
			
		||||
 | 
			
		||||
终端用户通过所谓的*路由*寻找到操作,路由是包含以下部分的字符串:End users address actions through the so-called *routes*. A route is a string that consists of the following parts:
 | 
			
		||||
End users address actions through the so-called *routes*. A route is a string that consists of the following parts:
 | 
			
		||||
终端用户通过所谓的*路由*寻找到操作,路由是包含以下部分的字符串:
 | 
			
		||||
 | 
			
		||||
* 模型ID: 仅存在于控制器属于非应用的[模块](structure-modules.md);
 | 
			
		||||
* 控制器ID: 同应用(或同模块如果为模块下的控制器)下唯一标识控制器的字符串;
 | 
			
		||||
* 操作ID: 同控制器下唯一标识操作的字符串。
 | 
			
		||||
* a module ID: this exists only if the controller belongs to a non-application [module](structure-modules.md);
 | 
			
		||||
* a controller ID: a string that uniquely identifies 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 identifies 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:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
ModuleID/ControllerID/ActionID
 | 
			
		||||
@ -104,20 +79,13 @@ ModuleID/ControllerID/ActionID
 | 
			
		||||
 | 
			
		||||
如果用户的请求地址为 `http://hostname/index.php?r=site/index`, 会执行`site` 控制器的`index` 操作。
 | 
			
		||||
更多关于处理路由的详情请参阅 [路由](runtime-routing.md) 一节。
 | 
			
		||||
So if a user requests with the URL `http://hostname/index.php?r=site/index`, the `index` action in the `site` controller
 | 
			
		||||
will be executed. For more details how routes are resolved into actions, please refer to
 | 
			
		||||
the [Routing](runtime-routing.md) section.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 创建控制器 <a name="creating-controllers"></a>
 | 
			
		||||
## Creating Controllers <a name="creating-controllers"></a>
 | 
			
		||||
 | 
			
		||||
在[[yii\web\Application|Web applications]]网页应用中,控制器应继承[[yii\web\Controller]] 或它的子类。
 | 
			
		||||
同理在[[yii\console\Application|console applications]]控制台应用中,控制器继承[[yii\console\Controller]] 或它的子类。
 | 
			
		||||
如下代码定义一个 `site` 控制器:
 | 
			
		||||
In [[yii\web\Application|Web applications]], controllers should extend from [[yii\web\Controller]] or its
 | 
			
		||||
child classes. Similarly in [[yii\console\Application|console applications]], controllers should extend from
 | 
			
		||||
[[yii\console\Controller]] or its child classes. The following code defines a `site` controller:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
namespace app\controllers;
 | 
			
		||||
@ -131,89 +99,50 @@ class SiteController extends Controller
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 控制器ID <a name="controller-ids"></a>
 | 
			
		||||
### Controller IDs <a name="controller-ids"></a>
 | 
			
		||||
 | 
			
		||||
通常情况下,控制器用来处理请求有关的资源类型,因此控制器ID通常为和资源有关的名词。
 | 
			
		||||
例如使用`article`作为处理文章的控制器ID。
 | 
			
		||||
For example, you may use `article` as the ID of a controller that handles article data.
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
控制器ID应仅包含英文小写字母、数字、下划线、中横杠和正斜杠,
 | 
			
		||||
例如 `article` 和 `post-comment` 是真是的控制器ID,`article?`, `PostComment`, `admin\post`不是控制器ID。
 | 
			
		||||
By default, controller IDs should contain these characters only: English letters in lower case, digits,
 | 
			
		||||
underscores, dashes and forward slashes. For example, `article` and `post-comment` are both valid controller IDs,
 | 
			
		||||
while `article?`, `PostComment`, `admin\post` are not.
 | 
			
		||||
 | 
			
		||||
控制器Id可包含子目录前缀,例如 `admin/article` 代表
 | 
			
		||||
[[yii\base\Application::controllerNamespace|controller namespace]]控制器命名空间下 `admin`子目录中 `article` 控制器。
 | 
			
		||||
子目录前缀可为英文大小写字母、数字、下划线、正斜杠,其中正斜杠用来区分多级子目录(如 `panels/admin`)。
 | 
			
		||||
A controller ID may also contain a subdirectory prefix. For example, `admin/article` stands for an `article` controller
 | 
			
		||||
in the `admin` subdirectory under the [[yii\base\Application::controllerNamespace|controller namespace]].
 | 
			
		||||
Valid characters for subdirectory prefixes 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`).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 控制器类命名 <a name="controller-class-naming"></a>
 | 
			
		||||
### Controller Class Naming <a name="controller-class-naming"></a>
 | 
			
		||||
 | 
			
		||||
控制器ID遵循以下规则衍生控制器类名:
 | 
			
		||||
Controller class names can be derived from controller IDs according to the following rules:
 | 
			
		||||
 | 
			
		||||
* 将用正斜杠区分的每个单词第一个字母转为大写。注意如果控制器ID包含正斜杠,只将最后的正斜杠后的部分第一个字母转为大写;
 | 
			
		||||
* 去掉中横杠,将正斜杠替换为反斜杠;
 | 
			
		||||
* 增加`Controller`后缀;
 | 
			
		||||
* 在前面增加[[yii\base\Application::controllerNamespace|controller namespace]]控制器命名空间.
 | 
			
		||||
* And prepend the [[yii\base\Application::controllerNamespace|controller namespace]].
 | 
			
		||||
* Turn the first letter in each word separated by dashes 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.
 | 
			
		||||
* Remove dashes and replace any forward slashes with backward slashes.
 | 
			
		||||
* Append the suffix `Controller`.
 | 
			
		||||
* And prepend the [[yii\base\Application::controllerNamespace|controller namespace]].
 | 
			
		||||
 | 
			
		||||
下面为一些示例,假设[[yii\base\Application::controllerNamespace|controller namespace]]控制器命名空间为 `app\controllers`:
 | 
			
		||||
The followings are some examples, assuming the [[yii\base\Application::controllerNamespace|controller namespace]]
 | 
			
		||||
takes the default value `app\controllers`:
 | 
			
		||||
 | 
			
		||||
* `article` 对应 `app\controllers\ArticleController`;
 | 
			
		||||
* `post-comment` 对应 `app\controllers\PostCommentController`;
 | 
			
		||||
* `admin/post-comment` 对应 `app\controllers\admin\PostCommentController`;
 | 
			
		||||
* `adminPanels/post-comment` 对应 `app\controllers\adminPanels\PostCommentController`.
 | 
			
		||||
* `article` derives `app\controllers\ArticleController`;
 | 
			
		||||
* `post-comment` derives `app\controllers\PostCommentController`;
 | 
			
		||||
* `admin/post-comment` derives `app\controllers\admin\PostCommentController`;
 | 
			
		||||
* `adminPanels/post-comment` derives `app\controllers\adminPanels\PostCommentController`.
 | 
			
		||||
 | 
			
		||||
控制器类必须能被 [自动加载](concept-autoloading.md),所以在上面的例子中,
 | 
			
		||||
控制器`article` 类应在 [别名](concept-aliases.md) 为`@app/controllers/ArticleController.php`的文件中定义,
 | 
			
		||||
控制器`admin/post2-comment`应在`@app/controllers/admin/Post2CommentController.php`文件中。
 | 
			
		||||
Controller classes must be [autoloadable](concept-autoloading.md). For this reason, in the above examples,
 | 
			
		||||
the `article` controller class should be saved in the file whose [alias](concept-aliases.md)
 | 
			
		||||
is `@app/controllers/ArticleController.php`; while the `admin/post2-comment` controller should be
 | 
			
		||||
in `@app/controllers/admin/Post2CommentController.php`.
 | 
			
		||||
 | 
			
		||||
> 补充: 最后一个示例 `admin/post2-comment` 表示你可以将控制器放在
 | 
			
		||||
  [[yii\base\Application::controllerNamespace|controller namespace]]控制器命名空间下的子目录中,
 | 
			
		||||
  在你不想用 [模块](structure-modules.md) 的情况下给控制器分类,这种方式很有用。
 | 
			
		||||
> Info: The last example `admin/post2-comment` shows how you can put a controller under a sub-directory
 | 
			
		||||
  of the [[yii\base\Application::controllerNamespace|controller namespace]]. This is useful when you want
 | 
			
		||||
  to organize your controllers into several categories and you do not want to use [modules](structure-modules.md).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 控制器部署 <a name="controller-map"></a>
 | 
			
		||||
### Controller Map <a name="controller-map"></a>
 | 
			
		||||
 | 
			
		||||
可通过配置 [[yii\base\Application::controllerMap|controller map]] 来强制上述的控制器ID和类名对应,
 | 
			
		||||
通常用在使用第三方不能掌控类名的控制器上。
 | 
			
		||||
You can configure [[yii\base\Application::controllerMap|controller map]] to overcome the constraints
 | 
			
		||||
of the controller IDs and class names described above. This is mainly useful when you are using some
 | 
			
		||||
third-party controllers which you do not control over their class names.
 | 
			
		||||
 | 
			
		||||
配置 [应用配置](structure-applications.md#application-configurations) 
 | 
			
		||||
中的[application configuration](structure-applications.md#application-configurations),如下所示:
 | 
			
		||||
You may configure [[yii\base\Application::controllerMap|controller map]] in the
 | 
			
		||||
[application configuration](structure-applications.md#application-configurations) like the following:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
[
 | 
			
		||||
@ -232,20 +161,14 @@ You may configure [[yii\base\Application::controllerMap|controller map]] in the
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 默认控制器 <a name="default-controller"></a>
 | 
			
		||||
### Default Controller <a name="default-controller"></a>
 | 
			
		||||
 | 
			
		||||
每个应用有一个由[[yii\base\Application::defaultRoute]]属性指定的默认控制器;
 | 
			
		||||
当请求没有指定 [路由](#ids-routes),该属性值作为路由使用。
 | 
			
		||||
对于[[yii\web\Application|Web applications]]网页应用,它的值为 `'site'`,
 | 
			
		||||
对于 [[yii\console\Application|console applications]]控制台应用,它的值为 `help`,
 | 
			
		||||
所以URL为 `http://hostname/index.php` 表示由 `site` 控制器来处理。
 | 
			
		||||
Each application has a default controller specified via the [[yii\base\Application::defaultRoute]] property.
 | 
			
		||||
When a request does not specify a [route](#ids-routes), the route specified by this property will be used.
 | 
			
		||||
For [[yii\web\Application|Web applications]], its value is `'site'`, while for [[yii\console\Application|console applications]],
 | 
			
		||||
it is `help`. Therefore, if a URL is `http://hostname/index.php`, it means the `site` controller will handle the request.
 | 
			
		||||
 | 
			
		||||
可以在 [应用配置](structure-applications.md#application-configurations) 中修改默认控制器,如下所示:
 | 
			
		||||
You may change the default controller with the following [application configuration](structure-applications.md#application-configurations):
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
[
 | 
			
		||||
@ -255,13 +178,9 @@ You may change the default controller with the following [application configurat
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 创建操作 <a name="creating-actions"></a>
 | 
			
		||||
## Creating Actions <a name="creating-actions"></a>
 | 
			
		||||
 | 
			
		||||
创建操作可简单地在控制器类中定义所谓的 *操作方法* 来完成,操作方法必须是以`action`开头的公有方法。
 | 
			
		||||
操作方法的返回值会作为响应数据发送给终端用户,如下代码定义了两个操作 `index` 和 `hello-world`:
 | 
			
		||||
Creating actions can be as simple as defining the so-called *action methods* in a controller class. An action method is
 | 
			
		||||
a *public* method whose name starts with the word `action`. The return value of an action method represents
 | 
			
		||||
the response data to be sent to end users. The following code defines two actions `index` and `hello-world`:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
namespace app\controllers;
 | 
			
		||||
@ -284,75 +203,44 @@ class SiteController extends Controller
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 操作ID <a name="action-ids"></a>
 | 
			
		||||
### Action IDs <a name="action-ids"></a>
 | 
			
		||||
 | 
			
		||||
操作通常是用来执行资源的特定操作,因此,操作ID通常为动词,如`view`, `update`等等。
 | 
			
		||||
An action is often designed to perform a particular manipulation about a resource. For this reason,
 | 
			
		||||
action IDs are usually verbs, such as `view`, `update`, etc.
 | 
			
		||||
操作通常是用来执行资源的特定操作,因此,操作ID通常为动词,如`view`, `update`等。
 | 
			
		||||
 | 
			
		||||
操作ID应仅包含英文小写字母、数字、下划线和中横杠,操作ID中的中横杠用来分隔单词。
 | 
			
		||||
例如`view`, `update2`, `comment-post`是真实的操作ID,`view?`, `Update`不是操作ID.
 | 
			
		||||
By default, action IDs should contain these characters only: English letters in lower case, digits,
 | 
			
		||||
underscores and dashes. The dashes in an actionID are used to separate words. For example,
 | 
			
		||||
`view`, `update2`, `comment-post` are all valid action IDs, while `view?`, `Update` are not.
 | 
			
		||||
 | 
			
		||||
可通过两种方式创建操作ID,内联操作和独立操作. An inline action is
 | 
			
		||||
内联操作在控制器类中定义为方法;独立操作是继承[[yii\base\Action]]或它的子类的类。
 | 
			
		||||
内联操作容易创建,在无需重用的情况下优先使用;
 | 
			
		||||
独立操作相反,主要用于多个控制器重用,或重构为[扩展](structure-extensions.md)。
 | 
			
		||||
You can create actions in two ways: inline actions and standalone actions. An inline action is
 | 
			
		||||
defined as a method in the controller class, while a standalone action is a class extending
 | 
			
		||||
[[yii\base\Action]] or its child class. Inline actions take less effort 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 different controllers or be redistributed as [extensions](structure-extensions.md).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 内联操作 <a name="inline-actions"></a>
 | 
			
		||||
### Inline Actions <a name="inline-actions"></a>
 | 
			
		||||
 | 
			
		||||
内联操作指的是根据我们刚描述的操作方法。
 | 
			
		||||
Inline actions refer to the actions that are defined in terms of action methods as we just described.
 | 
			
		||||
 | 
			
		||||
操作方法的名字是根据操作ID遵循如下规则衍生:
 | 
			
		||||
The names of the action methods are derived from action IDs according to the following criteria:
 | 
			
		||||
 | 
			
		||||
* 将每个单词的第一个字母转为大写;
 | 
			
		||||
* 去掉中横杠;
 | 
			
		||||
* 增加`action`前缀.
 | 
			
		||||
* Turn the first letter in each word of the action ID into upper case;
 | 
			
		||||
* Remove dashes;
 | 
			
		||||
* Prepend the prefix `action`.
 | 
			
		||||
 | 
			
		||||
例如`index` 转成 `actionIndex`, `hello-world` 转成 `actionHelloWorld`。
 | 
			
		||||
For example, `index` becomes `actionIndex`, and `hello-world` becomes `actionHelloWorld`.
 | 
			
		||||
 | 
			
		||||
> 注意: 操作方法的名字*大小写敏感*,如果方法名称为`ActionIndex`不会认为是操作方法,
 | 
			
		||||
  所以请求`index`操作会返回一个异常,也要注意操作方法必须是公有的,私有或者受保护的方法不能定义成内联操作。
 | 
			
		||||
> Note: The names of the action methods are *case-sensitive*. If you have a method named `ActionIndex`,
 | 
			
		||||
  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 define an inline action.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
因为容易创建,内联操作是最常用的操作,但是如果你计划在不同地方重用相同的操作,
 | 
			
		||||
或者你想重新分配一个操作,需要考虑定义它为*独立操作*。
 | 
			
		||||
Inline actions are the most commonly defined actions because they take little effort to create. However,
 | 
			
		||||
if you plan to reuse the same action in different places, or if you want to redistribute an action,
 | 
			
		||||
you should consider defining it as a *standalone action*.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 独立操作 <a name="standalone-actions"></a>
 | 
			
		||||
### Standalone Actions <a name="standalone-actions"></a>
 | 
			
		||||
 | 
			
		||||
独立操作通过继承[[yii\base\Action]]或它的子类来定义。
 | 
			
		||||
例如Yii发布的[[yii\web\ViewAction]]和[[yii\web\ErrorAction]]都是独立操作。
 | 
			
		||||
Standalone actions are defined 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.
 | 
			
		||||
 | 
			
		||||
要使用独立操作,需要通过控制器中覆盖[[yii\base\Controller::actions()]]方法在*action map*中申明,如下例所示:
 | 
			
		||||
To use a standalone action, you should declare it in the *action map* by overriding the
 | 
			
		||||
[[yii\base\Controller::actions()]] method in your controller classes like the following:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
public function actions()
 | 
			
		||||
@ -372,15 +260,10 @@ public function actions()
 | 
			
		||||
 | 
			
		||||
如上所示, `actions()` 方法返回键为操作ID、值为对应操作类名或数组[configurations](concept-configurations.md) 的数组。
 | 
			
		||||
和内联操作不同,独立操作ID可包含任意字符,只要在`actions()` 方法中申明.
 | 
			
		||||
As you can see, the `actions()` method should return an array whose keys are action IDs and values the corresponding
 | 
			
		||||
action class names or [configurations](concept-configurations.md). Unlike inline actions, action IDs for standalone
 | 
			
		||||
actions can contain arbitrary characters, as long as they are declared in the `actions()` method.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
为创建一个独立操作类,需要继承[[yii\base\Action]] 或它的子类,并实现公有的名称为`run()`的方法,
 | 
			
		||||
`run()` 方法的角色和操作方法类似,例如:
 | 
			
		||||
To create a standalone action class, you should extend [[yii\base\Action]] or its child class, and implement
 | 
			
		||||
a public method named `run()`. The role of the `run()` method is similar to that of an action method. For example,
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
<?php
 | 
			
		||||
@ -399,31 +282,18 @@ class HelloWorldAction extends Action
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 操作结果 <a name="action-results"></a>
 | 
			
		||||
### Action Results <a name="action-results"></a>
 | 
			
		||||
 | 
			
		||||
操作方法或独立操作的`run()`方法的返回值非常中药,它表示对应操作结果。
 | 
			
		||||
The return value of an action method or the `run()` method of a standalone action is significant. It stands
 | 
			
		||||
for the result of the corresponding action.
 | 
			
		||||
 | 
			
		||||
返回值可为 [响应](runtime-responses.md) 对象,作为响应发送给终端用户。
 | 
			
		||||
The return value can be a [response](runtime-responses.md) object which will be sent to as the response
 | 
			
		||||
to end users.
 | 
			
		||||
 | 
			
		||||
* 对于[[yii\web\Application|Web applications]]网页应用,返回值可为任意数据, 它赋值给[[yii\web\Response::data]],
 | 
			
		||||
  最终转换为字符串来展示响应内容。
 | 
			
		||||
* 对于[[yii\console\Application|console applications]]控制台应用,返回值可为整数,
 | 
			
		||||
  表示命令行下执行的 [[yii\console\Response::exitStatus|exit status]] 退出状态。
 | 
			
		||||
* For [[yii\web\Application|Web applications]], the return value can also be some arbitrary data which will
 | 
			
		||||
  be assigned to [[yii\web\Response::data]] and be further converted into a string representing the response body.
 | 
			
		||||
* For [[yii\console\Application|console applications]], the return value can also be an integer representing
 | 
			
		||||
  the [[yii\console\Response::exitStatus|exit status]] of the command execution.
 | 
			
		||||
 | 
			
		||||
在上面的例子中,操作结果都为字符串,作为响应数据发送给终端用户,下例显示一个操作通过
 | 
			
		||||
返回响应对象(因为[[yii\web\Controller::redirect()|redirect()]]方法返回一个响应对象)可将用户浏览器跳转到新的URL。
 | 
			
		||||
In the examples shown above, the action results are all strings which will be treated as the response body
 | 
			
		||||
to be sent to end users. The following example shows how an action can redirect the user browser to a new URL
 | 
			
		||||
by returning a response object (because the [[yii\web\Controller::redirect()|redirect()]] method returns
 | 
			
		||||
a response object):
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
public function actionForward()
 | 
			
		||||
@ -435,19 +305,13 @@ public function actionForward()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 操作参数 <a name="action-parameters"></a>
 | 
			
		||||
### Action Parameters <a name="action-parameters"></a>
 | 
			
		||||
 | 
			
		||||
内联操作的操作方法和独立操作的 `run()` 方法可以带参数,称为*操作参数*。
 | 
			
		||||
参数值从请求中获取,对于[[yii\web\Application|Web applications]]网页应用,
 | 
			
		||||
每个操作参数的值从`$_GET`中获得,参数名作为键;
 | 
			
		||||
对于[[yii\console\Application|console applications]]控制台应用, 操作参数对应命令行参数。
 | 
			
		||||
The action methods for inline actions and the `run()` methods for standalone actions can take parameters,
 | 
			
		||||
called *action parameters*. Their values are obtained from requests. For [[yii\web\Application|Web applications]],
 | 
			
		||||
the value of each action parameter is retrieved from `$_GET` using the parameter name as the key;
 | 
			
		||||
for [[yii\console\Application|console applications]], they correspond to the command line arguments.
 | 
			
		||||
 | 
			
		||||
如下例,操作`view` (内联操作) 申明了两个参数 `$id` 和 `$version`。
 | 
			
		||||
In the following example, the `view` action (an inline action) has declared two parameters: `$id` and `$version`.
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
namespace app\controllers;
 | 
			
		||||
@ -464,7 +328,6 @@ class PostController extends Controller
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
操作参数会被不同的参数填入,如下所示:
 | 
			
		||||
The action parameters will be populated as follows for different requests:
 | 
			
		||||
 | 
			
		||||
* `http://hostname/index.php?r=post/view&id=123`: `$id` 会填入`'123'`,`$version` 仍为 null 空因为没有`version`请求参数;
 | 
			
		||||
* `http://hostname/index.php?r=post/view&id=123&version=2`: $id` 和 `$version` 分别填入 `'123'` 和 `'2'`;
 | 
			
		||||
@ -472,17 +335,8 @@ The action parameters will be populated as follows for different requests:
 | 
			
		||||
  因为请求没有提供参数给必须赋值参数`$id`;
 | 
			
		||||
* `http://hostname/index.php?r=post/view&id[]=123`: 会抛出[[yii\web\BadRequestHttpException]] 异常
 | 
			
		||||
  因为`$id` 参数收到数字值 `['123']`而不是字符串.
 | 
			
		||||
* `http://hostname/index.php?r=post/view&id=123`: the `$id` parameter will be filled with the value
 | 
			
		||||
  `'123'`,  while `$version` is still null because there is no `version` query parameter.
 | 
			
		||||
* `http://hostname/index.php?r=post/view&id=123&version=2`: the `$id` and `$version` parameters will
 | 
			
		||||
  be filled 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 provided in the request.
 | 
			
		||||
* `http://hostname/index.php?r=post/view&id[]=123`: a [[yii\web\BadRequestHttpException]] exception will be thrown
 | 
			
		||||
  because `$id` parameter is receiving an unexpected array value `['123']`.
 | 
			
		||||
 | 
			
		||||
如果想让操作参数接收数组值,需要指定$id为`array`,如下所示:
 | 
			
		||||
If you want an action parameter to accept array values, you should type-hint it with `array`, like the following:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
public function actionView(array $id, $version = null)
 | 
			
		||||
@ -496,22 +350,14 @@ public function actionView(array $id, $version = null)
 | 
			
		||||
参数 `$id` 会获取相同数组值,因为无类型的`'123'`会自动转成数组。
 | 
			
		||||
 | 
			
		||||
上述例子主要描述网页应用的操作参数,对于控制台应用,更多详情请参阅[控制台命令](tutorial-console.md)。
 | 
			
		||||
The above examples mainly show how action parameters work for Web applications. For console applications,
 | 
			
		||||
please refer to the [Console Commands](tutorial-console.md) section for more details.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 默认操作 <a name="default-action"></a>
 | 
			
		||||
### Default Action <a name="default-action"></a>
 | 
			
		||||
 | 
			
		||||
每个控制器都有一个由 [[yii\base\Controller::defaultAction]] 属性指定的默认操作,
 | 
			
		||||
当[路由](#ids-routes) 只包含控制器ID,会使用所请求的控制器的默认操作。
 | 
			
		||||
Each controller has a default action specified via the [[yii\base\Controller::defaultAction]] property.
 | 
			
		||||
When a [route](#ids-routes) contains the controller ID only, it implies that the default action of
 | 
			
		||||
the specified controller is requested.
 | 
			
		||||
 | 
			
		||||
默认操作默认为 `index`,如果想修改默认操作,只需简单地在控制器类中覆盖这个属性,如下所示:
 | 
			
		||||
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:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
namespace app\controllers;
 | 
			
		||||
@ -531,68 +377,36 @@ class SiteController extends Controller
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 控制器生命周期 <a name="controller-lifecycle"></a>
 | 
			
		||||
## Controller Lifecycle <a name="controller-lifecycle"></a>
 | 
			
		||||
 | 
			
		||||
处理一个请求时,[应用主体](structure-applications.md) 会根据请求[路由](#routes)创建一个控制器,will create a controller
 | 
			
		||||
控制器经过以下生命周期来完成请求:
 | 
			
		||||
When processing a request, an [application](structure-applications.md) will create a controller
 | 
			
		||||
based on the requested [route](#routes). The controller will then undergo the following lifecycle
 | 
			
		||||
to fulfill the request:
 | 
			
		||||
 | 
			
		||||
1. 在控制器创建和配置后,[[yii\base\Controller::init()]] 方法会被调用。
 | 
			
		||||
1. The [[yii\base\Controller::init()]] method is called after the controller is created and configured.
 | 
			
		||||
2. 控制器根据请求操作ID创建一个操作对象:
 | 
			
		||||
   * 如果操作ID没有指定,会使用[[yii\base\Controller::defaultAction|default action ID]]默认操作ID;
 | 
			
		||||
   * 如果在[[yii\base\Controller::actions()|action map]]找到操作ID,会创建一个独立操作;
 | 
			
		||||
   * 如果操作ID对应操作方法,会创建一个内联操作;
 | 
			
		||||
   * 否则会抛出[[yii\base\InvalidRouteException]]异常。
 | 
			
		||||
2. The controller creates an action object based on the requested action ID:
 | 
			
		||||
   * If the action ID is not specified, the [[yii\base\Controller::defaultAction|default action ID]] will be used.
 | 
			
		||||
   * If the action ID is found in the [[yii\base\Controller::actions()|action map]], 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. 控制器按顺序调用应用主体、模块(如果控制器属于模块)、控制器的 `beforeAction()` 方法;
 | 
			
		||||
   * 如果任意一个调用返回false,后面未调用的`beforeAction()`会跳过并且操作执行会被取消;
 | 
			
		||||
     action execution will be cancelled.
 | 
			
		||||
   * 默认情况下每个 `beforeAction()` 方法会触发一个 `beforeAction` 事件,在事件中你可以追加事件处理操作;
 | 
			
		||||
3. The controller sequentially calls the `beforeAction()` method of the application, 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()` will be skipped and the
 | 
			
		||||
     action execution will be cancelled.
 | 
			
		||||
   * By default, each `beforeAction()` method call will trigger a `beforeAction` event to which you can attach a handler.
 | 
			
		||||
4. 控制器执行操作:
 | 
			
		||||
   * 请求数据解析和填入到操作参数;
 | 
			
		||||
4. The controller runs the action:
 | 
			
		||||
   * The action parameters will be analyzed and populated from the request data;
 | 
			
		||||
5. 控制器按顺序调用控制器、模块(如果控制器属于模块)、应用主体的 `afterAction()` 方法;
 | 
			
		||||
   * 默认情况下每个 `afterAction()` 方法会触发一个 `afterAction` 事件,在事件中你可以追加事件处理操作;
 | 
			
		||||
5. The controller sequentially calls the `afterAction()` method of the controller, 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. 应用主体获取操作结果并赋值给[响应](runtime-responses.md).
 | 
			
		||||
6. The application will take the action result and assign it to the [response](runtime-responses.md).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 最佳实践 <a name="best-practices"></a>
 | 
			
		||||
## Best Practices <a name="best-practices"></a>
 | 
			
		||||
 | 
			
		||||
在设计良好的应用中,控制器很精练,包含的操作代码简短;
 | 
			
		||||
如果你的控制器很复杂,通常意味着需要重构,转移一些代码到其他类中。
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
归纳起来,控制器
 | 
			
		||||
In summary, controllers
 | 
			
		||||
 | 
			
		||||
* 可访问 [请求](runtime-requests.md) 数据;
 | 
			
		||||
* 可根据请求数据调用 [模型](structure-models.md) 的方法和其他服务组件;
 | 
			
		||||
* 可使用 [视图](structure-views.md) 构造响应;
 | 
			
		||||
* 不应处理应被[模型](structure-models.md)处理的请求数据;
 | 
			
		||||
* 应避免嵌入HTML或其他展示代码,这些代码最好在 [视图](structure-views.md)中处理.
 | 
			
		||||
* may access the [request](runtime-requests.md) data;
 | 
			
		||||
* may call methods of [models](structure-models.md) and other service components with request data;
 | 
			
		||||
* may use [views](structure-views.md) to compose responses;
 | 
			
		||||
* should NOT process the request data - this should be done in [models](structure-models.md);
 | 
			
		||||
* should avoid embedding HTML or other presentational code - this is better done in [views](structure-views.md).
 | 
			
		||||
 | 
			
		||||
@ -1,48 +1,29 @@
 | 
			
		||||
模型
 | 
			
		||||
Models
 | 
			
		||||
======
 | 
			
		||||
 | 
			
		||||
模型是 [MVC](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) 模式中的一部分,
 | 
			
		||||
是代表业务数据、规则和逻辑的对象。
 | 
			
		||||
Models are part of the [MVC](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) architecture.
 | 
			
		||||
They are objects representing business data, rules and logic.
 | 
			
		||||
 | 
			
		||||
可通过继承 [[yii\base\Model]] 或它的子类定义模型类,基类[[yii\base\Model]]支持许多实用的特性:
 | 
			
		||||
You can create model classes by extending [[yii\base\Model]] or its child classes. The base class
 | 
			
		||||
[[yii\base\Model]] supports many useful features:
 | 
			
		||||
 | 
			
		||||
* [属性](#attributes): 代表可像普通类属性或数组一样被访问的业务数据;
 | 
			
		||||
* [属性标签](#attribute-labels): 指定属性显示出来的标签;
 | 
			
		||||
* [块赋值](#massive-assignment): 支持一步给许多属性赋值;
 | 
			
		||||
* [验证规则](#validation-rules): 确保输入数据符合所申明的验证规则;
 | 
			
		||||
* [数据导出](#data-exporting): 允许模型数据导出为自定义格式的数组。
 | 
			
		||||
* [Attributes](#attributes): represent the business data and can be accessed like normal object properties
 | 
			
		||||
  or array elements;
 | 
			
		||||
* [Attribute labels](#attribute-labels): specify the display labels for attributes;
 | 
			
		||||
* [Massive assignment](#massive-assignment): supports populating multiple attributes in a single step;
 | 
			
		||||
* [Validation rules](#validation-rules): ensures input data based on the declared validation rules;
 | 
			
		||||
* [Data Exporting](#data-exporting): allows model data to be exported in terms of arrays with customizable formats.
 | 
			
		||||
 | 
			
		||||
`Model` 类也是更多高级模型如[Active Record 活动记录](db-active-record.md)的基类,
 | 
			
		||||
更多关于这些高级模型的详情请参考相关手册。
 | 
			
		||||
The `Model` class is also the base class for more advanced models, such as [Active Record](db-active-record.md).
 | 
			
		||||
Please refer to the relevant documentation for more details about these advanced models.
 | 
			
		||||
 | 
			
		||||
> 补充:模型并不强制一定要继承[[yii\base\Model]],但是由于很多组件支持[[yii\base\Model]],最好使用它做为模型基类。
 | 
			
		||||
> Info: You are not required to base your model classes on [[yii\base\Model]]. However, because there are many Yii
 | 
			
		||||
  components built to support [[yii\base\Model]], it is usually the preferable base class for a model.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 属性 <a name="attributes"></a>
 | 
			
		||||
## Attributes <a name="attributes"></a>
 | 
			
		||||
 | 
			
		||||
模型通过 *属性* 来代表业务数据,每个属性像是模型的公有可访问属性,
 | 
			
		||||
[[yii\base\Model::attributes()]] 指定模型所拥有的属性。
 | 
			
		||||
Models represent business data in terms of *attributes*. Each attribute is like a publicly accessible property
 | 
			
		||||
of a model. The method [[yii\base\Model::attributes()]] specifies what attributes a model class has.
 | 
			
		||||
 | 
			
		||||
可像访问一个对象属性一样访问模型的属性:
 | 
			
		||||
You can access an attribute like accessing a normal object property:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
$model = new \app\models\ContactForm;
 | 
			
		||||
@ -54,9 +35,6 @@ echo $model->name;
 | 
			
		||||
 | 
			
		||||
也可像访问数组单元项一样访问属性,这要感谢[[yii\base\Model]]支持 [ArrayAccess 数组访问](http://php.net/manual/en/class.arrayaccess.php) 
 | 
			
		||||
和 [ArrayIterator 数组迭代器](http://php.net/manual/en/class.arrayiterator.php):
 | 
			
		||||
You can also access attributes like accessing array elements, thanks to the support for
 | 
			
		||||
[ArrayAccess](http://php.net/manual/en/class.arrayaccess.php) and [ArrayIterator](http://php.net/manual/en/class.arrayiterator.php)
 | 
			
		||||
by [[yii\base\Model]]:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
$model = new \app\models\ContactForm;
 | 
			
		||||
@ -73,14 +51,10 @@ foreach ($model as $name => $value) {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 定义属性 <a name="defining-attributes"></a>
 | 
			
		||||
### Defining Attributes <a name="defining-attributes"></a>
 | 
			
		||||
 | 
			
		||||
默认情况下你的模型类直接从[[yii\base\Model]]继承,所有 *non-static public非静态公有* 成员变量都是属性。
 | 
			
		||||
例如,下述`ContactForm` 模型类有四个属性`name`, `email`, `subject` and `body`,
 | 
			
		||||
`ContactForm` 模型用来代表从HTML表单获取的输入数据。
 | 
			
		||||
By default, if your model class extends directly from [[yii\base\Model]], all its *non-static public* member
 | 
			
		||||
variables are attributes. 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.
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
namespace app\models;
 | 
			
		||||
@ -100,24 +74,14 @@ class ContactForm extends Model
 | 
			
		||||
另一种方式是可覆盖 [[yii\base\Model::attributes()]] 来定义属性,该方法返回模型的属性名。
 | 
			
		||||
例如 [[yii\db\ActiveRecord]] 返回对应数据表列名作为它的属性名,
 | 
			
		||||
注意可能需要覆盖魔术方法如`__get()`, `__set()`使属性像普通对象属性被访问。
 | 
			
		||||
You may override [[yii\base\Model::attributes()]] to define attributes in a different way. The method should
 | 
			
		||||
return the names of the attributes in a model. For example, [[yii\db\ActiveRecord]] does so by returning
 | 
			
		||||
the column 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.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 属性标签 <a name="attribute-labels"></a>
 | 
			
		||||
### Attribute Labels <a name="attribute-labels"></a>
 | 
			
		||||
 | 
			
		||||
当属性显示或获取输入时,经常要显示属性相关标签,例如假定一个属性名为`firstName`,
 | 
			
		||||
在某些地方如表单输入或错误信息处,你可能想显示对终端用户来说更友好的 `First Name` 标签。
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
可以调用 [[yii\base\Model::getAttributeLabel()]] 获取属性的标签,例如:
 | 
			
		||||
You can get the label of an attribute by calling [[yii\base\Model::getAttributeLabel()]]. For example,
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
$model = new \app\models\ContactForm;
 | 
			
		||||
@ -129,14 +93,8 @@ echo $model->getAttributeLabel('name');
 | 
			
		||||
默认情况下,属性标签通过[[yii\base\Model::generateAttributeLabel()]]方法自动从属性名生成. 
 | 
			
		||||
它会自动将驼峰式大小写变量名转换为多个首字母大写的单词,例如 `username` 转换为 `Username`,
 | 
			
		||||
`firstName` 转换为 `First 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 first letter in each word in upper case. For example, `username` becomes `Username`,
 | 
			
		||||
and `firstName` becomes `First Name`.
 | 
			
		||||
 | 
			
		||||
如果你不想用自动生成的标签,可以覆盖 [[yii\base\Model::attributeLabels()]] 方法明确指定属性标签,例如:
 | 
			
		||||
If you do not want to use automatically generated labels, you may override [[yii\base\Model::attributeLabels()]]
 | 
			
		||||
to explicitly declare attribute labels. For example,
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
namespace app\models;
 | 
			
		||||
@ -164,8 +122,6 @@ class ContactForm extends Model
 | 
			
		||||
 | 
			
		||||
应用支持多语言的情况下,可翻译属性标签,
 | 
			
		||||
可在 [[yii\base\Model::attributeLabels()|attributeLabels()]] 方法中定义,如下所示:
 | 
			
		||||
For applications supporting multiple languages, you may want to translate attribute labels. This can be done
 | 
			
		||||
in the [[yii\base\Model::attributeLabels()|attributeLabels()]] method as well, like the following:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
public function attributeLabels()
 | 
			
		||||
@ -181,23 +137,14 @@ public function attributeLabels()
 | 
			
		||||
 | 
			
		||||
甚至可以根据条件定义标签,例如通过使用模型的 [scenario场景](#scenarios),
 | 
			
		||||
可对相同的属性返回不同的标签。
 | 
			
		||||
You may even conditionally define attribute labels. For example, based on the [scenario](#scenarios) the model
 | 
			
		||||
is being used in, you may return different labels for the same attribute.
 | 
			
		||||
 | 
			
		||||
> 补充:属性标签是 [视图](structure-views.md)一部分,但是在模型中申明标签通常非常方便,并可行程非常简洁可重用代码。
 | 
			
		||||
> Info: Strictly speaking, attribute labels are part of [views](structure-views.md). But declaring labels
 | 
			
		||||
  in models is often very convenient and can result in very clean and reusable code.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 场景 <a name="scenarios"></a>
 | 
			
		||||
## Scenarios <a name="scenarios"></a>
 | 
			
		||||
 | 
			
		||||
模型可能在多个 *场景* 下使用,例如 `User` 模块可能会在收集用户登录输入,也可能会在用户注册时使用。
 | 
			
		||||
在不同的场景下,模型可能会使用不同的业务规则和逻辑,例如 `email` 属性在注册时强制要求有,但在登陆时不需要。
 | 
			
		||||
A model may be used in different *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 different scenarios, a model may use different
 | 
			
		||||
business rules and logic. For example, the `email` attribute may be required during user registration,
 | 
			
		||||
but not so during user login.
 | 
			
		||||
 | 
			
		||||
模型使用 [[yii\base\Model::scenario]] 属性保持使用场景的跟踪,
 | 
			
		||||
默认情况下,模型支持一个名为 `default` 的场景,如下展示两种设置场景的方法:
 | 
			
		||||
@ -213,9 +160,6 @@ $model = new User(['scenario' => 'login']);
 | 
			
		||||
 | 
			
		||||
默认情况下,模型支持的场景由模型中申明的 [验证规则](#validation-rules) 来决定,
 | 
			
		||||
但你可以通过覆盖[[yii\base\Model::scenarios()]]方法来自定义行为,如下所示:
 | 
			
		||||
By default, the scenarios supported by a model are determined by the [validation rules](#validation-rules) declared
 | 
			
		||||
in the model. However, you can customize this behavior by overriding the [[yii\base\Model::scenarios()]] method,
 | 
			
		||||
like the following:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
namespace app\models;
 | 
			
		||||
@ -236,23 +180,14 @@ class User extends ActiveRecord
 | 
			
		||||
 | 
			
		||||
> 补充:在上述和下述的例子中,模型类都是继承[[yii\db\ActiveRecord]],
 | 
			
		||||
  因为多场景的使用通常发生在[Active Record](db-active-record.md) 类中.
 | 
			
		||||
> 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](db-active-record.md) classes.
 | 
			
		||||
 | 
			
		||||
`scenarios()` 方法返回一个数组,数组的键为场景名,值为对应的 *active attributes活动属性*。
 | 
			
		||||
活动属性可被 [块赋值](#massive-assignment) 并遵循[验证规则](#validation-rules)
 | 
			
		||||
在上述例子中,`username` 和 `password` 在`login`场景中启用,在 `register` 场景中, 
 | 
			
		||||
除了 `username` and `password` 外 `email` 也被启用。
 | 
			
		||||
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](#massive-assignment) and is subject
 | 
			
		||||
to [validation](#validation-rules). In the above example, the `username` and `password` attributes are active
 | 
			
		||||
in the `login` scenario; while in the `register` scenario, `email` is also active besides `username` and `password`.
 | 
			
		||||
 | 
			
		||||
`scenarios()` 方法默认实现会返回所有[[yii\base\Model::rules()]]方法申明的验证规则中的场景,
 | 
			
		||||
当覆盖`scenarios()`时,如果你想在默认场景外使用新场景,可以编写类似如下代码:
 | 
			
		||||
The default implementation of `scenarios()` will return all scenarios found in the validation rule declaration
 | 
			
		||||
method [[yii\base\Model::rules()]]. When overriding `scenarios()`, if you want to introduce new scenarios
 | 
			
		||||
in addition to the default ones, you may write code like the following:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
namespace app\models;
 | 
			
		||||
@ -273,30 +208,17 @@ class User extends ActiveRecord
 | 
			
		||||
 | 
			
		||||
场景特性主要在[验证](#validation-rules) 和 [属性块赋值](#massive-assignment) 中使用。
 | 
			
		||||
你也可以用于其他目的,例如可基于不同的场景定义不同的 [属性标签](#attribute-labels)。
 | 
			
		||||
The scenario feature is primarily used by [validation](#validation-rules) and [massive attribute assignment](#massive-assignment).
 | 
			
		||||
You can, however, use it for other purposes. For example, you may declare [attribute labels](#attribute-labels)
 | 
			
		||||
differently based on the current scenario.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 验证规则 <a name="validation-rules"></a>
 | 
			
		||||
## Validation Rules <a name="validation-rules"></a>
 | 
			
		||||
 | 
			
		||||
当模型接收到终端用户输入的数据,数据应当满足某种规则(称为 *验证规则*, 也称为 *业务规则*)。
 | 
			
		||||
例如假定`ContactForm`模型,你可能想确保所有属性不为空且 `email` 属性包含一个有效的邮箱地址,
 | 
			
		||||
如果某个属性的值不满足对应的业务规则,相应的错误信息应显示,以帮助用户修正错误。
 | 
			
		||||
When the data for a model is received from end users, it should be validated to make sure it satisfies
 | 
			
		||||
certain rules (called *validation rules*, also known as *business rules*). For example, given a `ContactForm` model,
 | 
			
		||||
you may want to make sure all attributes are not empty and the `email` attribute contains 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 fix the errors.
 | 
			
		||||
 | 
			
		||||
可调用 [[yii\base\Model::validate()]] 来验证接收到的数据,
 | 
			
		||||
该方法使用[[yii\base\Model::rules()]]申明的验证规则来验证每个相关属性,
 | 
			
		||||
如果没有找到错误,会返回 true,否则它会将错误保存在 [[yii\base\Model::errors]] 属性中并返回false,例如:
 | 
			
		||||
You may call [[yii\base\Model::validate()]] to validate the received data. The method will use
 | 
			
		||||
the validation rules declared in [[yii\base\Model::rules()]] to validate every relevant attribute. If no error
 | 
			
		||||
is found, it will return true. Otherwise, it will keep the errors in the [[yii\base\Model::errors]] property
 | 
			
		||||
and return false. For example,
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
$model = new \app\models\ContactForm;
 | 
			
		||||
@ -315,9 +237,6 @@ if ($model->validate()) {
 | 
			
		||||
 | 
			
		||||
通过覆盖 [[yii\base\Model::rules()]] 方法指定模型属性应该满足的规则来申明模型相关验证规则。
 | 
			
		||||
下述例子显示`ContactForm`模型申明的验证规则:
 | 
			
		||||
To declare validation rules associated with a model, override the [[yii\base\Model::rules()]] method by returning
 | 
			
		||||
the rules that the model attributes should satisfy. The following example shows the validation rules declared
 | 
			
		||||
for the `ContactForm` model:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
public function rules()
 | 
			
		||||
@ -334,13 +253,8 @@ public function rules()
 | 
			
		||||
 | 
			
		||||
一条规则可用来验证一个或多个属性,一个属性可对应一条或多条规则。
 | 
			
		||||
更多关于如何申明验证规则的详情请参考 [验证输入](input-validation.md) 一节.
 | 
			
		||||
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](input-validation.md) section for more details on how to declare
 | 
			
		||||
validation rules.
 | 
			
		||||
 | 
			
		||||
有时你想一条规则只在某个 [场景](#scenarios) 下应用,为此你可以指定规则的 `on` 属性,如下所示:
 | 
			
		||||
Sometimes, you may want a rule to be applied only in certain [scenarios](#scenarios). To do so, you can
 | 
			
		||||
specify the `on` property of a rule, like the following:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
public function rules()
 | 
			
		||||
@ -357,12 +271,8 @@ public function rules()
 | 
			
		||||
 | 
			
		||||
如果没有指定 `on` 属性,规则会在所有场景下应用, 在当前[[yii\base\Model::scenario|scenario]]
 | 
			
		||||
下应用的规则称之为 *active rule活动规则*。
 | 
			
		||||
If you do not specify the `on` property, the rule would be applied in all scenarios. A rule is called
 | 
			
		||||
an *active rule* if it can be applied in the current [[yii\base\Model::scenario|scenario]].
 | 
			
		||||
 | 
			
		||||
一个属性只会属于`scenarios()`中定义的活动属性且在`rules()`申明对应一条或多条活动规则的情况下被验证。
 | 
			
		||||
An attribute will be validated if and only if it is an active attribute declared in `scenarios()` and
 | 
			
		||||
is associated with one or multiple active rules declared in `rules()`.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 块赋值 <a name="massive-assignment"></a>
 | 
			
		||||
@ -372,11 +282,6 @@ is associated with one or multiple active rules declared in `rules()`.
 | 
			
		||||
它直接将输入数据对应填充到 [[yii\base\Model::attributes]] 属性。
 | 
			
		||||
以下两段代码效果是相同的,都是将终端用户输入的表单数据赋值到 `ContactForm` 模型的属性,
 | 
			
		||||
明显地前一段块赋值的代码比后一段代码简洁且不易出错。
 | 
			
		||||
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:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
$model = new \app\models\ContactForm;
 | 
			
		||||
@ -394,16 +299,10 @@ $model->body = isset($data['body']) ? $data['body'] : null;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 安全属性 <a name="safe-attributes"></a>
 | 
			
		||||
### Safe Attributes <a name="safe-attributes"></a>
 | 
			
		||||
 | 
			
		||||
块赋值只应用在模型当前[[yii\base\Model::scenario|scenario]]场景[[yii\base\Model::scenarios()]]方法
 | 
			
		||||
列出的称之为 *安全属性* 的属性上,例如,如果`User`模型申明以下场景,
 | 
			
		||||
当当前场景为`login`时候,只有`username` and `password` 可被块赋值,其他属性不会被赋值。
 | 
			
		||||
Massive assignment only applies to the so-called *safe attributes* which are the attributes listed in
 | 
			
		||||
[[yii\base\Model::scenarios()]] for the current [[yii\base\Model::scenario|scenario]] of a model.
 | 
			
		||||
For example, if the `User` model has the following scenario declaration, then when the current scenario
 | 
			
		||||
is `login`, only the `username` and `password` can be massively assigned. Any other attributes will
 | 
			
		||||
be kept untouched.
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
public function scenarios()
 | 
			
		||||
@ -418,22 +317,12 @@ public function scenarios()
 | 
			
		||||
> 补充: 块赋值只应用在安全属性上,因为你想控制哪些属性会被终端用户输入数据所修改,
 | 
			
		||||
  例如,如果 `User` 模型有一个`permission`属性对应用户的权限,
 | 
			
		||||
  你可能只想让这个属性在后台界面被管理员修改。
 | 
			
		||||
> Info: The reason that massive assignment only applies to safe attributes is because you want to
 | 
			
		||||
  control which attributes can be modified by end user data. For example, if the `User` model
 | 
			
		||||
  has a `permission` attribute which determines the permission assigned to the user, you would
 | 
			
		||||
  like this attribute to be modifiable by administrators through a backend interface only.
 | 
			
		||||
 | 
			
		||||
由于默认[[yii\base\Model::scenarios()]]的实现会返回[[yii\base\Model::rules()]]所有属性和数据,
 | 
			
		||||
如果不覆盖这个方法,表示所有只要出现在活动验证规则中的属性都是安全的。
 | 
			
		||||
Because the default implementation of [[yii\base\Model::scenarios()]] will return all scenarios and attributes
 | 
			
		||||
found in [[yii\base\Model::rules()]], if you do not override this method, it means an attribute is safe as long
 | 
			
		||||
as it appears in one of the active validation rules.
 | 
			
		||||
 | 
			
		||||
为此,提供一个特别的别名为 `safe` 的验证器来申明哪些属性是安全的不需要被验证,
 | 
			
		||||
如下示例的规则申明 `title` 和 `description` 都为安全属性。
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
public function rules()
 | 
			
		||||
@ -446,15 +335,10 @@ public function rules()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 非安全属性 <a name="unsafe-attributes"></a>
 | 
			
		||||
### Unsafe Attributes <a name="unsafe-attributes"></a>
 | 
			
		||||
 | 
			
		||||
如上所述,[[yii\base\Model::scenarios()]] 方法提供两个用处:定义哪些属性应被验证,定义哪些属性安全。
 | 
			
		||||
在某些情况下,你可能想验证一个属性但不想让他是安全的,可在`scenarios()`方法中属性名加一个惊叹号 `!`。
 | 
			
		||||
例如像如下的`secret`属性。
 | 
			
		||||
As described above, the [[yii\base\Model::scenarios()]] method serves for two purposes: determining which attributes
 | 
			
		||||
should be validated, and determining which attributes are safe. In some rare cases, you may want to validate
 | 
			
		||||
an attribute but do not want to mark it safe. You can do so by prefixing an exclamation mark `!` to the attribute
 | 
			
		||||
name when declaring it in `scenarios()`, like the `secret` attribute in the following:
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
public function scenarios()
 | 
			
		||||
@ -467,9 +351,6 @@ public function scenarios()
 | 
			
		||||
 | 
			
		||||
当模型在 `login` 场景下,三个属性都会被验证,但只有 `username`和 `password` 属性会被块赋值,
 | 
			
		||||
要对`secret`属性赋值,必须像如下例子明确对它赋值。
 | 
			
		||||
When the model is in the `login` scenario, all three attributes will be validated. However, only the `username`
 | 
			
		||||
and `password` attributes can be massively assigned. To assign an input value to the `secret` attribute, you
 | 
			
		||||
have to do it explicitly as follows,
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
$model->secret = $secret;
 | 
			
		||||
@ -477,20 +358,12 @@ $model->secret = $secret;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 数据导出 <a name="data-exporting"></a>
 | 
			
		||||
## Data Exporting <a name="data-exporting"></a>
 | 
			
		||||
 | 
			
		||||
模型通常要导出成不同格式,例如,你可能想将模型的一个集合转成JSON或Excel格式,
 | 
			
		||||
导出过程可分解为两个步骤,第一步,模型转换成数组;第二步,数组转换成所需要的格式。
 | 
			
		||||
你只需要关注第一步,因为第二步可被通用的数据转换器如[[yii\web\JsonResponseFormatter]]来完成。
 | 
			
		||||
Models often need to be exported in different 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.
 | 
			
		||||
In the first step, models are converted into arrays; in the second step, the arrays are converted into
 | 
			
		||||
target formats. You may just focus on the first step, because the second step can be achieved by generic
 | 
			
		||||
data formatters, such as [[yii\web\JsonResponseFormatter]].
 | 
			
		||||
 | 
			
		||||
将模型转换为数组最简单的方式是使用 [[yii\base\Model::attributes]] 属性,例如:
 | 
			
		||||
The simplest way of converting a model into an array is to use the [[yii\base\Model::attributes]] property.
 | 
			
		||||
For example,
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
$post = \app\models\Post::findOne(100);
 | 
			
		||||
@ -498,39 +371,22 @@ $array = $post->attributes;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
[[yii\base\Model::attributes]] 属性会返回 *所有* [[yii\base\Model::attributes()]] 申明的属性的值。
 | 
			
		||||
By default, the [[yii\base\Model::attributes]] property will return the values of *all* attributes
 | 
			
		||||
declared in [[yii\base\Model::attributes()]].
 | 
			
		||||
 | 
			
		||||
更灵活和强大的将模型转换为数组的方式是使用 [[yii\base\Model::toArray()]] 方法,
 | 
			
		||||
它的行为默认和 [[yii\base\Model::attributes]] 相同,
 | 
			
		||||
但是它允许你选择哪些称之为*字段*的数据项放入到结果数组中并同时被格式化。
 | 
			
		||||
实际上,它是导出模型到 RESTful 网页服务开发的默认方法,详情请参阅[响应格式](rest-response-formatting.md).
 | 
			
		||||
A more flexible and powerful way of converting a model into an array is to use the [[yii\base\Model::toArray()]]
 | 
			
		||||
method. Its default behavior is the same as that of [[yii\base\Model::attributes]]. However, it allows you
 | 
			
		||||
to choose which data items, called *fields*, to be put in the resulting array and how they should be formatted.
 | 
			
		||||
In fact, it is the default way of exporting models in RESTful Web service development, as described in
 | 
			
		||||
the [Response Formatting](rest-response-formatting.md).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 字段 <a name="fields"></a>
 | 
			
		||||
### Fields <a name="fields"></a>
 | 
			
		||||
 | 
			
		||||
字段是模型通过调用[[yii\base\Model::toArray()]]生成的数组的单元名。
 | 
			
		||||
A field is simply a named element in the array that is obtained by calling the [[yii\base\Model::toArray()]] method
 | 
			
		||||
of a model.
 | 
			
		||||
 | 
			
		||||
默认情况下,字段名对应属性名,但是你可以通过覆盖
 | 
			
		||||
[[yii\base\Model::fields()|fields()]] 和/或 [[yii\base\Model::extraFields()|extraFields()]] 方法来改变这种行为,
 | 
			
		||||
两个方法都返回一个字段定义列表,`fields()` 方法定义的字段是默认字段,表示`toArray()`方法默认会返回这些字段。 
 | 
			
		||||
`extraFields()`方法定义额外可用字段,通过`toArray()`方法指定`$expand`参数来返回这些额外可用字段。
 | 
			
		||||
例如如下代码会返回`fields()`方法定义的所有字段和`extraFields()`方法定义的`prettyName` and `fullAddress`字段。
 | 
			
		||||
By default, field names are equivalent to attribute names. However, you can change this behavior by overriding
 | 
			
		||||
the [[yii\base\Model::fields()|fields()]] and/or [[yii\base\Model::extraFields()|extraFields()]] methods. Both methods
 | 
			
		||||
should return a list of field definitions. The fields defined by `fields()` are default fields, meaning that
 | 
			
		||||
`toArray()` will return these fields by default. The `extraFields()` method defines additionally available fields
 | 
			
		||||
which can also be returned by `toArray()` as long as you specify them via the `$expand` parameter. For example,
 | 
			
		||||
the following code will return all fields defined in `fields()` and the `prettyName` and `fullAddress` fields
 | 
			
		||||
if they are defined in `extraFields()`.
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
$array = $model->toArray([], ['prettyName', 'fullAddress']);
 | 
			
		||||
@ -539,11 +395,6 @@ $array = $model->toArray([], ['prettyName', 'fullAddress']);
 | 
			
		||||
可通过覆盖 `fields()` 来增加、删除、重命名和重定义字段,`fields()` 方法返回值应为数组,
 | 
			
		||||
数组的键为字段名,数组的值为对应的可为属性名或匿名函数返回的字段定义对应的值。
 | 
			
		||||
特使情况下,如果字段名和属性定义名相同,可以省略数组键,例如:
 | 
			
		||||
You can override `fields()` to add, remove, rename or redefine fields. The return value of `fields()`
 | 
			
		||||
should be an array. The array keys are the field names, and the array values are the corresponding
 | 
			
		||||
field definitions which can be either property/attribute names or anonymous functions returning the
 | 
			
		||||
corresponding field values. In the special case when a field name is the same as its defining attribute
 | 
			
		||||
name, you can omit the array key. For example,
 | 
			
		||||
 | 
			
		||||
```php
 | 
			
		||||
// 明确列出每个字段,特别用于你想确保数据表或模型属性改变不会导致你的字段改变(保证后端的API兼容).
 | 
			
		||||
@ -578,23 +429,14 @@ public function fields()
 | 
			
		||||
> 警告:由于模型的所有属性会被包含在导出数组,最好检查数据确保没包含敏感数据,
 | 
			
		||||
> 如果有敏感数据,应覆盖 `fields()` 方法过滤掉,在上述列子中,我们选择过滤掉
 | 
			
		||||
> `auth_key`, `password_hash` and `password_reset_token`。
 | 
			
		||||
> 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 filter them out. In the above example, we choose
 | 
			
		||||
> to filter out `auth_key`, `password_hash` and `password_reset_token`.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 最佳实践 <a name="best-practices"></a>
 | 
			
		||||
## Best Practices <a name="best-practices"></a>
 | 
			
		||||
 | 
			
		||||
模型是代表业务数据、规则和逻辑的中心地方,通常在很多地方重用,
 | 
			
		||||
在一个设计良好的应用中,模型通常比[控制器](structure-controllers.md)代码多。
 | 
			
		||||
Models are the central places to represent business data, rules and logic. They often need to be reused
 | 
			
		||||
in different places. In a well-designed application, models are usually much fatter than
 | 
			
		||||
[controllers](structure-controllers.md).
 | 
			
		||||
 | 
			
		||||
归纳起来,模型
 | 
			
		||||
In summary, models
 | 
			
		||||
 | 
			
		||||
* 可包含属性来展示业务数据;
 | 
			
		||||
* 可包含验证规则确保数据有效和完整;
 | 
			
		||||
@ -602,42 +444,18 @@ In summary, models
 | 
			
		||||
* 不应直接访问请求,session和其他环境数据,这些数据应该由[控制器](structure-controllers.md)传入到模型;
 | 
			
		||||
* 应避免嵌入HTML或其他展示代码,这些代码最好在 [视图](structure-views.md)中处理;
 | 
			
		||||
* 单个模型中避免太多的 [场景](#scenarios).
 | 
			
		||||
* 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](structure-controllers.md) into models;
 | 
			
		||||
* should avoid embedding HTML or other presentational code - this is better done in [views](structure-views.md);
 | 
			
		||||
* avoid having too many [scenarios](#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 affect several different places. To make the mode code more maintainable,
 | 
			
		||||
you may take the following strategy:
 | 
			
		||||
 | 
			
		||||
* 定义可被多个 [应用主体](structure-applications.md) 或 [模块](structure-modules.md) 共享的模型基类集合。
 | 
			
		||||
  这些模型类应包含通用的最小规则集合和逻辑。
 | 
			
		||||
* 在每个使用模型的 [应用主体](structure-applications.md) 或 [模块](structure-modules.md)中,
 | 
			
		||||
  通过继承对应的模型基类来定义具体的模型类,具体模型类包含应用主体或模块指定的规则和逻辑。
 | 
			
		||||
* Define a set of base model classes that are shared by different [applications](structure-applications.md) or
 | 
			
		||||
  [modules](structure-modules.md). These model classes should contain minimal sets of rules and logic that
 | 
			
		||||
  are common among all their usages.
 | 
			
		||||
* In each [application](structure-applications.md) or [module](structure-modules.md) that uses a model,
 | 
			
		||||
  define a concrete model class by extending from the corresponding base model class. The concrete model classes
 | 
			
		||||
  should contain rules and logic that are specific for that application or module.
 | 
			
		||||
 | 
			
		||||
例如,在[高级应用模板](tutorial-advanced-app.md),你可以定义一个模型基类`common\models\Post`,
 | 
			
		||||
然后在前台应用中,定义并使用一个继承`common\models\Post`的具体模型类`frontend\models\Post`,
 | 
			
		||||
在后台应用中可以类似地定义`backend\models\Post`。
 | 
			
		||||
通过这种策略,你清楚`frontend\models\Post`只对应前台应用,如果你修改它,就无需担忧修改会影响后台应用。
 | 
			
		||||
For example, in the [Advanced Application Template](tutorial-advanced-app.md), you may define a base model
 | 
			
		||||
class `common\models\Post`. Then for the front end application, you define and use a concrete model class
 | 
			
		||||
`frontend\models\Post` which extends from `common\models\Post`. And similarly for the back end application,
 | 
			
		||||
you define `backend\models\Post`. With this strategy, you will be sure that the code in `frontend\models\Post`
 | 
			
		||||
is only specific to the front end application, and if you make any change to it, you do not need to worry if
 | 
			
		||||
the change may break the back end application.
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user