From 101a30f762a6f24965ace5c0364c21175eaf728e Mon Sep 17 00:00:00 2001 From: funson86 Date: Thu, 9 Oct 2014 22:53:02 +0800 Subject: [PATCH 01/11] for check --- docs/guide-zh-CN/structure-controllers.md | 598 +++++++++++++++++++++++++ docs/guide-zh-CN/structure-models.md | 511 +++++++++++++++++++++ docs/guide-zh-CN/structure-views.md | 722 ++++++++++++++++++++++++++++++ 3 files changed, 1831 insertions(+) create mode 100644 docs/guide-zh-CN/structure-controllers.md create mode 100644 docs/guide-zh-CN/structure-models.md create mode 100644 docs/guide-zh-CN/structure-views.md diff --git a/docs/guide-zh-CN/structure-controllers.md b/docs/guide-zh-CN/structure-controllers.md new file mode 100644 index 0000000..88602bd --- /dev/null +++ b/docs/guide-zh-CN/structure-controllers.md @@ -0,0 +1,598 @@ +控制器 +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. + + +## 动作 +## Actions + +控制器由 *动作* 组成,它是执行终端用户请求的最基础的单元,一个控制器可有一个或多个动作。 +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; + +use Yii; +use app\models\Post; +use yii\web\Controller; +use yii\web\NotFoundHttpException; + +class PostController extends Controller +{ + public function actionView($id) + { + $model = Post::findOne($id); + if ($model === null) { + throw new NotFoundHttpException; + } + + return $this->render('view', [ + 'model' => $model, + ]); + } + + public function actionCreate() + { + $model = new Post; + + if ($model->load(Yii::$app->request->post()) && $model->save()) { + return $this->redirect(['view', 'id' => $model->id]); + } else { + return $this->render('create', [ + 'model' => $model, + ]); + } + } +} +``` + +在动作 `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. + + +## 路由 +## Routes + +终端用户通过所谓的*路由*寻找到动作,路由是包含以下部分的字符串: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 +``` + +如果用户的请求地址为 `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. + + +## 创建控制器 +## Creating Controllers + +在[[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; + +use yii\web\Controller; + +class SiteController extends Controller +{ +} +``` + + +### 控制器ID +### Controller IDs + +通常情况下,控制器用来处理请求有关的资源类型,因此控制器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`). + + +### 控制器类命名 +### Controller Class Naming + +控制器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). + + +### 控制器部署 +### Controller Map + +可通过配置 [[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 +[ + 'controllerMap' => [ + // 用类名申明 "account" 控制器 + 'account' => 'app\controllers\UserController', + + // 用配置数组申明 "article" 控制器 + 'article' => [ + 'class' => 'app\controllers\PostController', + 'enableCsrfValidation' => false, + ], + ], +] +``` + + +### 默认控制器 +### Default Controller + +每个应用有一个由[[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 +[ + 'defaultRoute' => 'main', +] +``` + + +## 创建动作 +## Creating Actions + +创建动作可简单地在控制器类中定义所谓的 *动作方法* 来完成,动作方法必须是以`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; + +use yii\web\Controller; + +class SiteController extends Controller +{ + public function actionIndex() + { + return $this->render('index'); + } + + public function actionHelloWorld() + { + return 'Hello World'; + } +} +``` + + +### 动作ID +### Action IDs + +动作通常是用来执行资源的特定操作,因此,动作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应仅包含英文小写字母、数字、下划线和中横杠,动作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). + + +### 内联动作 +### Inline Actions + +内联动作指的是根据我们刚描述的动作方法。 +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*. + + +### 独立动作 +### Standalone Actions + +独立动作通过继承[[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() +{ + return [ + // 用类来申明"error" 动作 + 'error' => 'yii\web\ErrorAction', + + // 用配置数组申明 "view" 动作 + 'view' => [ + 'class' => 'yii\web\ViewAction', + 'viewPrefix' => '', + ], + ]; +} +``` + +如上所示, `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 + +### Action Results + +动作方法或独立动作的`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() +{ + // 用户浏览器跳转到 http://example.com + return $this->redirect('http://example.com'); +} +``` + + +### 动作参数 +### Action Parameters + +内联动作的动作方法和独立动作的 `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; + +use yii\web\Controller; + +class PostController extends Controller +{ + public function actionView($id, $version = null) + { + // ... + } +} +``` + +动作参数会被不同的参数填入,如下所示: +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'`; +* `http://hostname/index.php?r=post/view`: 会抛出[[yii\web\BadRequestHttpException]] 异常 + 因为请求没有提供参数给必须赋值参数`$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) +{ + // ... +} +``` + +现在如果请求为 `http://hostname/index.php?r=post/view&id[]=123`, 参数 `$id` 会使用数组值`['123']`, +如果请求为 `http://hostname/index.php?r=post/view&id=123`, +参数 `$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. + + +### 默认动作 +### Default Action + +每个控制器都有一个由 [[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; + +use yii\web\Controller; + +class SiteController extends Controller +{ + public $defaultAction = 'home'; + + public function actionHome() + { + return $this->render('home'); + } +} +``` + + +## 控制器生命周期 +## Controller Lifecycle + +处理一个请求时,[应用主体](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). + + +## 最佳实践 +## 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. + +归纳起来,控制器 +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). diff --git a/docs/guide-zh-CN/structure-models.md b/docs/guide-zh-CN/structure-models.md new file mode 100644 index 0000000..7c8a192 --- /dev/null +++ b/docs/guide-zh-CN/structure-models.md @@ -0,0 +1,511 @@ +Models +====== + +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. + +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](#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. + +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. + +> 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. + + +## 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; + +// "name" is an attribute of ContactForm +$model->name = 'example'; +echo $model->name; +``` + +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; + +// accessing attributes like array elements +$model['name'] = 'example'; +echo $model['name']; + +// iterate attributes +foreach ($model as $name => $value) { + echo "$name: $value\n"; +} +``` + + +### Defining Attributes + +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; + +use yii\base\Model; + +class ContactForm extends Model +{ + public $name; + public $email; + public $subject; + public $body; +} +``` + + +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. + + +### 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, + +```php +$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 first letter in each word in upper case. For example, `username` becomes `Username`, +and `firstName` becomes `First Name`. + +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; + +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', + ]; + } +} +``` + +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() +{ + 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 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. + +> 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. + + +## Scenarios + +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. + +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: + +```php +// scenario is set as a property +$model = new User; +$model->scenario = 'login'; + +// scenario is set through configuration +$model = new User(['scenario' => 'login']); +``` + +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; + +use yii\db\ActiveRecord; + +class User extends ActiveRecord +{ + public function scenarios() + { + return [ + 'login' => ['username', 'password'], + '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](db-active-record.md) 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](#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`. + +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; + +use yii\db\ActiveRecord; + +class User extends ActiveRecord +{ + public function scenarios() + { + $scenarios = parent::scenarios(); + $scenarios['login'] = ['username', 'password']; + $scenarios['register'] = ['username', 'email', 'password']; + return $scenarios; + } +} +``` + +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. + + +## Validation Rules + +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. + +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; + +// 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 [[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() +{ + 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](input-validation.md) section for more details on how to declare +validation rules. + +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() +{ + return [ + // username, email and password are all required in "register" scenario + [['username', 'email', 'password'], 'required', 'on' => 'register'], + + // username and password are required in "login" scenario + [['username', 'password'], 'required', 'on' => 'login'], + ]; +} +``` + +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]]. + +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()`. + + +## 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: + +```php +$model = new \app\models\ContactForm; +$model->attributes = \Yii::$app->request->post('ContactForm'); +``` + +```php +$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 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() +{ + return [ + 'login' => ['username', 'password'], + '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 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. + +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. + +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() +{ + return [ + [['title', 'description'], 'safe'], + ]; +} +``` + + +### Unsafe Attributes + +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() +{ + return [ + '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; +``` + + +## Data Exporting + +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]]. + +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); +$array = $post->attributes; +``` + +By default, the [[yii\base\Model::attributes]] property will return the values of *all* attributes +declared in [[yii\base\Model::attributes()]]. + +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). + + +### Fields + +A field is simply a named element in the array that is obtained by calling the [[yii\base\Model::toArray()]] method +of a model. + +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']); +``` + +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 +// 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 filter them out. In the above example, we choose +> to filter out `auth_key`, `password_hash` and `password_reset_token`. + + +## Best Practices + +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 + +* 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: + +* 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. + +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. diff --git a/docs/guide-zh-CN/structure-views.md b/docs/guide-zh-CN/structure-views.md new file mode 100644 index 0000000..1b13333 --- /dev/null +++ b/docs/guide-zh-CN/structure-views.md @@ -0,0 +1,722 @@ +Views +===== + +Views are part of the [MVC](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) architecture. +They are code responsible for presenting data to end users. In a Web application, views are usually created +in terms of *view templates* which are PHP script files containing mainly HTML code and presentational PHP code. +They are managed by the [[yii\web\View|view]] application component which provides commonly used methods +to facilitate view composition and rendering. For simplicity, we often call view templates or view template files +as views. + + +## Creating Views + +As aforementioned, a view is simply a PHP script mixed with HTML and PHP code. The following is the view +that presents a login form. As you can see, PHP code is used to generate the dynamic content, such as the +page title and the form, while HTML code organizes them into a presentable HTML page. + +```php +title = 'Login'; +?> +

title) ?>

+ +

Please fill out the following fields to login:

+ + + field($model, 'username') ?> + field($model, 'password')->passwordInput() ?> + + +``` + +Within a view, you can access `$this` which refers to the [[yii\web\View|view component]] managing +and rendering this view template. + +Besides `$this`, there may be other predefined variables in a view, such as `$model` in the above +example. These variables represent the data that are *pushed* into the view by [controllers](structure-controllers.md) +or other objects whose trigger the [view rendering](#rendering-views). + +> Tip: The predefined variables are listed in a comment block at beginning of a view so that they can + be recognized by IDEs. It is also a good way of documenting your views. + + +### Security + +When creating views that generate HTML pages, it is important that you encode and/or filter the data coming +from end users before presenting them. Otherwise, your application may be subject to +[cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting) attacks. + +To display a plain text, encode it first by calling [[yii\helpers\Html::encode()]]. For example, the following code +encodes the user name before displaying it: + +```php + + +
+ name) ?> +
+``` + +To display HTML content, use [[yii\helpers\HtmlPurifier]] to filter the content first. For example, the following +code filters the post content before displaying it: + +```php + + +
+ text) ?> +
+``` + +> Tip: While HTMLPurifier does excellent job in making output safe, it is not fast. You should consider + [caching](caching-overview.md) the filtering result if your application requires high performance. + + +### Organizing Views + +Like [controllers](structure-controllers.md) and [models](structure-models.md), 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 the [controller ID](structure-controllers.md#routes). For example, if + the controller class is `PostController`, the directory would be `@app/views/post`; If it is `PostCommentController`, + the directory would be `@app/views/post-comment`. In case the controller belongs to a module, the directory + would be `views/ControllerID` under the [[yii\base\Module::basePath|module directory]]. +* For views rendered in a [widget](structure-widgets.md), they should be put under the `WidgetPath/views` directory by + default, where `WidgetPath` stands for the directory containing the widget class file. +* For views rendered by other objects, it is recommended that you follow the similar convention as that for widgets. + +You may customize these default view directories by overriding the [[yii\base\ViewContextInterface::getViewPath()]] +method of controllers or widgets. + + +## Rendering Views + +You can render views in [controllers](structure-controllers.md), [widgets](structure-widgets.md), or any +other places by calling view rendering methods. These methods share a similar signature shown as follows, + +``` +/** + * @param string $view view name or file path, depending on the actual rendering method + * @param array $params the data to be passed to the view + * @return string rendering result + */ +methodName($view, $params = []) +``` + + +### Rendering in Controllers + +Within [controllers](structure-controllers.md), you may call the following controller methods to render views: + +* [[yii\base\Controller::render()|render()]]: renders a [named view](#named-views) and applies a [layout](#layouts) + to the rendering result. +* [[yii\base\Controller::renderPartial()|renderPartial()]]: renders a [named view](#named-views) without any layout. +* [[yii\web\Controller::renderAjax()|renderAjax()]]: renders a [named view](#named-views) without any layout, + and injects all registered JS/CSS scripts and files. It is usually used in response to AJAX Web requests. +* [[yii\base\Controller::renderFile()|renderFile()]]: renders a view specified in terms of a view file path or + [alias](concept-aliases.md). + +For example, + +```php +namespace app\controllers; + +use Yii; +use app\models\Post; +use yii\web\Controller; +use yii\web\NotFoundHttpException; + +class PostController extends Controller +{ + public function actionView($id) + { + $model = Post::findOne($id); + if ($model === null) { + throw new NotFoundHttpException; + } + + // renders a view named "view" and applies a layout to it + return $this->render('view', [ + 'model' => $model, + ]); + } +} +``` + + +### Rendering in Widgets + +Within [widgets](structure-widgets.md), you may call the following widget methods to render views. + +* [[yii\base\Widget::render()|render()]]: renders a [named view](#named-views). +* [[yii\base\Widget::renderFile()|renderFile()]]: renders a view specified in terms of a view file path or + [alias](concept-aliases.md). + +For example, + +```php +namespace app\components; + +use yii\base\Widget; +use yii\helpers\Html; + +class ListWidget extends Widget +{ + public $items = []; + + public function run() + { + // renders a view named "list" + return $this->render('list', [ + 'items' => $this->items, + ]); + } +} +``` + + +### Rendering in Views + +You can render a view within another view by calling one of the following methods provided by the [[yii\base\View|view component]]: + +* [[yii\base\View::render()|render()]]: renders a [named view](#named-views). +* [[yii\web\View::renderAjax()|renderAjax()]]: renders a [named view](#named-views) and injects all registered + JS/CSS scripts and files. It is usually used in response to AJAX Web requests. +* [[yii\base\View::renderFile()|renderFile()]]: renders a view specified in terms of a view file path or + [alias](concept-aliases.md). + +For example, the following code in a view renders the `_overview.php` view file which is in the same directory +as the view being currently rendered. Remember that `$this` in a view refers to the [[yii\base\View|view]] component: + +```php +render('_overview') ?> +``` + + +### Rendering in Other Places + +In any place, you can get access to the [[yii\base\View|view]] application component by the expression +`Yii::$app->view` and then call its aforementioned methods to render a view. For example, + +```php +// 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 file path/alias. In most cases, +you would use the former because it is more concise and flexible. We call views specified using names as *named views*. + +A view name is resolved into the corresponding view file path according to the following rules: + +* A view name may omit the file extension name. In this case, `.php` will be used as the extension. For example, + the view name `about` corresponds to the file name `about.php`. +* If the view name starts with double slashes `//`, the corresponding view file path would be `@app/views/ViewName`. + That is, the view is looked for under the [[yii\base\Application::viewPath|application's view path]]. + For example, `//site/about` will be resolved into `@app/views/site/about.php`. +* If the view name starts with a single slash `/`, the view file path is formed by prefixing the view name + with the [[yii\base\Module::viewPath|view path]] of the currently active [module](structure-modules.md). + If there is no active module, `@app/views/ViewName` will be used. For example, `/user/create` will be resolved into + `@app/modules/user/views/user/create.php`, if the currently active module is `user`. If there is no active module, + the view file path would be `@app/views/user/create.php`. +* If the view is rendered with a [[yii\base\View::context|context]] and the context implements [[yii\base\ViewContextInterface]], + the view file path is formed by prefixing the [[yii\base\ViewContextInterface::getViewPath()|view path]] of the + context to the view name. This mainly applies to the views rendered within controllers and widgets. For example, + `site/about` will be resolved into `@app/views/site/about.php` if the context is the controller `SiteController`. +* If a view is rendered within another view, the directory containing the other view file will be prefixed to + the new view name to form the actual view file path. For example, `item` will be resolved into `@app/views/post/item` + if it is being rendered in the view `@app/views/post/index.php`. + +According to the above rules, calling `$this->render('view')` in a controller `app\controllers\PostController` will +actually render the view file `@app/views/post/view.php`, while calling `$this->render('_overview')` in that view +will render the view file `@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` view: +`$foo = 1` and `$bar = 2`. + +```php +echo $this->render('report', [ + 'foo' => 1, + 'bar' => 2, +]); +``` + +The pull approach actively retrieves data from the [[yii\base\View|view component]] or other 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: + +```php +The controller ID is: 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 different places. + + +### Sharing Data among Views + +The [[yii\base\View|view component]] provides the [[yii\base\View::params|params]] property that you can use +to share data among views. + +For example, in an `about` view, you can have the following code which specifies the current segment of the +breadcrumbs. + +```php +$this->params['breadcrumbs'][] = 'About Us'; +``` + +Then, in the [layout](#layouts) file, which is also a view, you can display the breadcrumbs using the data +passed along [[yii\base\View::params|params]]: + +```php + isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [], +]) ?> +``` + + +## 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. By default, layouts +are stored in the directory `@app/views/layouts`. For layouts used within a [module](structure-modules.md), +they should be stored in the `views/layouts` directory under the [[yii\base\Module::basePath|module directory]]. +You may customize the default layout directory by configuring the [[yii\base\Module::layoutPath]] property of +the application or modules. + +The following example shows how a layout looks like. Note that for illustrative purpose, we have greatly simplified +the code in the layout. In practice, you may want to add more content to it, such as head tags, main menu, etc. + +```php + +beginPage() ?> + + + + + + <?= Html::encode($this->title) ?> + head() ?> + + +beginBody() ?> +
My Company
+ + +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 layout when [[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()|beginPage()]]: This method should be called at the very beginning of the layout. + It triggers the [[yii\base\View::EVENT_BEGIN_PAGE|EVENT_BEGIN_PAGE]] event which indicates the beginning of a page. +- [[yii\base\View::endPage()|endPage()]]: This method should be called at the end of the layout. + It triggers the [[yii\base\View::EVENT_END_PAGE|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 finishes rendering. +- [[yii\web\View::beginBody()|beginBody()]]: This method should be called at the beginning of the `` section. + It triggers the [[yii\web\View::EVENT_BEGIN_BODY|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()|endBody()]]: This method should be called at the end of the `` section. + It triggers the [[yii\web\View::EVENT_END_BODY|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 predefined variables: `$this` and `$content`. The former refers to +the [[yii\base\View|view]] component, like in normal views, while the latter contains the rendering result of a content +view which is rendered by calling the [[yii\base\Controller::render()|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](#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](#sharing-data-among-views) subsection. + + +### Using Layouts + +As described in the [Rendering in Controllers](#rendering-in-controllers) subsection, when you render a view +by calling the [[yii\base\Controller::render()|render()]] method in a controller, a layout will be applied +to the rendering result. By default, the layout `@app/views/layouts/main.php` will be used. + +You may use a different layout by configuring either [[yii\base\Application::layout]] or [[yii\base\Controller::layout]]. +The former governs the layout used by all controllers, while the latter overrides the former for individual controllers. +For example, the following code makes the `post` controller to use `@app/views/layouts/post.php` as the layout +when rendering its views. Other controllers, assuming their `layout` property is untouched, will still use the default +`@app/views/layouts/main.php` as the layout. + +```php +namespace app\controllers; + +use yii\web\Controller; + +class PostController extends Controller +{ + public $layout = 'post'; + + // ... +} +``` + +For controllers belonging to a module, you may also configure the module's [[yii\base\Module::layout|layout]] property to +use a particular layout for these controllers. + +Because the `layout` property may be configured at different levels (controllers, modules, application), +behind the scene Yii takes two steps to determine what is the actual layout file being used for a particular controller. + +In the first step, it determines the layout value and the context module: + +- If the [[yii\base\Controller::layout]] property of the controller is not null, use it as the layout value and + the [[yii\base\Controller::module|module]] of the controller as the context module. +- If [[yii\base\Controller::layout|layout]] is null, search through all ancestor modules (including the application itself) of the controller and + find the first module whose [[yii\base\Module::layout|layout]] property is not null. Use that module and + its [[yii\base\Module::layout|layout]] value as the context module and 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 file according to the layout value and the context module +determined in the first step. The layout value can be: + +- a path alias (e.g. `@app/views/layouts/main`). +- an absolute path (e.g. `/main`): the layout value starts with a slash. The actual layout file will be + looked for under the application's [[yii\base\Application::layoutPath|layout path]] which defaults to + `@app/views/layouts`. +- a relative path (e.g. `main`): the actual layout file will be looked for under the context module's + [[yii\base\Module::layoutPath|layout path]] which defaults to the `views/layouts` directory under the + [[yii\base\Module::basePath|module directory]]. +- the boolean value `false`: no layout will be applied. + +If the layout value does not contain a file extension, it will use the default one `.php`. + + +### Nested Layouts + +Sometimes you may want to nest one layout in another. For example, in different sections of a Web site, you +want to use different 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()|beginContent()]] and +[[yii\base\View::endContent()|endContent()]] in the child layouts like the following: + +```php +beginContent('@app/views/layouts/base.php'); ?> + +...child layout content here... + +endContent(); ?> +``` + +As shown above, the child layout content should be enclosed within [[yii\base\View::beginContent()|beginContent()]] and +[[yii\base\View::endContent()|endContent()]]. The parameter passed to [[yii\base\View::beginContent()|beginContent()]] +specifies what is the parent layout. It can be either a layout file 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 define a block in a content view and display it in the layout. + +You call [[yii\base\View::beginBlock()|beginBlock()]] and [[yii\base\View::endBlock()|endBlock()]] to define a block. +The block can then be accessed via `$view->blocks[$blockID]`, where `$blockID` stands for a unique ID that you assign +to the block when defining it. + +The following example shows how you can use blocks to customize specific parts of a layout in a content view. + +First, in a content view, define one or multiple blocks: + +```php +... + +beginBlock('block1'); ?> + +...content of block1... + +endBlock(); ?> + +... + +beginBlock('block3'); ?> + +...content of block3... + +endBlock(); ?> +``` + +Then, in the layout view, render the blocks if they are available, or display some default content if a block is +not defined. + +```php +... +blocks['block1'])): ?> + blocks['block1'] ?> + + ... default content for block1 ... + + +... + +blocks['block2'])): ?> + blocks['block2'] ?> + + ... default content for block2 ... + + +... + +blocks['block3'])): ?> + blocks['block3'] ?> + + ... default content for block3 ... + +... +``` + + +## Using View Components + +[[yii\base\View|View components]] 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 configure this component in [application configurations](structure-applications.md#application-configurations) +like the following: + +```php +[ + // ... + '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](output-theming.md): allows you to develop and change the theme for your Web site. +* [fragment caching](caching-fragment.md): allows you to cache a fragment within a Web page. +* [client script handling](output-client-scripts.md): supports CSS and JavaScript registration and rendering. +* [asset bundle handling](structure-assets.md): supports registering and rendering of [asset bundles](structure-assets.md). +* [alternative template engines](tutorial-template-engines.md): allows you to use other template engines, such as + [Twig](http://twig.sensiolabs.org/), [Smarty](http://www.smarty.net/). + +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](#layouts). However, in practice +the title is often determined in content views rather than layouts. To solve this problem, [[yii\web\View]] provides +the [[yii\web\View::title|title]] 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: + +```php +title = 'My page title'; +?> +``` + +Then in the layout, make sure you have the following code in the `` section: + +```php +<?= Html::encode($this->title) ?> +``` + + +### Registering Meta Tags + +Web pages usually need to generate various meta tags needed by different 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: + +```php +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 finishes rendering. By then, the following HTML code will be inserted +at the place where you call [[yii\web\View::head()]] in the layout and generate the following HTML code: + +```php + +``` + +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. + +```html +$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](#adding-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 [[yii\web\View::registerLinkTag()]]. For example, in a content view, you can register a link tag like follows, + +```php +$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 + +```html + +``` + +Similar as [[yii\web\View::registerMetaTag()|registerMetaTags()]], you can specify a key when calling +[[yii\web\View::registerLinkTag()|registerLinkTag()]] to avoid generated repeated link tags. + + +## View Events + +[[yii\base\View|View components]] 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|EVENT_BEFORE_RENDER]]: triggered at the beginning of rendering a file + 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|EVENT_AFTER_RENDER]]: triggered by the call of [[yii\base\View::beginPage()]] in layouts. + Handlers of this event 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|EVENT_BEGIN_PAGE]]: triggered by the call of [[yii\base\View::beginPage()]] in layouts. +- [[yii\base\View::EVENT_END_PAGE|EVENT_END_PAGE]]: triggered by the call of [[yii\base\View::endPage()]] in layouts. +- [[yii\web\View::EVENT_BEGIN_BODY|EVENT_BEGIN_BODY]]: triggered by the call of [[yii\web\View::beginBody()]] in layouts. +- [[yii\web\View::EVENT_END_BODY|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: + +```php +\Yii::$app->view->on(View::EVENT_END_BODY, function () { + echo date('Y-m-d'); +}); +``` + + +## 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: + +```php +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](structure-controllers.md#standalone-actions) +called [[yii\web\ViewAction]] in a controller. For example, + +```php +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 `about` under the directory `@app/views/site/pages`, you will be able to +display this view by the following URL: + +``` +http://localhost/index.php?r=site/page&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 `@app/views/site/pages`. You may configure [[yii\web\ViewAction::viewPrefix]] +to change the directory for searching these views. + + +## 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](#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](structure-widgets.md) as building blocks of views. +* create and use helper classes to transform and format data in views. + From 08c19abafa3910610973f5fa90857ca62898220a Mon Sep 17 00:00:00 2001 From: funson86 Date: Sun, 12 Oct 2014 17:26:38 +0800 Subject: [PATCH 02/11] for check --- docs/guide-zh-CN/structure-controllers.md | 126 ++++++++++----------- docs/guide-zh-CN/structure-models.md | 180 ++++++++++++++++++++++++++---- 2 files changed, 219 insertions(+), 87 deletions(-) diff --git a/docs/guide-zh-CN/structure-controllers.md b/docs/guide-zh-CN/structure-controllers.md index 88602bd..a76537d 100644 --- a/docs/guide-zh-CN/structure-controllers.md +++ b/docs/guide-zh-CN/structure-controllers.md @@ -13,14 +13,14 @@ controllers will analyze incoming request data, pass them to [models](structure- into [views](structure-views.md), and finally generate outgoing responses. -## 动作 +## 操作 ## Actions -控制器由 *动作* 组成,它是执行终端用户请求的最基础的单元,一个控制器可有一个或多个动作。 +控制器由 *操作* 组成,它是执行终端用户请求的最基础的单元,一个控制器可有一个或多个操作。 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`: +如下示例显示包含两个操作`view` and `create` 的控制器`post`: The following example shows a `post` controller with two actions: `view` and `create`: ```php @@ -60,14 +60,14 @@ class PostController extends Controller } ``` -在动作 `view` (定义为 `actionView()` 方法)中, 代码首先根据请求模型ID加载 [模型](structure-models.md), +在操作 `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`视图。 +在操作 `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 @@ -77,12 +77,12 @@ the `create` view through which users can provide the needed input. ## 路由 ## Routes -终端用户通过所谓的*路由*寻找到动作,路由是包含以下部分的字符串: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: 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: 同控制器下唯一标识动作的字符串。 +* 操作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); @@ -102,7 +102,7 @@ or the following format if the controller belongs to a module: ModuleID/ControllerID/ActionID ``` -如果用户的请求地址为 `http://hostname/index.php?r=site/index`, 会执行`site` 控制器的`index` 动作。 +如果用户的请求地址为 `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 @@ -254,11 +254,11 @@ You may change the default controller with the following [application configurat ``` -## 创建动作 +## 创建操作 ## Creating Actions -创建动作可简单地在控制器类中定义所谓的 *动作方法* 来完成,动作方法必须是以`action`开头的公有方法。 -动作方法的返回值会作为响应数据发送给终端用户,如下代码定义了两个动作 `index` 和 `hello-world`: +创建操作可简单地在控制器类中定义所谓的 *操作方法* 来完成,操作方法必须是以`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`: @@ -283,23 +283,23 @@ class SiteController extends Controller ``` -### 动作ID +### 操作ID ### Action IDs -动作通常是用来执行资源的特定操作,因此,动作ID通常为动词,如`view`, `update`等等。 +操作通常是用来执行资源的特定操作,因此,操作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应仅包含英文小写字母、数字、下划线和中横杠,动作ID中的中横杠用来分隔单词。 -例如`view`, `update2`, `comment-post`是真实的动作ID,`view?`, `Update`不是动作ID. +操作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)。 +可通过两种方式创建操作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 @@ -307,13 +307,13 @@ if you have no intention to reuse these actions. Standalone actions, on the othe created to be used in different controllers or be redistributed as [extensions](structure-extensions.md). -### 内联动作 +### 内联操作 ### Inline Actions -内联动作指的是根据我们刚描述的动作方法。 +内联操作指的是根据我们刚描述的操作方法。 Inline actions refer to the actions that are defined in terms of action methods as we just described. -动作方法的名字是根据动作ID遵循如下规则衍生: +操作方法的名字是根据操作ID遵循如下规则衍生: The names of the action methods are derived from action IDs according to the following criteria: * 将每个单词的第一个字母转为大写; @@ -326,31 +326,31 @@ The names of the action methods are derived from action IDs according to the fol 例如`index` 转成 `actionIndex`, `hello-world` 转成 `actionHelloWorld`。 For example, `index` becomes `actionIndex`, and `hello-world` becomes `actionHelloWorld`. -> 注意: 动作方法的名字*大小写敏感*,如果方法名称为`ActionIndex`不会认为是动作方法, - 所以请求`index`动作会返回一个异常,也要注意动作方法必须是公有的,私有或者受保护的方法不能定义成内联动作。 +> 注意: 操作方法的名字*大小写敏感*,如果方法名称为`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*. -### 独立动作 +### 独立操作 ### Standalone Actions -独立动作通过继承[[yii\base\Action]]或它的子类来定义。 -例如Yii发布的[[yii\web\ViewAction]]和[[yii\web\ErrorAction]]都是独立动作。 +独立操作通过继承[[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*中申明,如下例所示: +要使用独立操作,需要通过控制器中覆盖[[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: @@ -358,10 +358,10 @@ To use a standalone action, you should declare it in the *action map* by overrid public function actions() { return [ - // 用类来申明"error" 动作 + // 用类来申明"error" 操作 'error' => 'yii\web\ErrorAction', - // 用配置数组申明 "view" 动作 + // 用配置数组申明 "view" 操作 'view' => [ 'class' => 'yii\web\ViewAction', 'viewPrefix' => '', @@ -370,15 +370,15 @@ public function actions() } ``` -如上所示, `actions()` 方法返回键为动作ID、值为对应动作类名或数组[configurations](concept-configurations.md) 的数组。 -和内联动作不同,独立动作ID可包含任意字符,只要在`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()` 方法的角色和动作方法类似,例如: +为创建一个独立操作类,需要继承[[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, @@ -398,10 +398,10 @@ class HelloWorldAction extends Action ``` -### 动作结果 +### 操作结果 ### Action Results -动作方法或独立动作的`run()`方法的返回值非常中药,它表示对应动作结果。 +操作方法或独立操作的`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. @@ -418,7 +418,7 @@ to end users. * 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 @@ -434,19 +434,19 @@ public function actionForward() ``` -### 动作参数 +### 操作参数 ### Action Parameters -内联动作的动作方法和独立动作的 `run()` 方法可以带参数,称为*动作参数*。 +内联操作的操作方法和独立操作的 `run()` 方法可以带参数,称为*操作参数*。 参数值从请求中获取,对于[[yii\web\Application|Web applications]]网页应用, -每个动作参数的值从`$_GET`中获得,参数名作为键; -对于[[yii\console\Application|console 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`。 +如下例,操作`view` (内联操作) 申明了两个参数 `$id` 和 `$version`。 In the following example, the `view` action (an inline action) has declared two parameters: `$id` and `$version`. ```php @@ -463,7 +463,7 @@ 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`请求参数; @@ -481,7 +481,7 @@ The action parameters will be populated as follows for different requests: * `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`,如下所示: +如果想让操作参数接收数组值,需要指定$id为`array`,如下所示: If you want an action parameter to accept array values, you should type-hint it with `array`, like the following: ```php @@ -495,21 +495,21 @@ public function actionView(array $id, $version = null) 如果请求为 `http://hostname/index.php?r=post/view&id=123`, 参数 `$id` 会获取相同数组值,因为无类型的`'123'`会自动转成数组。 -上述例子主要描述网页应用的动作参数,对于控制台应用,更多详情请参阅[控制台命令](tutorial-console.md)。 +上述例子主要描述网页应用的操作参数,对于控制台应用,更多详情请参阅[控制台命令](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. -### 默认动作 +### 默认操作 ### Default Action -每个控制器都有一个由 [[yii\base\Controller::defaultAction]] 属性指定的默认动作, -当[路由](#ids-routes) 只包含控制器ID,会使用所请求的控制器的默认动作。 +每个控制器都有一个由 [[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`,如果想修改默认动作,只需简单地在控制器类中覆盖这个属性,如下所示: +默认操作默认为 `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: @@ -541,10 +541,10 @@ 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对应动作方法,会创建一个内联动作; +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. @@ -553,31 +553,31 @@ to fulfill the request: * 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()`会跳过并且动作执行会被取消; + * 如果任意一个调用返回false,后面未调用的`beforeAction()`会跳过并且操作执行会被取消; action execution will be cancelled. - * 默认情况下每个 `beforeAction()` 方法会触发一个 `beforeAction` 事件,在事件中你可以追加事件处理动作; + * 默认情况下每个 `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. 控制器执行操作: + * 请求数据解析和填入到操作参数; 4. The controller runs the action: * The action parameters will be analyzed and populated from the request data; 5. 控制器按顺序调用控制器、模块(如果控制器属于模块)、应用主体的 `afterAction()` 方法; - * 默认情况下每个 `afterAction()` 方法会触发一个 `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. 应用主体获取操作结果并赋值给[响应](runtime-responses.md). 6. The application will take the action result and assign it to the [response](runtime-responses.md). ## 最佳实践 ## 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 diff --git a/docs/guide-zh-CN/structure-models.md b/docs/guide-zh-CN/structure-models.md index 7c8a192..c6fc66e 100644 --- a/docs/guide-zh-CN/structure-models.md +++ b/docs/guide-zh-CN/structure-models.md @@ -1,12 +1,21 @@ +模型 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; @@ -14,28 +23,37 @@ You can create model classes by extending [[yii\base\Model]] or its child classe * [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. +## 属性 ## Attributes +模型通过 *属性* 来代表业务数据,每个属性像是模型的公有可访问属性, +[[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; -// "name" is an attribute of ContactForm +// "name" 是ContactForm模型的属性 $model->name = 'example'; 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]]: @@ -43,19 +61,23 @@ by [[yii\base\Model]]: ```php $model = new \app\models\ContactForm; -// accessing attributes like array elements +// 像访问数组单元项一样访问属性 $model['name'] = 'example'; echo $model['name']; -// iterate attributes +// 迭代器遍历模型 foreach ($model as $name => $value) { echo "$name: $value\n"; } ``` +### 定义属性 ### Defining Attributes +默认情况下你的模型类直接从[[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. @@ -75,6 +97,9 @@ 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 @@ -82,26 +107,34 @@ override the magic methods such as `__get()`, `__set()` so that the attributes c normal object properties. +### 属性标签 ### Attribute Labels +当属性显示或获取输入时,经常要显示属性相关标签,例如假定一个属性名为`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; -// displays "Name" +// 显示为 "Name" 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, @@ -129,6 +162,8 @@ 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: @@ -144,33 +179,40 @@ 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. +## 场景 ## Scenarios +模型可能在多个 *场景* 下使用,例如 `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. -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: +模型使用 [[yii\base\Model::scenario]] 属性保持使用场景的跟踪, +默认情况下,模型支持一个名为 `default` 的场景,如下展示两种设置场景的方法: ```php -// scenario is set as a property +// 场景作为属性来设置 $model = new User; $model->scenario = 'login'; -// scenario is set through configuration +// 场景通过构造初始化配置来设置 $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: @@ -192,14 +234,22 @@ 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: @@ -221,19 +271,28 @@ 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. +## 验证规则 ## Validation Rules +当模型接收到终端用户输入的数据,数据应当满足某种规则(称为 *验证规则*, 也称为 *业务规则*)。 +例如假定`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 @@ -242,18 +301,20 @@ and return false. For example, ```php $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 + // 所有输入数据都有效 all inputs are valid } else { - // validation failed: $errors is an array containing error messages + // 验证失败:$errors 是一个包含错误信息的数组 $errors = $model->errors; } ``` +通过覆盖 [[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: @@ -262,19 +323,22 @@ for the `ContactForm` model: public function rules() { return [ - // the name, email, subject and body attributes are required + // name, email, subject 和 body 属性必须有值 [['name', 'email', 'subject', 'body'], 'required'], - // the email attribute should be a valid email address + // email 属性必须是一个有效的电子邮箱地址 ['email', 'email'], ]; } ``` +一条规则可用来验证一个或多个属性,一个属性可对应一条或多条规则。 +更多关于如何申明验证规则的详情请参考 [验证输入](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: @@ -282,24 +346,32 @@ specify the `on` property of a rule, like the following: public function rules() { return [ - // username, email and password are all required in "register" scenario + // 在"register" 场景下 username, email 和 password 必须有值 [['username', 'email', 'password'], 'required', 'on' => 'register'], - // username and password are required in "login" scenario + // 在 "login" 场景下 username 和 password 必须有值 [['username', 'password'], 'required', 'on' => 'login'], ]; } ``` +如果没有指定 `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()`. +## 块赋值 ## Massive Assignment +块赋值只用一行代码将用户所有输入填充到一个模型,非常方便, +它直接将输入数据对应填充到 [[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 @@ -321,8 +393,12 @@ $model->body = isset($data['body']) ? $data['body'] : null; ``` +### 安全属性 ### Safe Attributes +块赋值只应用在模型当前[[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 @@ -339,15 +415,22 @@ 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. @@ -362,8 +445,12 @@ public function rules() ``` +### 非安全属性 ### Unsafe Attributes +如上所述,[[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 @@ -378,6 +465,8 @@ 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, @@ -387,14 +476,19 @@ $model->secret = $secret; ``` +## 数据导出 ## Data Exporting +模型通常要导出成不同格式,例如,你可能想将模型的一个集合转成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, @@ -403,9 +497,14 @@ $post = \app\models\Post::findOne(100); $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. @@ -413,11 +512,18 @@ In fact, it is the default way of exporting models in RESTful Web service develo the [Response Formatting](rest-response-formatting.md). +### 字段 ### Fields +字段是模型通过调用[[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 @@ -430,6 +536,9 @@ if they are defined in `extraFields()`. $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 @@ -437,51 +546,62 @@ corresponding field values. In the special case when a field name is the same as name, you can omit the array key. For example, ```php -// 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). +// 明确列出每个字段,特别用于你想确保数据表或模型属性改变不会导致你的字段改变(保证后端的API兼容). 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" 'email' => 'email_address', - // field name is "name", its value is defined by a PHP callback + // 字段名为 "name", 值通过PHP代码返回 '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; } ``` +> 警告:由于模型的所有属性会被包含在导出数组,最好检查数据确保没包含敏感数据, +> 如果有敏感数据,应覆盖 `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`. +## 最佳实践 ## Best Practices +模型是代表业务数据、规则和逻辑的中心地方,通常在很多地方重用, +在一个设计良好的应用中,模型通常比[控制器](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 +* 可包含属性来展示业务数据; +* 可包含验证规则确保数据有效和完整; +* 可包含方法实现业务逻辑; +* 不应直接访问请求,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; @@ -490,12 +610,20 @@ In summary, 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. @@ -503,6 +631,10 @@ you may take the following strategy: 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, From 1e8fa78d2b1a3da54460b2870a19f4bf0fa51194 Mon Sep 17 00:00:00 2001 From: funson86 Date: Sun, 12 Oct 2014 17:39:26 +0800 Subject: [PATCH 03/11] new translation --- docs/guide-zh-CN/structure-controllers.md | 190 +----------------------------- docs/guide-zh-CN/structure-models.md | 182 ---------------------------- 2 files changed, 2 insertions(+), 370 deletions(-) diff --git a/docs/guide-zh-CN/structure-controllers.md b/docs/guide-zh-CN/structure-controllers.md index a76537d..703f246 100644 --- a/docs/guide-zh-CN/structure-controllers.md +++ b/docs/guide-zh-CN/structure-controllers.md @@ -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. ## 操作 -## Actions 控制器由 *操作* 组成,它是执行终端用户请求的最基础的单元,一个控制器可有一个或多个操作。 -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. ## 路由 -## Routes -终端用户通过所谓的*路由*寻找到操作,路由是包含以下部分的字符串: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. ## 创建控制器 -## Creating Controllers 在[[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 -### Controller IDs 通常情况下,控制器用来处理请求有关的资源类型,因此控制器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`). ### 控制器类命名 -### Controller Class Naming 控制器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). ### 控制器部署 -### Controller Map 可通过配置 [[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 ### 默认控制器 -### Default Controller 每个应用有一个由[[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 ## 创建操作 -## Creating Actions 创建操作可简单地在控制器类中定义所谓的 *操作方法* 来完成,操作方法必须是以`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 -### Action IDs -操作通常是用来执行资源的特定操作,因此,操作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). ### 内联操作 -### Inline Actions 内联操作指的是根据我们刚描述的操作方法。 -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*. ### 独立操作 -### Standalone Actions 独立操作通过继承[[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 -### Action Results 操作方法或独立操作的`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() ### 操作参数 -### Action Parameters 内联操作的操作方法和独立操作的 `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. ### 默认操作 -### Default Action 每个控制器都有一个由 [[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 ## 控制器生命周期 -## Controller Lifecycle 处理一个请求时,[应用主体](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). ## 最佳实践 -## 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. 归纳起来,控制器 -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). diff --git a/docs/guide-zh-CN/structure-models.md b/docs/guide-zh-CN/structure-models.md index c6fc66e..eaffbd4 100644 --- a/docs/guide-zh-CN/structure-models.md +++ b/docs/guide-zh-CN/structure-models.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. ## 属性 -## Attributes 模型通过 *属性* 来代表业务数据,每个属性像是模型的公有可访问属性, [[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) { ### 定义属性 -### Defining Attributes 默认情况下你的模型类直接从[[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. ### 属性标签 -### Attribute Labels 当属性显示或获取输入时,经常要显示属性相关标签,例如假定一个属性名为`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. ## 场景 -## Scenarios 模型可能在多个 *场景* 下使用,例如 `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. ## 验证规则 -## Validation Rules 当模型接收到终端用户输入的数据,数据应当满足某种规则(称为 *验证规则*, 也称为 *业务规则*)。 例如假定`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()`. ## 块赋值 @@ -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; ### 安全属性 -### Safe Attributes 块赋值只应用在模型当前[[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() ### 非安全属性 -### Unsafe Attributes 如上所述,[[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; ## 数据导出 -## Data Exporting 模型通常要导出成不同格式,例如,你可能想将模型的一个集合转成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). ### 字段 -### Fields 字段是模型通过调用[[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`. ## 最佳实践 -## Best Practices 模型是代表业务数据、规则和逻辑的中心地方,通常在很多地方重用, 在一个设计良好的应用中,模型通常比[控制器](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. From dfc15f5f4d9c21229359078da0007102e3ff7014 Mon Sep 17 00:00:00 2001 From: funson86 Date: Sun, 12 Oct 2014 22:04:57 +0800 Subject: [PATCH 04/11] for translation --- docs/guide-zh-CN/structure-modules.md | 251 ++++++++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 docs/guide-zh-CN/structure-modules.md diff --git a/docs/guide-zh-CN/structure-modules.md b/docs/guide-zh-CN/structure-modules.md new file mode 100644 index 0000000..e790ed9 --- /dev/null +++ b/docs/guide-zh-CN/structure-modules.md @@ -0,0 +1,251 @@ +Modules +======= + +Modules are self-contained software units that consist of [models](structure-models.md), [views](structure-views.md), +[controllers](structure-controllers.md), and other supporting components. End users can access the controllers +of a module when it is installed in [application](structure-applications.md). For these reasons, modules are +often viewed as mini-applications. Modules differ from [applications](structure-applications.md) in that +modules cannot be deployed alone and must reside within applications. + + +## Creating Modules + +A module is organized as a directory which is called the [[yii\base\Module::basePath|base path]] of the module. +Within the directory, there are sub-directories, such as `controllers`, `models`, `views`, which hold controllers, +models, views, and other code, just like in an application. The following example shows the content within a module: + +``` +forum/ + Module.php the module class file + controllers/ containing controller class files + DefaultController.php the default controller class file + models/ containing model class files + views/ containing controller view and layout files + layouts/ containing layout view files + default/ containing view files for DefaultController + index.php the index view file +``` + + +### Module Classes + +Each module should have a module class which extends from [[yii\base\Module]]. The class should be located +directly under the module's [[yii\base\Module::basePath|base path]] and should be [autoloadable](concept-autoloading.md). +When a module is being accessed, a single instance of the corresponding module class will be created. +Like [application instances](structure-applications.md), 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: + +```php +namespace app\modules\forum; + +class Module extends \yii\base\Module +{ + public function init() + { + parent::init(); + + $this->params['foo'] = 'bar'; + // ... other initialization code ... + } +} +``` + +If the `init()` method contains a lot of code initializing the module's properties, you may also save them in terms +of a [configuration](concept-configurations.md) and load it with the following code in `init()`: + +```php +public function init() +{ + parent::init(); + // initialize the module with the configuration loaded from config.php + \Yii::configure($this, require(__DIR__ . '/config.php')); +} +``` + +where the configuration file `config.php` may contain the following content, similar to that in an +[application configuration](structure-applications.md#application-configurations). + +```php + [ + // 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 `controllers` +sub-namespace of the namespace of the module class. This also means the controller class files should be +put in the `controllers` directory within the module's [[yii\base\Module::basePath|base path]]. +For example, to create a `post` controller in the `forum` module shown in the last subsection, you should +declare the controller class like the following: + +```php +namespace app\modules\forum\controllers; + +use yii\web\Controller; + +class PostController extends Controller +{ + // ... +} +``` + +You may customize the namespace of controller classes by configuring the [[yii\base\Module::controllerNamespace]] +property. In case when some of the controllers are out of this namespace, you may make them accessible +by configuring the [[yii\base\Module::controllerMap]] property, similar to [what you do in an application](structure-applications.md#controller-map). + + +### Views in Modules + +Views in a module should be put in the `views` directory within the module's [[yii\base\Module::basePath|base path]]. +For views rendered by a controller in the module, they should be put under the directory `views/ControllerID`, +where `ControllerID` refers to the [controller ID](structure-controllers.md#routes). For example, if +the controller class is `PostController`, the directory would be `views/post` within the module's +[[yii\base\Module::basePath|base path]]. + +A module can specify a [layout](structure-views.md#layouts) that is applied to the views rendered by the module's +controllers. The layout should be put in the `views/layouts` directory by default, and you should configure +the [[yii\base\Module::layout]] property to point to the layout name. If you do not configure the `layout` property, +the application's layout will be used instead. + + +## Using Modules + +To use a module in an application, simply configure the application by listing the module in +the [[yii\base\Application::modules|modules]] property of the application. The following code in the +[application configuration](structure-applications.md#application-configurations) uses the `forum` module: + +```php +[ + 'modules' => [ + 'forum' => [ + 'class' => 'app\modules\forum\Module', + // ... other configurations for the module ... + ], + ], +] +``` + +The [[yii\base\Application::modules|modules]] property takes an array of module configurations. Each array key +represents a *module ID* which uniquely identifies the module among all modules in the application, and the corresponding +array value is a [configuration](concept-configurations.md) for creating the module. + + +### Routes + +Like accessing controllers in an application, [routes](structure-controllers.md#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/post/index` would represent the `index` action of the `post` controller in the module. If the route +only contains the module ID, then the [[yii\base\Module::defaultRoute]] property, which defaults to `default`, +will determine which controller/action should be used. This means a route `forum` would represent the `default` +controller in the `forum` module. + + +### Accessing Modules + +Within a module, you may often need to get the instance of the [module class](#module-classes) so that you can +access the module ID, module parameters, module components, etc. You can do so by using the following statement: + +```php +$module = MyModuleClass::getInstance(); +``` + +where `MyModuleClass` refers to the name of the module class that you are interested in. The `getInstance()` method +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 +different 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 fixed 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 first, and then get the ID via + `$module->id`. + +You may also access the instance of a module using the following approaches: + +```php +// get the 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 first 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 getting hold of a module instance, you can access parameters or components registered with the module. For example, + +```php +$maxPostCount = $module->params['maxPostCount']; +``` + + +### Bootstrapping Modules + +Some modules may need to be run for every request. The [[yii\debug\Module|debug]] module is such an example. +To do so, list the IDs of such modules in the [[yii\base\Application::bootstrap|bootstrap]] property of the application. + +For example, the following application configuration makes sure the `debug` module is always load: + +```php +[ + 'bootstrap' => [ + 'debug', + ], + + 'modules' => [ + 'debug' => 'yii\debug\Module', + ], +] +``` + + +## 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* while the latter *child module*. Child modules must be declared +in the [[yii\base\Module::modules|modules]] property of their parent modules. For example, + +```php +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 all its ancestor module. +For example, the route `forum/admin/dashboard/index` represents the `index` action of the `dashboard` controller +in the `admin` module which is a child module of the `forum` module. + + +## 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 specific 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. From acfc3d3e43832d311f2766e9fbc988024ced32d1 Mon Sep 17 00:00:00 2001 From: Funson Lee Date: Fri, 17 Oct 2014 16:01:55 +0800 Subject: [PATCH 05/11] new translation --- docs/guide-zh-CN/start-forms.md | 8 ++++---- docs/guide-zh-CN/start-gii.md | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/guide-zh-CN/start-forms.md b/docs/guide-zh-CN/start-forms.md index f633e51..a459ec8 100644 --- a/docs/guide-zh-CN/start-forms.md +++ b/docs/guide-zh-CN/start-forms.md @@ -1,7 +1,7 @@ 使用表单 ================== -本章节将介绍如何创建一个从用户那搜集数据的表单页。该页将显示一个包含 name 输入框和 email 输入框的表单。当搜集完这两部分信息后,页面将会显示用户输入的信息。 +本章节介绍如何创建一个让用户提交数据的表单页。该页将显示一个包含 name 输入框和 email 输入框的表单。当提交这两部分信息后,页面将会显示用户所输入的信息。 为了实现这个目标,除了创建一个[操作](structure-controllers.md)和两个[视图](structure-views)外,还需要创建一个[模型](structure-models.md)。 @@ -39,16 +39,16 @@ class EntryForm extends Model } ``` -该类继承自 [[yii\base\Model]],Yii 提供的一个基类,通常用来表示数据。 +该类继承自Yii 提供的一个基类 [[yii\base\Model]],该基类通常用来表示数据。 > 补充:[[yii\base\Model]] 被用于普通模型类的父类并与数据表**无关**。[[yii\db\ActiveRecord]] 通常是普通模型类的父类但与数据表有关联(译者注:[[yii\db\ActiveRecord]] 类其实也是继承自 [[yii\base\Model]],增加了数据库处理)。 `EntryForm` 类包含 `name` 和 `email` 两个公共成员,用来储存用户输入的数据。它还包含一个名为 `rules()` 的方法,用来返回数据验证规则的集合。上面声明的验证规则表示: * `name` 和 `email` 值都是必须的 -* `mail` 的值必须满足 email 地址验证 +* `email` 的值必须满足email规则验证 -如果你有一个从用户那搜集数据的 `EntryForm` 对象,你可以调用它的 [[yii\base\Model::validate()|validate()]] 方法触发数据验证。如果有数据验证失败,将把 [[yii\base\Model::hasErrors|hasErrors]] 属性设为 ture,想要知道具体发生什么错误就调用 [[yii\base\Model::getErrors|getErrors]]。 +如果你有一个处理用户提交数据的 `EntryForm` 对象,你可以调用它的 [[yii\base\Model::validate()|validate()]] 方法触发数据验证。如果有数据验证失败,将把 [[yii\base\Model::hasErrors|hasErrors]] 属性设为 ture,想要知道具体发生什么错误就调用 [[yii\base\Model::getErrors|getErrors]]。 ```php [ 'class' => 'yii\gii\Module', - 'allowedIPs' => ['127.0.0.1', '::1', '192.168.0.*', '192.168.178.20'] // 根据你自己的需要调整 + 'allowedIPs' => ['127.0.0.1', '::1', '192.168.0.*', '192.168.178.20'] // adjust this to your needs ], ``` From 1b1a6dc85bc9ec78a9a094e403c78705809ba6e5 Mon Sep 17 00:00:00 2001 From: funson86 Date: Wed, 22 Oct 2014 19:55:55 +0800 Subject: [PATCH 06/11] english --- docs/guide-zh-CN/output-formatter.md | 190 +++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 docs/guide-zh-CN/output-formatter.md diff --git a/docs/guide-zh-CN/output-formatter.md b/docs/guide-zh-CN/output-formatter.md new file mode 100644 index 0000000..7ec3d59 --- /dev/null +++ b/docs/guide-zh-CN/output-formatter.md @@ -0,0 +1,190 @@ +Data Formatter +============== + +For formatting of outputs Yii provides a formatter class to make data more readable for users. +[[yii\i18n\Formatter]] is a helper class that is registered as an [application component](structure-application-components.md) named `formatter` by default. + +It provides a set of methods for data formatting purpose such as date/time values, numbers and other commonly used formats in a localized way. +The formatter can be used in two different ways. + +1. Using the formatting methods (all formatter methods prefixed with `as`) directly: + + ```php + echo Yii::$app->formatter->asDate('2014-01-01', 'long'); // output: January 1, 2014 + echo Yii::$app->formatter->asPercent(0.125, 2); // output: 12.50% + echo Yii::$app->formatter->asEmail('cebe@example.com'); // output: cebe@example.com + echo Yii::$app->formatter->asBoolean(true); // output: Yes + // it also handles display of null values: + echo Yii::$app->formatter->asDate(null); // output: (Not set) + ``` + +2. Using the [[yii\i18n\Formatter::format()|format()]] method and the format name. + This method is also used by widgets like [[yii\grid\GridView]] and [[yii\widgets\DetailView]] where you can specify + the data format of a column in the widget configuration. + + ```php + echo Yii::$app->formatter->format('2014-01-01', 'date'); // output: January 1, 2014 + // you can also use an array to specify parameters for the format method: + // `2` is the value for the $decimals parameter of the asPercent()-method. + echo Yii::$app->formatter->format(0.125, ['percent', 2]); // output: 12.50% + ``` + +All output of the formatter is localized when the [PHP intl extension](http://php.net/manual/en/book.intl.php) is installed. +You can configure the [[yii\i18n\Formatter::locale|locale]] property of the formatter for this. If not configured, the +application [[yii\base\Application::language|language]] is used as the locale. See the [section on internationalization](tutorial-i18n.md) for more details. +The Formatter will then choose the correct format for dates and numbers according to the locale including names of month and +week days translated to the current language. Date formats are also affected by the [[yii\i18n\Formatter::timeZone|timeZone]] +which will also be taken [[yii\base\Application::timeZone|from the application]] if not configured explicitly. + +For example the date format call will output different results for different locales: + +```php +Yii::$app->formatter->locale = 'en-US'; +echo Yii::$app->formatter->asDate('2014-01-01'); // output: January 1, 2014 +Yii::$app->formatter->locale = 'de-DE'; +echo Yii::$app->formatter->asDate('2014-01-01'); // output: 1. Januar 2014 +Yii::$app->formatter->locale = 'ru-RU'; +echo Yii::$app->formatter->asDate('2014-01-01'); // output: 1 января 2014 г. +``` + +> Note that formatting may differ between different versions of the ICU library compiled with PHP and also based on the fact whether the +> [PHP intl extension](http://php.net/manual/en/book.intl.php) is installed or not. So to ensure your website works with the same output +> in all environments it is recommended to install the PHP intl extension in all environments and verify that the version of the ICU library +> is the same. See also: [Setting up your PHP environment for internationalization](tutorial-i18n.md#setup-environment). + + +Configuring the formatter +------------------------- + +The default formats used by the formatter methods can be adjusted using the properties of the [[yii\i18n\Formatter|formatter class]]. +You can adjust these values application wide by configuring the `formatter` component in your [application config](concept-configurations.md#application-configurations). +An example configuration is shown in the following. +For more details about the available properties check out the [[yii\i18n\Formatter|API documentation of the Formatter class]] and the following subsections. + +```php +'components' => [ + 'formatter' => [ + 'dateFormat' => 'dd.MM.yyyy', + 'decimalSeparator' => ',', + 'thousandSeparator' => ' ', + 'currencyCode' => 'EUR', + ], +], +``` + +Formatting Date and Time values +------------------------------- + +The formatter class provides different methods for formatting date and time values. These are: + +- [[yii\i18n\Formatter::asDate()|date]] - the value is formatted as a date e.g. `January, 01 2014`. +- [[yii\i18n\Formatter::asTime()|time]] - the value is formatted as a time e.g. `14:23`. +- [[yii\i18n\Formatter::asDatetime()|datetime]] - the value is formatted as date and time e.g. `January, 01 2014 14:23`. +- [[yii\i18n\Formatter::asTimestamp()|timestamp]] - the value is formatted as a [unix timestamp](http://en.wikipedia.org/wiki/Unix_time) e.g. `1412609982`. +- [[yii\i18n\Formatter::asRelativeTime()|relativeTime]] - the value is formatted as the time interval between a date + and now in human readable form e.g. `1 hour ago`. + +The date and time format for the [[yii\i18n\Formatter::asDate()|date]], [[yii\i18n\Formatter::asTime()|time]], and +[[yii\i18n\Formatter::asDatetime()|datetime]] method can be specified globally by configuring the formatters +properties [[yii\i18n\Formatter::$dateFormat|$dateFormat]], [[yii\i18n\Formatter::$timeFormat|$timeFormat]], and +[[yii\i18n\Formatter::$datetimeFormat|$datetimeFormat]]. + +By default the formatter uses a shortcut format that is interpreted differently according to the currently active locale +so that dates and times are formatted in a way that is common for the users country and language. +There are four different shortcut formats available: + +- `short` in `en_GB` locale will print for example `06/10/2014` for date and `15:58` for time, while +- `medium` will print `6 Oct 2014` and `15:58:42`, +- `long` will print `6 October 2014` and `15:58:42 GMT`, +- and `full` will print `Monday, 6 October 2014` and `15:58:42 GMT`. + +Additionally you can specify custom formats using the syntax defined by the +[ICU Project](http://site.icu-project.org/) which is described in the ICU manual under the following URL: +. Alternatively you can use the syntax that can be recognized by the +PHP [date()](http://php.net/manual/de/function.date.php)-function using a string that is prefixed with `php:`. + +```php +// ICU format +echo Yii::$app->formatter->asDate('now', 'yyyy-MM-dd'); // 2014-10-06 +// PHP date()-format +echo Yii::$app->formatter->asDate('now', 'php:Y-m-d'); // 2014-10-06 +``` + +### Time zones + +When formatting date and time values, Yii will convert them to the [[yii\i18n\Formatter::timeZone|configured time zone]]. +Therefor the input value is assumed to be in UTC unless a time zone is explicitly given. For this reason +it is recommended to store all date and time values in UTC preferably as a UNIX timestamp, which is always UTC by definition. +If the input value is in a time zone different from UTC, the time zone has to be stated explicitly like in the following example: + +```php +// assuming Yii::$app->timeZone = 'Europe/Berlin'; +echo Yii::$app->formatter->asTime(1412599260); // 14:41:00 +echo Yii::$app->formatter->asTime('2014-10-06 12:41:00'); // 14:41:00 +echo Yii::$app->formatter->asTime('2014-10-06 14:41:00 CEST'); // 14:41:00 +``` + +> Note: As time zones are subject to rules made by the governments around the world and may change frequently, it is +> likely that you do not have the latest information in the time zone database installed on your system. +> You may refer to the [ICU manual](http://userguide.icu-project.org/datetime/timezone#TOC-Updating-the-Time-Zone-Data) +> for details on updating the time zone database. +> See also: [Setting up your PHP environment for internationalization](tutorial-i18n.md#setup-environment). + + +Formatting Numbers +------------------ + +For formatting numeric values the formatter class provides the following methods: + +- [[yii\i18n\Formatter::asInteger()|integer]] - the value is formatted as an integer e.g. `42`. +- [[yii\i18n\Formatter::asDecimal()|decimal]] - the value is formatted as a decimal number considering decimal and thousand separators e.g. `42.123`. +- [[yii\i18n\Formatter::asPercent()|percent]] - the value is formatted as a percent number e.g. `42%`. +- [[yii\i18n\Formatter::asScientific()|scientific]] - the value is formatted as a number in scientific format e.g. `4.2E4`. +- [[yii\i18n\Formatter::asCurrency()|currency]] - the value is formatted as a currency value e.g. `£420.00`. +- [[yii\i18n\Formatter::asSize()|size]] - the value that is a number of bytes is formatted as a human readable size e.g. `410 kibibytes`. +- [[yii\i18n\Formatter::asShortSize()|shortSize]] - is the short version of [[yii\i18n\Formatter::asSize()|size]], e.g. `410 KiB`. + +The format for number formatting can be adjusted using the [[yii\i18n\Formatter::decimalSeparator|decimalSeparator]] and +[[yii\i18n\Formatter::thousandSeparator|thousandSeparator]] which are set by default according to the locale. + +For more advanced configuration, [[yii\i18n\Formatter::numberFormatterOptions]] and [[yii\i18n\Formatter::numberFormatterTextOptions]] +can be used to configure the interally used [Numberformatter class](http://php.net/manual/en/class.numberformatter.php) + +For example to adjust the maximum and minimum value of fraction digits you can configure this property like the following: + +```php +[ + NumberFormatter::MIN_FRACTION_DIGITS => 0, + NumberFormatter::MAX_FRACTION_DIGITS => 2, +] +``` + +Other formatters +---------------- + +Additional to date, time and number formatting, Yii provides a set of other useful formatters for different purposes: + +- [[yii\i18n\Formatter::asRaw()|raw]] - the value is outputted as is, this is a pseudo-formatter that has no effect except that + `null` values will be formatted using [[nullDisplay]]. +- [[yii\i18n\Formatter::asText()|text]] - the value is HTML-encoded. + This is the default format used by the [GridView DataColumn](output-data-widgets.md#data-column). +- [[yii\i18n\Formatter::asNtext()|ntext]] - the value is formatted as an HTML-encoded plain text with newlines converted + into line breaks. +- [[yii\i18n\Formatter::asParagraphs()|paragraphs]] - the value is formatted as HTML-encoded text paragraphs wrapped + into `

` tags. +- [[yii\i18n\Formatter::asHtml()|html]] - the value is purified using [[HtmlPurifier]] to avoid XSS attacks. You can + pass additional options such as `['html', ['Attr.AllowedFrameTargets' => ['_blank']]]`. +- [[yii\i18n\Formatter::asEmail()|email]] - the value is formatted as a `mailto`-link. +- [[yii\i18n\Formatter::asImage()|image]] - the value is formatted as an image tag. +- [[yii\i18n\Formatter::asUrl()|url]] - the value is formatted as a hyperlink. +- [[yii\i18n\Formatter::asBoolean()|boolean]] - the value is formatted as a boolean. By default `true` is rendered + as `Yes` and `false` as `No`, translated to the application language. You adjust this by configuring + the [[yii\i18n\Formatter::booleanFormat]]-property. + +`null`-values +------------- + +For values that are `null` in PHP, the formatter class will print a placeholder instead of and empty string which +defaults to `(not set)` translated to the current application language. You can configure the +[[yii\i18n\Formatter::nullDisplay|nullDisplay]]-property to set a custom placeholder. +If you want no special handling for `null` values, you can set [[yii\i18n\Formatter::nullDisplay|nullDisplay]] to `null`. From 0ec8ed84e0d1cb014235412ecb64ba53be8c62f2 Mon Sep 17 00:00:00 2001 From: funson86 Date: Sun, 26 Oct 2014 22:31:49 +0800 Subject: [PATCH 07/11] for check --- docs/guide-zh-CN/output-formatter.md | 145 ++++++++++++++++++++++++----------- 1 file changed, 99 insertions(+), 46 deletions(-) diff --git a/docs/guide-zh-CN/output-formatter.md b/docs/guide-zh-CN/output-formatter.md index 7ec3d59..1866cac 100644 --- a/docs/guide-zh-CN/output-formatter.md +++ b/docs/guide-zh-CN/output-formatter.md @@ -1,34 +1,44 @@ -Data Formatter +数据格式器 ============== +Yii提供一个格式化类来格式化输出,以使输出数据对终端用户更友好易读, +[[yii\i18n\Formatter]] 是一个助手类,作为 [应用组件](structure-application-components.md) 使用,默认名为`formatter`。 For formatting of outputs Yii provides a formatter class to make data more readable for users. [[yii\i18n\Formatter]] is a helper class that is registered as an [application component](structure-application-components.md) named `formatter` by default. +它提供一些方法用来格式化数据,如日期/时间、数字或其他常用的本地化格式, +两种方式使用格式器: It provides a set of methods for data formatting purpose such as date/time values, numbers and other commonly used formats in a localized way. The formatter can be used in two different ways. +1. 直接使用格式化方法(所有的格式器方法以 `as`做前缀): 1. Using the formatting methods (all formatter methods prefixed with `as`) directly: ```php - echo Yii::$app->formatter->asDate('2014-01-01', 'long'); // output: January 1, 2014 - echo Yii::$app->formatter->asPercent(0.125, 2); // output: 12.50% - echo Yii::$app->formatter->asEmail('cebe@example.com'); // output: cebe@example.com - echo Yii::$app->formatter->asBoolean(true); // output: Yes - // it also handles display of null values: - echo Yii::$app->formatter->asDate(null); // output: (Not set) + echo Yii::$app->formatter->asDate('2014-01-01', 'long'); // 输出: January 1, 2014 + echo Yii::$app->formatter->asPercent(0.125, 2); // 输出: 12.50% + echo Yii::$app->formatter->asEmail('cebe@example.com'); // 输出: cebe@example.com + echo Yii::$app->formatter->asBoolean(true); // 输出: Yes + // 也可处理null值的输出显示: + echo Yii::$app->formatter->asDate(null); // 输出: (Not set) ``` -2. Using the [[yii\i18n\Formatter::format()|format()]] method and the format name. - This method is also used by widgets like [[yii\grid\GridView]] and [[yii\widgets\DetailView]] where you can specify - the data format of a column in the widget configuration. +2. 使用 [[yii\i18n\Formatter::format()|format()]] 方法和格式化名, + 该方法也被一些小部件如[[yii\grid\GridView]] 和 [[yii\widgets\DetailView]]使用,在小部件配置中可以指定列的数据格式。 ```php - echo Yii::$app->formatter->format('2014-01-01', 'date'); // output: January 1, 2014 - // you can also use an array to specify parameters for the format method: - // `2` is the value for the $decimals parameter of the asPercent()-method. - echo Yii::$app->formatter->format(0.125, ['percent', 2]); // output: 12.50% + echo Yii::$app->formatter->format('2014-01-01', 'date'); // 输出: January 1, 2014 + // 可使用数组来指定格式化方法的参数: + // `2` 是asPercent()方法的参数$decimals的值 + echo Yii::$app->formatter->format(0.125, ['percent', 2]); // 输出: 12.50% ``` +当[PHP intl extension](http://php.net/manual/en/book.intl.php)安装时,格式器的输出会本地化, +为此可配置格式器的 [[yii\i18n\Formatter::locale|locale]] 属性,如果没有配置, +应用配置 [[yii\base\Application::language|language]] 作为当前区域,更多详情参考 [国际化](tutorial-i18n.md)一节。 +然后格式器根据当前区域为日期和数字选择正确的格式,包括月份和星期也会转换到当前语言, +日期格式也会被 [[yii\i18n\Formatter::timeZone|timeZone]] 参数影响, +该参数如果没有明确配置会使用应用的 [[yii\base\Application::timeZone|from the application]] 参数。 All output of the formatter is localized when the [PHP intl extension](http://php.net/manual/en/book.intl.php) is installed. You can configure the [[yii\i18n\Formatter::locale|locale]] property of the formatter for this. If not configured, the application [[yii\base\Application::language|language]] is used as the locale. See the [section on internationalization](tutorial-i18n.md) for more details. @@ -36,26 +46,35 @@ The Formatter will then choose the correct format for dates and numbers accordin week days translated to the current language. Date formats are also affected by the [[yii\i18n\Formatter::timeZone|timeZone]] which will also be taken [[yii\base\Application::timeZone|from the application]] if not configured explicitly. +日期格式根据不同区域输出不同的结果,如下例所示: For example the date format call will output different results for different locales: ```php Yii::$app->formatter->locale = 'en-US'; -echo Yii::$app->formatter->asDate('2014-01-01'); // output: January 1, 2014 +echo Yii::$app->formatter->asDate('2014-01-01'); // 输出: January 1, 2014 Yii::$app->formatter->locale = 'de-DE'; -echo Yii::$app->formatter->asDate('2014-01-01'); // output: 1. Januar 2014 +echo Yii::$app->formatter->asDate('2014-01-01'); // 输出: 1. Januar 2014 Yii::$app->formatter->locale = 'ru-RU'; -echo Yii::$app->formatter->asDate('2014-01-01'); // output: 1 января 2014 г. +echo Yii::$app->formatter->asDate('2014-01-01'); // 输出: 1 января 2014 г. ``` +> 注意不管[PHP intl extension](http://php.net/manual/en/book.intl.php)有没有安装,PHP编译的ICU库不同,格式化结果可能不同, +> 所以为确保不同环境下得到相同的输出,推荐在每个环境下安装PHP intl扩展以及相同的ICU库, +> 可参考: [为国际化设置PHP环境](tutorial-i18n.md#setup-environment). > Note that formatting may differ between different versions of the ICU library compiled with PHP and also based on the fact whether the > [PHP intl extension](http://php.net/manual/en/book.intl.php) is installed or not. So to ensure your website works with the same output > in all environments it is recommended to install the PHP intl extension in all environments and verify that the version of the ICU library > is the same. See also: [Setting up your PHP environment for internationalization](tutorial-i18n.md#setup-environment). +配置格式器 Configuring the formatter ------------------------- +可配置[[yii\i18n\Formatter|formatter class]]的属性来调整格式器方法的默认格式, +可以在[应用主体配置](concept-configurations.md#application-configurations) 中配置 `formatter` 组件应用到整个项目, +配置样例如下所示, +更多关于可用属性的详情请参考 [[yii\i18n\Formatter|API documentation of the Formatter class]] 和接下来一小节。 The default formats used by the formatter methods can be adjusted using the properties of the [[yii\i18n\Formatter|formatter class]]. You can adjust these values application wide by configuring the `formatter` component in your [application config](concept-configurations.md#application-configurations). An example configuration is shown in the following. @@ -72,11 +91,18 @@ For more details about the available properties check out the [[yii\i18n\Formatt ], ``` +格式化日期和时间 Formatting Date and Time values ------------------------------- +格式器类为格式化日期和时间提供了多个方法: The formatter class provides different methods for formatting date and time values. These are: +- [[yii\i18n\Formatter::asDate()|date]] - 值被格式化成日期,如 `January, 01 2014`. +- [[yii\i18n\Formatter::asTime()|time]] - 值被格式化成时间,如 `14:23`. +- [[yii\i18n\Formatter::asDatetime()|datetime]] - 值被格式化成日期和时间,如 `January, 01 2014 14:23`. +- [[yii\i18n\Formatter::asTimestamp()|timestamp]] - 值被格式化成 [unix 时间戳](http://en.wikipedia.org/wiki/Unix_time) 如 `1412609982`. +- [[yii\i18n\Formatter::asRelativeTime()|relativeTime]] - 值被格式化成和当前时间比较的时间间隔并用人们易读的格式,如`1 hour ago`. - [[yii\i18n\Formatter::asDate()|date]] - the value is formatted as a date e.g. `January, 01 2014`. - [[yii\i18n\Formatter::asTime()|time]] - the value is formatted as a time e.g. `14:23`. - [[yii\i18n\Formatter::asDatetime()|datetime]] - the value is formatted as date and time e.g. `January, 01 2014 14:23`. @@ -84,46 +110,63 @@ The formatter class provides different methods for formatting date and time valu - [[yii\i18n\Formatter::asRelativeTime()|relativeTime]] - the value is formatted as the time interval between a date and now in human readable form e.g. `1 hour ago`. +可配置格式器的属性[[yii\i18n\Formatter::$dateFormat|$dateFormat]], [[yii\i18n\Formatter::$timeFormat|$timeFormat]] +和[[yii\i18n\Formatter::$datetimeFormat|$datetimeFormat]]来全局指定[[yii\i18n\Formatter::asDate()|date]], +[[yii\i18n\Formatter::asTime()|time]] 和 [[yii\i18n\Formatter::asDatetime()|datetime]] 方法的日期和时间格式。 The date and time format for the [[yii\i18n\Formatter::asDate()|date]], [[yii\i18n\Formatter::asTime()|time]], and [[yii\i18n\Formatter::asDatetime()|datetime]] method can be specified globally by configuring the formatters properties [[yii\i18n\Formatter::$dateFormat|$dateFormat]], [[yii\i18n\Formatter::$timeFormat|$timeFormat]], and [[yii\i18n\Formatter::$datetimeFormat|$datetimeFormat]]. +格式器默认会使用一个快捷格式,它根据当前启用的区域来解析, +这样日期和时间会格式化成用户国家和语言通用的格式, +有四种不同的快捷格式: By default the formatter uses a shortcut format that is interpreted differently according to the currently active locale so that dates and times are formatted in a way that is common for the users country and language. There are four different shortcut formats available: -- `short` in `en_GB` locale will print for example `06/10/2014` for date and `15:58` for time, while -- `medium` will print `6 Oct 2014` and `15:58:42`, -- `long` will print `6 October 2014` and `15:58:42 GMT`, -- and `full` will print `Monday, 6 October 2014` and `15:58:42 GMT`. +- `en_GB`区域的 `short` 会打印日期为 `06/10/2014`,时间为 `15:58` +- `medium` 会分别打印 `6 Oct 2014` 和 `15:58:42`, +- `long` 会分别打印 `6 October 2014` 和 `15:58:42 GMT`, +- `full` 会分别打印 `Monday, 6 October 2014` 和 `15:58:42 GMT`. +另外你可使用[ICU 项目](http://site.icu-project.org/) 定义的语法来自定义格式, +ICU项目在该URL:下的手册有介绍, +或者可使用PHP [date()](http://php.net/manual/de/function.date.php) 方法的语法字符串并加上前缀`php:`. Additionally you can specify custom formats using the syntax defined by the [ICU Project](http://site.icu-project.org/) which is described in the ICU manual under the following URL: . Alternatively you can use the syntax that can be recognized by the PHP [date()](http://php.net/manual/de/function.date.php)-function using a string that is prefixed with `php:`. ```php -// ICU format +// ICU 格式化 echo Yii::$app->formatter->asDate('now', 'yyyy-MM-dd'); // 2014-10-06 -// PHP date()-format +// PHP date()-格式化 echo Yii::$app->formatter->asDate('now', 'php:Y-m-d'); // 2014-10-06 ``` +### 时区 ### Time zones +当格式化日期和时间时,Yii会将它们转换为对应的 [[yii\i18n\Formatter::timeZone|configured time zone]] 时区, +输入的值在没有指定时区时候会被当作UTC时间,因此,推荐存储所有的日期和时间为UTC而不是UNIX时间戳,UNIX通常也是UTC。 +如果输入值所在的时区不同于UTC,时区应明确指定,如下所示: When formatting date and time values, Yii will convert them to the [[yii\i18n\Formatter::timeZone|configured time zone]]. Therefor the input value is assumed to be in UTC unless a time zone is explicitly given. For this reason it is recommended to store all date and time values in UTC preferably as a UNIX timestamp, which is always UTC by definition. If the input value is in a time zone different from UTC, the time zone has to be stated explicitly like in the following example: ```php -// assuming Yii::$app->timeZone = 'Europe/Berlin'; +// 假定 Yii::$app->timeZone = 'Europe/Berlin'; echo Yii::$app->formatter->asTime(1412599260); // 14:41:00 echo Yii::$app->formatter->asTime('2014-10-06 12:41:00'); // 14:41:00 echo Yii::$app->formatter->asTime('2014-10-06 14:41:00 CEST'); // 14:41:00 ``` +> 注意:时区从属于全世界各国政府定的规则,可能会频繁的变更,因此你的系统的时区数据库可能不是最新的信息, +> 可参考 [ICU manual](http://userguide.icu-project.org/datetime/timezone#TOC-Updating-the-Time-Zone-Data) +> 关于更新时区数据库的详情, +> 也可参考:[为国际化设置PHP环境](tutorial-i18n.md#setup-environment). > Note: As time zones are subject to rules made by the governments around the world and may change frequently, it is > likely that you do not have the latest information in the time zone database installed on your system. > You may refer to the [ICU manual](http://userguide.icu-project.org/datetime/timezone#TOC-Updating-the-Time-Zone-Data) @@ -131,11 +174,20 @@ echo Yii::$app->formatter->asTime('2014-10-06 14:41:00 CEST'); // 14:41:00 > See also: [Setting up your PHP environment for internationalization](tutorial-i18n.md#setup-environment). +格式化数字 Formatting Numbers ------------------ +格式器类提供如下方法格式化数值: For formatting numeric values the formatter class provides the following methods: +- [[yii\i18n\Formatter::asInteger()|integer]] - 值被格式化成整型,如 `42`. +- [[yii\i18n\Formatter::asDecimal()|decimal]] - 值被格式化成十进制数字并带有小数位和千分位,如 `42.123`. +- [[yii\i18n\Formatter::asPercent()|percent]] - 值被格式化成百分率,如 `42%`. +- [[yii\i18n\Formatter::asScientific()|scientific]] - 值被格式化成科学计数型,如`4.2E4`. +- [[yii\i18n\Formatter::asCurrency()|currency]] - 值被格式化成货币格式,如 `£420.00`. +- [[yii\i18n\Formatter::asSize()|size]] - 字节值被格式化成易读的值,如 `410 kibibytes`. +- [[yii\i18n\Formatter::asShortSize()|shortSize]] - [[yii\i18n\Formatter::asSize()|size]] 的缩写值,如 `410 KiB`. - [[yii\i18n\Formatter::asInteger()|integer]] - the value is formatted as an integer e.g. `42`. - [[yii\i18n\Formatter::asDecimal()|decimal]] - the value is formatted as a decimal number considering decimal and thousand separators e.g. `42.123`. - [[yii\i18n\Formatter::asPercent()|percent]] - the value is formatted as a percent number e.g. `42%`. @@ -144,12 +196,17 @@ For formatting numeric values the formatter class provides the following methods - [[yii\i18n\Formatter::asSize()|size]] - the value that is a number of bytes is formatted as a human readable size e.g. `410 kibibytes`. - [[yii\i18n\Formatter::asShortSize()|shortSize]] - is the short version of [[yii\i18n\Formatter::asSize()|size]], e.g. `410 KiB`. +可配置[[yii\i18n\Formatter::decimalSeparator|decimalSeparator]] 和 [[yii\i18n\Formatter::thousandSeparator|thousandSeparator]] +属性来调整数字格式化的格式,默认和当前区域相同。 The format for number formatting can be adjusted using the [[yii\i18n\Formatter::decimalSeparator|decimalSeparator]] and [[yii\i18n\Formatter::thousandSeparator|thousandSeparator]] which are set by default according to the locale. +更多高级配置, [[yii\i18n\Formatter::numberFormatterOptions]] 和 [[yii\i18n\Formatter::numberFormatterTextOptions]] +可用于配置内部使用 [Numberformatter class](http://php.net/manual/en/class.numberformatter.php) For more advanced configuration, [[yii\i18n\Formatter::numberFormatterOptions]] and [[yii\i18n\Formatter::numberFormatterTextOptions]] can be used to configure the interally used [Numberformatter class](http://php.net/manual/en/class.numberformatter.php) +为调整数字的小数部分的最大值和最小值,可配置如下属性: For example to adjust the maximum and minimum value of fraction digits you can configure this property like the following: ```php @@ -159,32 +216,28 @@ For example to adjust the maximum and minimum value of fraction digits you can c ] ``` +其他格式器 Other formatters ---------------- +除了日期、时间和数字格式化外,Yii提供其他用途提供一些实用的格式器: Additional to date, time and number formatting, Yii provides a set of other useful formatters for different purposes: -- [[yii\i18n\Formatter::asRaw()|raw]] - the value is outputted as is, this is a pseudo-formatter that has no effect except that - `null` values will be formatted using [[nullDisplay]]. -- [[yii\i18n\Formatter::asText()|text]] - the value is HTML-encoded. - This is the default format used by the [GridView DataColumn](output-data-widgets.md#data-column). -- [[yii\i18n\Formatter::asNtext()|ntext]] - the value is formatted as an HTML-encoded plain text with newlines converted - into line breaks. -- [[yii\i18n\Formatter::asParagraphs()|paragraphs]] - the value is formatted as HTML-encoded text paragraphs wrapped - into `

` tags. -- [[yii\i18n\Formatter::asHtml()|html]] - the value is purified using [[HtmlPurifier]] to avoid XSS attacks. You can - pass additional options such as `['html', ['Attr.AllowedFrameTargets' => ['_blank']]]`. -- [[yii\i18n\Formatter::asEmail()|email]] - the value is formatted as a `mailto`-link. -- [[yii\i18n\Formatter::asImage()|image]] - the value is formatted as an image tag. -- [[yii\i18n\Formatter::asUrl()|url]] - the value is formatted as a hyperlink. -- [[yii\i18n\Formatter::asBoolean()|boolean]] - the value is formatted as a boolean. By default `true` is rendered - as `Yes` and `false` as `No`, translated to the application language. You adjust this by configuring - the [[yii\i18n\Formatter::booleanFormat]]-property. - -`null`-values +- [[yii\i18n\Formatter::asRaw()|raw]] - 输出值和原始值一样,除了`null`值会用[[nullDisplay]]格式化,这是一个伪格式器; +- [[yii\i18n\Formatter::asText()|text]] - 值会经过HTML编码; + 这是[GridView DataColumn](output-data-widgets.md#data-column)默认使用的格式; +- [[yii\i18n\Formatter::asNtext()|ntext]] - 值会格式化成HTML编码的纯文本,新行会转换成换行符; +- [[yii\i18n\Formatter::asParagraphs()|paragraphs]] - 值会转换成HTML编码的文本段落,用`

`标签包裹; +- [[yii\i18n\Formatter::asHtml()|html]] - 值会被[[HtmlPurifier]]过滤来避免XSS跨域攻击,可传递附加选项如`['html', ['Attr.AllowedFrameTargets' => ['_blank']]]; +- [[yii\i18n\Formatter::asEmail()|email]] - 值会格式化成 `mailto`-链接; +- [[yii\i18n\Formatter::asImage()|image]] - 值会格式化成图片标签; +- [[yii\i18n\Formatter::asUrl()|url]] - 值会格式化成超链接; +- [[yii\i18n\Formatter::asBoolean()|boolean]] - 值会格式化成布尔型值,默认情况下 `true` 对应 `Yes`,`false` 对应 `No`, + 可根据应用语言配置进行翻译,可以配置[[yii\i18n\Formatter::booleanFormat]]-属性来调整; + +`null`-值 ------------- -For values that are `null` in PHP, the formatter class will print a placeholder instead of and empty string which -defaults to `(not set)` translated to the current application language. You can configure the -[[yii\i18n\Formatter::nullDisplay|nullDisplay]]-property to set a custom placeholder. -If you want no special handling for `null` values, you can set [[yii\i18n\Formatter::nullDisplay|nullDisplay]] to `null`. +对于PHP的`null`值,格式器类会打印一个占位符而不是空字符串,空字符串默认会显示对应当前语言`(not set)`, +可配置[[yii\i18n\Formatter::nullDisplay|nullDisplay]]-属性配置一个自定义占位符, +如果对处理`null`值没有特殊要求,可设置[[yii\i18n\Formatter::nullDisplay|nullDisplay]] 为 `null`. From e36ffded16c49b15c5f229ee1ea6b63fea60b435 Mon Sep 17 00:00:00 2001 From: funson86 Date: Sun, 26 Oct 2014 22:34:48 +0800 Subject: [PATCH 08/11] new translation --- docs/guide-zh-CN/output-formatter.md | 63 ------------------------------------ 1 file changed, 63 deletions(-) diff --git a/docs/guide-zh-CN/output-formatter.md b/docs/guide-zh-CN/output-formatter.md index 1866cac..2587ce5 100644 --- a/docs/guide-zh-CN/output-formatter.md +++ b/docs/guide-zh-CN/output-formatter.md @@ -3,16 +3,11 @@ Yii提供一个格式化类来格式化输出,以使输出数据对终端用户更友好易读, [[yii\i18n\Formatter]] 是一个助手类,作为 [应用组件](structure-application-components.md) 使用,默认名为`formatter`。 -For formatting of outputs Yii provides a formatter class to make data more readable for users. -[[yii\i18n\Formatter]] is a helper class that is registered as an [application component](structure-application-components.md) named `formatter` by default. 它提供一些方法用来格式化数据,如日期/时间、数字或其他常用的本地化格式, 两种方式使用格式器: -It provides a set of methods for data formatting purpose such as date/time values, numbers and other commonly used formats in a localized way. -The formatter can be used in two different ways. 1. 直接使用格式化方法(所有的格式器方法以 `as`做前缀): -1. Using the formatting methods (all formatter methods prefixed with `as`) directly: ```php echo Yii::$app->formatter->asDate('2014-01-01', 'long'); // 输出: January 1, 2014 @@ -39,12 +34,6 @@ The formatter can be used in two different ways. 然后格式器根据当前区域为日期和数字选择正确的格式,包括月份和星期也会转换到当前语言, 日期格式也会被 [[yii\i18n\Formatter::timeZone|timeZone]] 参数影响, 该参数如果没有明确配置会使用应用的 [[yii\base\Application::timeZone|from the application]] 参数。 -All output of the formatter is localized when the [PHP intl extension](http://php.net/manual/en/book.intl.php) is installed. -You can configure the [[yii\i18n\Formatter::locale|locale]] property of the formatter for this. If not configured, the -application [[yii\base\Application::language|language]] is used as the locale. See the [section on internationalization](tutorial-i18n.md) for more details. -The Formatter will then choose the correct format for dates and numbers according to the locale including names of month and -week days translated to the current language. Date formats are also affected by the [[yii\i18n\Formatter::timeZone|timeZone]] -which will also be taken [[yii\base\Application::timeZone|from the application]] if not configured explicitly. 日期格式根据不同区域输出不同的结果,如下例所示: For example the date format call will output different results for different locales: @@ -61,24 +50,15 @@ echo Yii::$app->formatter->asDate('2014-01-01'); // 输出: 1 января 2014 > 注意不管[PHP intl extension](http://php.net/manual/en/book.intl.php)有没有安装,PHP编译的ICU库不同,格式化结果可能不同, > 所以为确保不同环境下得到相同的输出,推荐在每个环境下安装PHP intl扩展以及相同的ICU库, > 可参考: [为国际化设置PHP环境](tutorial-i18n.md#setup-environment). -> Note that formatting may differ between different versions of the ICU library compiled with PHP and also based on the fact whether the -> [PHP intl extension](http://php.net/manual/en/book.intl.php) is installed or not. So to ensure your website works with the same output -> in all environments it is recommended to install the PHP intl extension in all environments and verify that the version of the ICU library -> is the same. See also: [Setting up your PHP environment for internationalization](tutorial-i18n.md#setup-environment). 配置格式器 -Configuring the formatter ------------------------- 可配置[[yii\i18n\Formatter|formatter class]]的属性来调整格式器方法的默认格式, 可以在[应用主体配置](concept-configurations.md#application-configurations) 中配置 `formatter` 组件应用到整个项目, 配置样例如下所示, 更多关于可用属性的详情请参考 [[yii\i18n\Formatter|API documentation of the Formatter class]] 和接下来一小节。 -The default formats used by the formatter methods can be adjusted using the properties of the [[yii\i18n\Formatter|formatter class]]. -You can adjust these values application wide by configuring the `formatter` component in your [application config](concept-configurations.md#application-configurations). -An example configuration is shown in the following. -For more details about the available properties check out the [[yii\i18n\Formatter|API documentation of the Formatter class]] and the following subsections. ```php 'components' => [ @@ -92,7 +72,6 @@ For more details about the available properties check out the [[yii\i18n\Formatt ``` 格式化日期和时间 -Formatting Date and Time values ------------------------------- 格式器类为格式化日期和时间提供了多个方法: @@ -103,27 +82,14 @@ The formatter class provides different methods for formatting date and time valu - [[yii\i18n\Formatter::asDatetime()|datetime]] - 值被格式化成日期和时间,如 `January, 01 2014 14:23`. - [[yii\i18n\Formatter::asTimestamp()|timestamp]] - 值被格式化成 [unix 时间戳](http://en.wikipedia.org/wiki/Unix_time) 如 `1412609982`. - [[yii\i18n\Formatter::asRelativeTime()|relativeTime]] - 值被格式化成和当前时间比较的时间间隔并用人们易读的格式,如`1 hour ago`. -- [[yii\i18n\Formatter::asDate()|date]] - the value is formatted as a date e.g. `January, 01 2014`. -- [[yii\i18n\Formatter::asTime()|time]] - the value is formatted as a time e.g. `14:23`. -- [[yii\i18n\Formatter::asDatetime()|datetime]] - the value is formatted as date and time e.g. `January, 01 2014 14:23`. -- [[yii\i18n\Formatter::asTimestamp()|timestamp]] - the value is formatted as a [unix timestamp](http://en.wikipedia.org/wiki/Unix_time) e.g. `1412609982`. -- [[yii\i18n\Formatter::asRelativeTime()|relativeTime]] - the value is formatted as the time interval between a date - and now in human readable form e.g. `1 hour ago`. 可配置格式器的属性[[yii\i18n\Formatter::$dateFormat|$dateFormat]], [[yii\i18n\Formatter::$timeFormat|$timeFormat]] 和[[yii\i18n\Formatter::$datetimeFormat|$datetimeFormat]]来全局指定[[yii\i18n\Formatter::asDate()|date]], [[yii\i18n\Formatter::asTime()|time]] 和 [[yii\i18n\Formatter::asDatetime()|datetime]] 方法的日期和时间格式。 -The date and time format for the [[yii\i18n\Formatter::asDate()|date]], [[yii\i18n\Formatter::asTime()|time]], and -[[yii\i18n\Formatter::asDatetime()|datetime]] method can be specified globally by configuring the formatters -properties [[yii\i18n\Formatter::$dateFormat|$dateFormat]], [[yii\i18n\Formatter::$timeFormat|$timeFormat]], and -[[yii\i18n\Formatter::$datetimeFormat|$datetimeFormat]]. 格式器默认会使用一个快捷格式,它根据当前启用的区域来解析, 这样日期和时间会格式化成用户国家和语言通用的格式, 有四种不同的快捷格式: -By default the formatter uses a shortcut format that is interpreted differently according to the currently active locale -so that dates and times are formatted in a way that is common for the users country and language. -There are four different shortcut formats available: - `en_GB`区域的 `short` 会打印日期为 `06/10/2014`,时间为 `15:58` - `medium` 会分别打印 `6 Oct 2014` 和 `15:58:42`, @@ -133,10 +99,6 @@ There are four different shortcut formats available: 另外你可使用[ICU 项目](http://site.icu-project.org/) 定义的语法来自定义格式, ICU项目在该URL:下的手册有介绍, 或者可使用PHP [date()](http://php.net/manual/de/function.date.php) 方法的语法字符串并加上前缀`php:`. -Additionally you can specify custom formats using the syntax defined by the -[ICU Project](http://site.icu-project.org/) which is described in the ICU manual under the following URL: -. Alternatively you can use the syntax that can be recognized by the -PHP [date()](http://php.net/manual/de/function.date.php)-function using a string that is prefixed with `php:`. ```php // ICU 格式化 @@ -146,15 +108,10 @@ echo Yii::$app->formatter->asDate('now', 'php:Y-m-d'); // 2014-10-06 ``` ### 时区 -### Time zones 当格式化日期和时间时,Yii会将它们转换为对应的 [[yii\i18n\Formatter::timeZone|configured time zone]] 时区, 输入的值在没有指定时区时候会被当作UTC时间,因此,推荐存储所有的日期和时间为UTC而不是UNIX时间戳,UNIX通常也是UTC。 如果输入值所在的时区不同于UTC,时区应明确指定,如下所示: -When formatting date and time values, Yii will convert them to the [[yii\i18n\Formatter::timeZone|configured time zone]]. -Therefor the input value is assumed to be in UTC unless a time zone is explicitly given. For this reason -it is recommended to store all date and time values in UTC preferably as a UNIX timestamp, which is always UTC by definition. -If the input value is in a time zone different from UTC, the time zone has to be stated explicitly like in the following example: ```php // 假定 Yii::$app->timeZone = 'Europe/Berlin'; @@ -167,15 +124,9 @@ echo Yii::$app->formatter->asTime('2014-10-06 14:41:00 CEST'); // 14:41:00 > 可参考 [ICU manual](http://userguide.icu-project.org/datetime/timezone#TOC-Updating-the-Time-Zone-Data) > 关于更新时区数据库的详情, > 也可参考:[为国际化设置PHP环境](tutorial-i18n.md#setup-environment). -> Note: As time zones are subject to rules made by the governments around the world and may change frequently, it is -> likely that you do not have the latest information in the time zone database installed on your system. -> You may refer to the [ICU manual](http://userguide.icu-project.org/datetime/timezone#TOC-Updating-the-Time-Zone-Data) -> for details on updating the time zone database. -> See also: [Setting up your PHP environment for internationalization](tutorial-i18n.md#setup-environment). 格式化数字 -Formatting Numbers ------------------ 格式器类提供如下方法格式化数值: @@ -187,27 +138,14 @@ For formatting numeric values the formatter class provides the following methods - [[yii\i18n\Formatter::asScientific()|scientific]] - 值被格式化成科学计数型,如`4.2E4`. - [[yii\i18n\Formatter::asCurrency()|currency]] - 值被格式化成货币格式,如 `£420.00`. - [[yii\i18n\Formatter::asSize()|size]] - 字节值被格式化成易读的值,如 `410 kibibytes`. -- [[yii\i18n\Formatter::asShortSize()|shortSize]] - [[yii\i18n\Formatter::asSize()|size]] 的缩写值,如 `410 KiB`. -- [[yii\i18n\Formatter::asInteger()|integer]] - the value is formatted as an integer e.g. `42`. -- [[yii\i18n\Formatter::asDecimal()|decimal]] - the value is formatted as a decimal number considering decimal and thousand separators e.g. `42.123`. -- [[yii\i18n\Formatter::asPercent()|percent]] - the value is formatted as a percent number e.g. `42%`. -- [[yii\i18n\Formatter::asScientific()|scientific]] - the value is formatted as a number in scientific format e.g. `4.2E4`. -- [[yii\i18n\Formatter::asCurrency()|currency]] - the value is formatted as a currency value e.g. `£420.00`. -- [[yii\i18n\Formatter::asSize()|size]] - the value that is a number of bytes is formatted as a human readable size e.g. `410 kibibytes`. -- [[yii\i18n\Formatter::asShortSize()|shortSize]] - is the short version of [[yii\i18n\Formatter::asSize()|size]], e.g. `410 KiB`. 可配置[[yii\i18n\Formatter::decimalSeparator|decimalSeparator]] 和 [[yii\i18n\Formatter::thousandSeparator|thousandSeparator]] 属性来调整数字格式化的格式,默认和当前区域相同。 -The format for number formatting can be adjusted using the [[yii\i18n\Formatter::decimalSeparator|decimalSeparator]] and -[[yii\i18n\Formatter::thousandSeparator|thousandSeparator]] which are set by default according to the locale. 更多高级配置, [[yii\i18n\Formatter::numberFormatterOptions]] 和 [[yii\i18n\Formatter::numberFormatterTextOptions]] 可用于配置内部使用 [Numberformatter class](http://php.net/manual/en/class.numberformatter.php) -For more advanced configuration, [[yii\i18n\Formatter::numberFormatterOptions]] and [[yii\i18n\Formatter::numberFormatterTextOptions]] -can be used to configure the interally used [Numberformatter class](http://php.net/manual/en/class.numberformatter.php) 为调整数字的小数部分的最大值和最小值,可配置如下属性: -For example to adjust the maximum and minimum value of fraction digits you can configure this property like the following: ```php [ @@ -217,7 +155,6 @@ For example to adjust the maximum and minimum value of fraction digits you can c ``` 其他格式器 -Other formatters ---------------- 除了日期、时间和数字格式化外,Yii提供其他用途提供一些实用的格式器: From cc4f932f59f6659426c3261e37160329b9017543 Mon Sep 17 00:00:00 2001 From: huoshi5151 Date: Wed, 29 Oct 2014 21:19:27 +0800 Subject: [PATCH 09/11] typo fix typo fix --- docs/guide-zh-CN/structure-applications.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide-zh-CN/structure-applications.md b/docs/guide-zh-CN/structure-applications.md index 452467d..4e9ef19 100644 --- a/docs/guide-zh-CN/structure-applications.md +++ b/docs/guide-zh-CN/structure-applications.md @@ -60,7 +60,7 @@ $config = require(__DIR__ . '/../config/web.php'); ### 重要属性 -本小节所描述的属性通常需要设置,因为不用的应用属性不同。 +本小节所描述的属性通常需要设置,因为不同的应用属性不同。 #### [[yii\base\Application::aliases|aliases]] From ce0116fc6b10eeb7f379bfa1e1f351f5eb702bfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=9C=E6=96=B9=E5=AD=A4=E6=80=9D=E5=AD=90=EF=BC=88Pari?= =?UTF-8?q?s=C2=B7QianSen=EF=BC=89?= Date: Wed, 29 Oct 2014 22:35:28 +0800 Subject: [PATCH 10/11] translating runtime-routing.md WIP --- docs/guide-zh-CN/runtime-routing.md | 92 +++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 docs/guide-zh-CN/runtime-routing.md diff --git a/docs/guide-zh-CN/runtime-routing.md b/docs/guide-zh-CN/runtime-routing.md new file mode 100644 index 0000000..eeb8db3 --- /dev/null +++ b/docs/guide-zh-CN/runtime-routing.md @@ -0,0 +1,92 @@ +路由 +======= + +当[入口脚本](structure-entry-scripts.md)在调用 [[yii\web\Application::run()|run()]] +方法时,它进行的第一个操作就是解析输入的请求,然后实例化对应的[控制器操作](structure-controllers.md)处理这个请求。该过程就被称为**引导路由(routing)**。(译者注:中文里既是动词也是名词) + + +## 解析路由 + +引导路由第一步,是解析输入请求为一个路由。如 [控制器(Controllers)](structure-controllers.md#routes) +所描述的那样,路由是一个用于定位控制器操作的地址。这个过程通过 `request` 应用组件的 [[yii\web\Request::resolve()|resolve()]] +方法实现,该方法会调用 [URL 管理器](runtime-url-handling.md) 进行实质上的请求解析工作。 + +The first step of routing is to parse the incoming request into a route which, as described in +the [Controllers](structure-controllers.md#routes) section, is used to address a controller action. +This is done by [[yii\web\Request::resolve()|resolve()]] method of the `request` application component. +The method invokes the [URL manager](runtime-url-handling.md) to do the actual request parsing work. + +默认情况下,输入请求会包含一个名为 `r` 的 `GET` 参数,它的值即被视为路由。但是如果启用 +[[yii\web\UrlManager::enablePrettyUrl|pretty URL feature]],确定请求路由时则会进行更多处理。具体的细节请参考 +[URL 的解析与生成](runtime-url-handling.md) 章节。 + +By default, if the incoming request contains a `GET` parameter named `r`, its value will be considered +as the route. However, if the [[yii\web\UrlManager::enablePrettyUrl|pretty URL feature]] is enabled, +more work will be done to determine the requested route. For more details, please refer to +the [URL Parsing and Generation](runtime-url-handling.md) section. + +若好死不死地路由最终无法被确定,那么 `request` 组件会抛出 [[yii\web\NotFoundHttpException]] 异常(译者注:大名鼎鼎的 404)。 + +In case a route cannot be determined, the `request` component will throw a [[yii\web\NotFoundHttpException]]. + + +### 默认路由 + +If an incoming request does not specify a route, which often happens to the request for homepages, +the route specified by [[yii\web\Application::defaultRoute]] will be used. The default value of this property +is `site/index`, which refers to the `index` action of the `site` controller. You may customize this property +in the application configuration like the following: + +```php +return [ + // ... + 'defaultRoute' => 'main/index', +]; +``` + + +### `catchAll` 路由(全拦截路由) + +Sometimes, you may want to put your Web application in maintenance mode temporarily and display the same +informational page for all requests. There are many ways to accomplish this goal. But one of the simplest +ways is to configure the [[yii\web\Application::catchAll]] property like the following in the application configuration: + +```php +return [ + // ... + 'catchAll' => ['site/offline'], +]; +``` + +The `catchAll` property should take an array whose first element specifies a route, and +the rest of the elements (name-value pairs) specify the parameters to be bound to the action. + +When the `catchAll` property is set, it will replace any route resolved from the incoming requests. +With the above configuration, the same `site/offline` action will be used to handle all incoming requests. + + +## 创建一个操作 + +Once the requested route is determined, the next step is to create the action object corresponding to the route. + +The route is broken down into multiple parts by the slashes in it. For example, `site/index` will be +broken into `site` and `index`. Each part is an ID which may refer to a module, a controller or an action. + +Starting from the first part in the route, the application conducts the following steps to create modules (if any), +the controller and the action: + +1. Set the application as the current module. +2. Check if the [[yii\base\Module::controllerMap|controller map]] of the current module contains the current ID. + If so, a controller object will be created according to the controller configuration found in the map, + and do Step 5 with the rest parts of the route. +3. Check if the ID refers to a module listed in the [[yii\base\Module::modules|modules]] property of + the current module. If so, a module is created according to the configuration found in the module list, + and do Step 2 with the next part in the route under the context of the newly created module. +4. Treat the ID as a controller ID and create a controller object. Do the next step with the rest part of + the route. +5. The controller looks for the current ID in its [[yii\base\Controller::actions()|action map]]. If found, + it creates an action according to the configuration found in the map. Otherwise, the controller will + attempt to create an inline action which is defined by an action method corresponding to the current ID. + +Among the above steps, if any error occurs, a [[yii\web\NotFoundHttpException]] will be thrown, indicating +failure of the routing. From e26def3923b3b9cf9b1a2a217b7d5378d4dc9ea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=9C=E6=96=B9=E5=AD=A4=E6=80=9D=E5=AD=90=EF=BC=88Pari?= =?UTF-8?q?s=C2=B7QianSen=EF=BC=89?= Date: Wed, 29 Oct 2014 23:05:46 +0800 Subject: [PATCH 11/11] list most of Chinese translators --- docs/internals/translation-teams.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/internals/translation-teams.md b/docs/internals/translation-teams.md index 1dd56c2..b0d780f 100644 --- a/docs/internals/translation-teams.md +++ b/docs/internals/translation-teams.md @@ -10,9 +10,15 @@ Brazilian Portuguese China ----- -- **Paris Qian Sen 东方孤思子,[@qiansen1386](https://github.com/qiansen1386),qiansen1386ATgmail.com** +- **Paris Qian Sen 东方孤思子,[@qiansen1386](https://github.com/qiansen1386),qiansen1386@gmail.com** +- [@AbrahamGreyson 刘阳](https://github.com/AbrahamGreyson) - [@Aliciamiao](https://github.com/aliciamiao) -- [@riverlet ](https://github.com/riverlet) +- [@fmalee](https://github.com/fmalee) +- [@funson86 花生](https://github.com/funson86) +- [@ivantree 长兴苗木](https://github.com/ivantree) +- [@netyum 未来](https://github.com/netyum) +- [@riverlet 小河](https://github.com/riverlet) +- [@yiichina 巡洋舰](https://github.com/yiichina) Finnish ------