Browse Source

merge from xiaoliushifu

tags/2.0.16
cuileon 7 years ago
parent
commit
3ed0fea789
  1. 229
      docs/guide-zh-CN/caching-data.md
  2. 87
      docs/guide-zh-CN/caching-fragment.md
  3. 88
      docs/guide-zh-CN/caching-http.md
  4. 16
      docs/guide-zh-CN/caching-overview.md
  5. 24
      docs/guide-zh-CN/caching-page.md
  6. 66
      docs/guide-zh-CN/concept-aliases.md
  7. 48
      docs/guide-zh-CN/concept-autoloading.md
  8. 42
      docs/guide-zh-CN/concept-behaviors.md
  9. 27
      docs/guide-zh-CN/concept-components.md
  10. 102
      docs/guide-zh-CN/concept-configurations.md
  11. 299
      docs/guide-zh-CN/concept-di-container.md
  12. 169
      docs/guide-zh-CN/concept-events.md
  13. 38
      docs/guide-zh-CN/concept-properties.md
  14. 29
      docs/guide-zh-CN/concept-service-locator.md
  15. 2
      docs/guide-zh-CN/db-dao.md
  16. 16
      docs/guide-zh-CN/input-multiple-models.md
  17. 149
      docs/guide-zh-CN/intro-upgrade-from-v1.md
  18. 31
      docs/guide-zh-CN/intro-yii.md
  19. 22
      docs/guide-zh-CN/rest-authentication.md
  20. 83
      docs/guide-zh-CN/rest-controllers.md
  21. 9
      docs/guide-zh-CN/rest-error-handling.md
  22. 10
      docs/guide-zh-CN/rest-quick-start.md
  23. 30
      docs/guide-zh-CN/rest-rate-limiting.md
  24. 98
      docs/guide-zh-CN/rest-resources.md
  25. 34
      docs/guide-zh-CN/rest-response-formatting.md
  26. 25
      docs/guide-zh-CN/rest-routing.md
  27. 4
      docs/guide-zh-CN/rest-versioning.md
  28. 10
      docs/guide-zh-CN/runtime-bootstrapping.md
  29. 41
      docs/guide-zh-CN/runtime-handling-errors.md
  30. 4
      docs/guide-zh-CN/runtime-overview.md
  31. 49
      docs/guide-zh-CN/runtime-responses.md
  32. 61
      docs/guide-zh-CN/runtime-sessions-cookies.md
  33. 56
      docs/guide-zh-CN/start-databases.md
  34. 72
      docs/guide-zh-CN/start-forms.md
  35. 18
      docs/guide-zh-CN/start-gii.md
  36. 92
      docs/guide-zh-CN/start-hello.md
  37. 8
      docs/guide-zh-CN/start-installation.md
  38. 28
      docs/guide-zh-CN/start-looking-ahead.md
  39. 20
      docs/guide-zh-CN/start-workflow.md
  40. 34
      docs/guide-zh-CN/structure-application-components.md
  41. 112
      docs/guide-zh-CN/structure-applications.md
  42. 56
      docs/guide-zh-CN/structure-assets.md
  43. 158
      docs/guide-zh-CN/structure-controllers.md
  44. 9
      docs/guide-zh-CN/structure-entry-scripts.md
  45. 44
      docs/guide-zh-CN/structure-filters.md
  46. 81
      docs/guide-zh-CN/structure-models.md
  47. 45
      docs/guide-zh-CN/structure-modules.md
  48. 84
      docs/guide-zh-CN/structure-views.md
  49. 50
      docs/guide-zh-CN/structure-widgets.md
  50. 103
      docs/guide-zh-CN/tutorial-core-validators.md
  51. 66
      docs/guide-zh-CN/tutorial-yii-integration.md

229
docs/guide-zh-CN/caching-data.md

@ -5,8 +5,8 @@
它也是更高级缓存特性的基础,例如[查询缓存](#query-caching)
和[内容缓存](caching-content.md)。
如下代码是一个典型的数据缓存使用模式。其中 `$cache` 指向
[缓存组件](#cache-components):
如下代码是一个典型的数据缓存使用模式。
其中 `$cache` 指向[缓存组件](#cache-components):
```php
// 尝试从缓存中取回 $data
@ -23,16 +23,35 @@ if ($data === false) {
// 这儿 $data 可以使用了。
```
从2.0.11版本开始, [缓存组件](#cache-components) 提供了[[yii\caching\Cache::getOrSet()|getOrSet()]] 方法来简化数据的取回、计算和存储。下面的代码逻辑和上一个例子是完全一样的:
```php
$data = $cache->getOrSet($key, function () {
return $this->calculateSomething();
});
```
当缓存中有关联$key的数据时,将返回这个缓存的值。否则就执行匿名函数来计算出将要缓存的数据并返回它。
如果匿名函数需要作用域外的数据时,可以使用`use`语句把这些数据传递到匿名函数中。例如:
```php
$user_id = 42;
$data = $cache->getOrSet($key, function () use ($user_id) {
return $this->calculateSomething($user_id);
});
```
> 注意: [[yii\caching\Cache::getOrSet()|getOrSet()]] 方法也支持缓存持续性和缓存依赖。请看[缓存过期](#cache-expiration) 和 [缓存依赖](#cache-dependencies) 来了解详细信息。
## 缓存组件 <span id="cache-components"></span>
数据缓存需要**缓存组件**提供支持,它代表各种缓存存储器,
例如内存,文件,数据库。
缓存组件通常注册为应用程序组件,这样
它们就可以在全局进行配置与访问。
如下代码演示了如何配置应用程序组件 `cache` 使用
两个 [memcached](http://memcached.org/) 服务器:
缓存组件通常注册为应用程序组件,这样它们就可以
在全局进行配置与访问。如下代码演示了如何配置应用程序组件
`cache` 使用两个 [memcached](http://memcached.org/)
服务器:
```php
'components' => [
@ -56,8 +75,8 @@ if ($data === false) {
然后就可以通过 `Yii::$app->cache` 访问上面的缓存组件了。
由于所有缓存组件都支持同样的一系列 API ,并不需要修改使用缓存的
业务代码就能直接替换为其他底层缓存组件,只需在应用配置中重新配置一下就可以。
由于所有缓存组件都支持同样的一系列 API ,并不需要修改使用缓存的业务代码
就能直接替换为其他底层缓存组件,只需在应用配置中重新配置一下就可以。
例如,你可以将上述配置修改为使用 [[yii\caching\ApcCache|APC cache]]:
@ -69,74 +88,73 @@ if ($data === false) {
],
```
> Tip: 你可以注册多个缓存组件,很多依赖缓存的类默认调用
名为 `cache` 的组件(例如 [[yii\web\UrlManager]])。
> 提示: 你可以注册多个缓存组件,很多依赖缓存的类默认调用
名为 `cache` 的组件(例如 [[yii\web\UrlManager]])。
### 支持的缓存存储器 <span id="supported-cache-storage"></span>
Yii 支持一系列缓存存储器,概况如下:
* [[yii\caching\ApcCache]]:使用 PHP [APC](http://php.net/manual/en/book.apc.php) 扩展。这个选项可以
认为是集中式应用程序环境中(例如:单一服务器,
没有独立的负载均衡器等)最快的缓存方案。
* [[yii\caching\DbCache]]:使用一个数据库的表存储缓存数据。要使用这个缓存,你必须
创建一个与 [[yii\caching\DbCache::cacheTable]] 对应的表。
* [[yii\caching\ApcCache]]:使用 PHP [APC](http://php.net/manual/en/book.apc.php) 扩展。
这个选项可以认为是集中式应用程序环境中
(例如:单一服务器,没有独立的负载均衡器等)最快的缓存方案。
* [[yii\caching\DbCache]]:使用一个数据库的表存储缓存数据。要使用这个缓存,
你必须创建一个与 [[yii\caching\DbCache::cacheTable]] 对应的表。
* [[yii\caching\DummyCache]]: 仅作为一个缓存占位符,不实现任何真正的缓存功能。
这个组件的目的是为了简化那些需要查询缓存有效性的代码。
例如,在开发中如果服务器没有实际的缓存支持,用它配置
一个缓存组件。一个真正的缓存服务启用后,可以再切换为使用相应的缓存组件。
这个组件的目的是为了简化那些需要查询缓存有效性的代码。例如,
在开发中如果服务器没有实际的缓存支持,用它配置一个缓存组件。
一个真正的缓存服务启用后,可以再切换为使用相应的缓存组件。
两种条件下你都可以使用同样的代码
`Yii::$app->cache->get($key)` 尝试从缓存中取回数据而不用担心
`Yii::$app->cache->get($key)` 尝试从缓存中取回数据而不用担心
`Yii::$app->cache` 可能是 `null`
* [[yii\caching\FileCache]]:使用标准文件存储缓存数据。这个特别适用于
缓存大块数据,例如一个整页的内容。
* [[yii\caching\FileCache]]:使用标准文件存储缓存数据。
这个特别适用于缓存大块数据,例如一个整页的内容。
* [[yii\caching\MemCache]]:使用 PHP [memcache](http://php.net/manual/en/book.memcache.php)
和 [memcached]( http://php.net/manual/en/book.memcached.php) 扩展。
这个选项被看作分布式应用环境中(例如:多台服务器,
有负载均衡等)最快的缓存方案。
* [[yii\redis\Cache]]:实现了一个基于 [Redis](http://redis.io/) 键值对存储器
的缓存组件(需要 redis 2.6.12 及以上版本的支持 )。
和 [memcached](http://php.net/manual/en/book.memcached.php) 扩展。
这个选项被看作分布式应用环境中(例如:多台服务器,有负载均衡等)
最快的缓存方案。
* [[yii\redis\Cache]]:实现了一个基于 [Redis](http://redis.io/) 键值对存储器的缓存组件
(需要 redis 2.6.12 及以上版本的支持 )。
* [[yii\caching\WinCache]]:使用 PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension)
([另可参考](http://php.net/manual/en/book.wincache.php) )扩展。
([另可参考](http://php.net/manual/en/book.wincache.php))扩展.
* [[yii\caching\XCache]]:使用 PHP [XCache](http://xcache.lighttpd.net/)扩展。
* [[yii\caching\ZendDataCache]]:使用
[Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm)
[Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend- server.htm#data_cache_component.htm)
作为底层缓存媒介。
> Tip: 你可以在同一个应用程序中使用不同的缓存存储器。一个常见的策略是使用基于内存的缓存存储器
存储小而常用的数据(例如:统计数据),使用基于文件
或数据库的缓存存储器存储大而不太常用的数据(例如:网页内容)。
> 提示: 你可以在同一个应用程序中使用不同的缓存存储器。一个常见的策略是使用基于内存的缓存存储器
存储小而常用的数据(例如:统计数据),使用基于文件或数据库的缓存存储器
存储大而不太常用的数据(例如:网页内容)。
## 缓存 API <span id="cache-apis"></span>
所有缓存组件都有同样的基类 [[yii\caching\Cache]] ,因此都支持如下 API:
* [[yii\caching\Cache::get()|get()]]:通过一个指定的键(key)从缓存中取回一项数据。如果该项数据
不存在于缓存中或者已经过期/失效,则返回值 false。
* [[yii\caching\Cache::set()|set()]]:将一项数据指定一个键,存放到缓存中。
* [[yii\caching\Cache::get()|get()]]:通过一个指定的键(key)从缓存中取回一项数据。
如果该项数据不存在于缓存中或者已经过期/失效,则返回值 false。
* [[yii\caching\Cache::set()|set()]]:将一个由键指定的数据项存放到缓存中。
* [[yii\caching\Cache::add()|add()]]:如果缓存中未找到该键,则将指定数据存放到缓存中。
* [[yii\caching\Cache::mget()|mget()]]:通过指定的多个键从缓存中取回多项数据。
* [[yii\caching\Cache::mset()|mset()]]:将多项数据存储到缓存中,每项数据对应一个键
* [[yii\caching\Cache::madd()|madd()]]:将多项数据存储到缓存中,每项数据对应一个键
如果某个键已经存在于缓存中,则该项数据会被跳过
* [[yii\caching\Cache::getOrSet()|getOrSet()]]:返回由键指定的缓存项,或者执行回调函数,把函数的返回值用键来关联存储到缓存中,最后返回这个函数的返回值。
* [[yii\caching\Cache::multiGet()|multiGet()]]:由指定的键获取多个缓存数据项
* [[yii\caching\Cache::multiSet()|multiSet()]]:一次存储多个数据项到缓存中,每个数据都由一个键来指明
* [[yii\caching\Cache::multiAdd()|multiAdd()]]:一次存储多个数据项到缓存中,每个数据都由一个键来指明。如果某个键已经存在,则略过该数据项不缓存
* [[yii\caching\Cache::exists()|exists()]]:返回一个值,指明某个键是否存在于缓存中。
* [[yii\caching\Cache::delete()|delete()]]:通过一个键,删除缓存中对应的值。
* [[yii\caching\Cache::flush()|flush()]]:删除缓存中的所有数据。
> Note: Do not cache a `false` boolean value directly because the [[yii\caching\Cache::get()|get()]] method uses
`false` return value to indicate the data item is not found in the cache. You may put `false` in an array and cache
this array instead to avoid this problem.
> 注意: 千万别直接用`false`布尔值当做数据项缓存,因为[[yii\caching\Cache::get()|get()]]方法用
`false`作为返回值来表名对应的缓存项不存在。你可以把`false`放到一个数组里然后缓存这个数组来避免上述的混淆问题。
有些缓存存储器如 MemCache,APC 支持以批量模式取回缓存值,这样可以节省取回
缓存数据的开支。[[yii\caching\Cache::mget()|mget()]] 和
[[yii\caching\Cache::madd()|madd()]] API提供对该特性的支持。
有些缓存存储器如 MemCache,APC 支持以批量模式取回缓存值,这样可以节省取回缓存数据的开支。
[[yii\caching\Cache::multiGet()|multiGet()]]
和 [[yii\caching\Cache::multiAdd()|multiAdd()]] API提供对该特性的支持。
如果底层缓存存储器不支持该特性,Yii 也会模拟实现。
由于 [[yii\caching\Cache]] 实现了 PHP `ArrayAccess` 接口,缓存组件也可以像数组那样使用,
下面是几个例子:
由于 [[yii\caching\Cache]] 实现了 PHP `ArrayAccess` 接口,
缓存组件也可以像数组那样使用,下面是几个例子:
```php
$cache['var1'] = $value1; // 等价于: $cache->set('var1', $value1);
@ -146,12 +164,12 @@ $value2 = $cache['var2']; // 等价于: $value2 = $cache->get('var2');
### 缓存键 <span id="cache-keys"></span>
存储在缓存中的每项数据都通过键作唯一识别。当你在缓存中存储一项
数据时,必须为它指定一个键,稍后从缓存中取回数据时,也需要提供
相应的键。
存储在缓存中的每项数据都通过键作唯一识别。
当你在缓存中存储一项数据时,必须为它指定一个键,
稍后从缓存中取回数据时,也需要提供相应的键。
你可以使用一个字符串或者任意值作为一个缓存键。当键不是一个字符串时,它将会自动
被序列化为一个字符串。
你可以使用一个字符串或者任意值作为一个缓存键。当键不是一个字符串时,
它将会自动被序列化为一个字符串。
定义一个缓存键常见的一个策略就是在一个数组中包含所有的决定性因素。
例如,[[yii\db\Schema]] 使用如下键存储一个数据表的结构信息。
@ -167,9 +185,13 @@ $value2 = $cache['var2']; // 等价于: $value2 = $cache->get('var2');
如你所见,该键包含了可唯一指定一个数据库表所需的所有必要信息。
当同一个缓存存储器被用于多个不同的应用时,应该为每个应用指定一个唯一的缓存键前缀
以避免缓存键冲突。可以通过配置 [[yii\caching\Cache::keyPrefix]]
属性实现。例如,在应用配置中可以编写如下代码:
> 注意: 通过[[yii\caching\Cache::multiSet()|multiSet()]]或者[[yii\caching\Cache::multiAdd()|multiAdd()]]方法缓存的数据项的键,它的类型只能是字符串或整型,
如果你想使用较为复杂的键,可以通过
[[yii\caching\Cache::set()|set()]]或者[[yii\caching\Cache::add()|add()]]方法来存储。
当同一个缓存存储器被用于多个不同的应用时,应该为每个应用指定一个唯一的缓存键前缀以避免缓存键冲突。
可以通过配置 [[yii\caching\Cache::keyPrefix]] 属性实现。
例如,在应用配置中可以编写如下代码:
```php
'components' => [
@ -185,12 +207,12 @@ $value2 = $cache['var2']; // 等价于: $value2 = $cache->get('var2');
### 缓存过期 <span id="cache-expiration"></span>
默认情况下,缓存中的数据会永久存留,除非它被某些缓存策略强制移除(例如:
缓存空间已满,最老的数据会被移除)。要改变此特性,你可以在调用
[[yii\caching\Cache::set()|set()]] 存储一项数据时提供一个过期时间参数
该参数代表这项数据在缓存中可保持有效多少秒。当你调用
[[yii\caching\Cache::get()|get()]] 取回数据时,如果它已经过了超时时间,
该方法将返回 false,表明在缓存中找不到这项数据。例如:
默认情况下,缓存中的数据会永久存留,除非它被某些缓存策略强制移除(例如:缓存空间已满,最老的数据会被移除)。
要改变此特性,你可以在调用 [[yii\caching\Cache::set()|set()]] 存储一项数据时提供一个过期时间参数。
该参数代表这项数据在缓存中可保持有效多少秒
当你调用 [[yii\caching\Cache::get()|get()]] 取回数据时,
如果它已经过了超时时间,该方法将返回 false,表明在缓存中找不到这项数据。
例如:
```php
// 将数据在缓存中保留 45 秒
@ -204,6 +226,9 @@ if ($data === false) {
}
```
从2.0.11开始,如果想自定义缓存的持续时间,你可以在缓存组件配置中设置[[yii\caching\Cache::$defaultDuration|defaultDuration]]成员属性的值。
这样设置会覆盖默认的缓存持续时间,且在使用[[yii\caching\Cache::set()|set()]]方法时不必每次都传递$duration参数。
### 缓存依赖 <span id="cache-dependencies"></span>
@ -213,8 +238,8 @@ if ($data === false) {
因此,缓存中任何过期的文件内容都应该被置为失效状态,
对 [[yii\caching\Cache::get()|get()]] 的调用都应该返回 false。
缓存依赖用 [[yii\caching\Dependency]] 的派生类所表示。当调用
[[yii\caching\Cache::set()|set()]] 在缓存中存储一项数据时,
缓存依赖用 [[yii\caching\Dependency]] 的派生类所表示。
当调用 [[yii\caching\Cache::set()|set()]] 在缓存中存储一项数据时,
可以同时传递一个关联的缓存依赖对象。例如:
```php
@ -237,13 +262,11 @@ $data = $cache->get($key);
- [[yii\caching\DbDependency]]:如果指定 SQL 语句的查询结果发生了变化,则依赖改变。
- [[yii\caching\ExpressionDependency]]:如果指定的 PHP 表达式执行结果发生变化,则依赖改变。
- [[yii\caching\FileDependency]]:如果文件的最后修改时间发生变化,则依赖改变。
- [[yii\caching\GroupDependency]]:将一项缓存数据标记到一个组名,你可以通过调用
[[yii\caching\GroupDependency::invalidate()]] 一次性将相同组名的缓存全部置为失效状态。
> Note: Avoid using [[yii\caching\Cache::exists()|exists()]] method along with dependencies. It does not check whether
the dependency associated with the cached data, if there is any, has changed. So a call to
[[yii\caching\Cache::get()|get()]] may return `false` while [[yii\caching\Cache::exists()|exists()]] returns `true`.
- [[yii\caching\TagDependency]]: associates a cached data item with one or multiple tags. You may invalidate
the cached data items with the specified tag(s) by calling [[yii\caching\TagDependency::invalidate()]].
> 注意:避免对带有缓存依赖的缓存项使用 [[yii\caching\Cache::exists()|exists()]] 方法,因为它不检测缓存依赖(如果有的话)是否有效,所以调用[[yii\caching\Cache::get()|get()]]可能返回`false`而调用[[yii\caching\Cache::exists()|exists()]]却返回`true`。
## 查询缓存 <span id="query-caching"></span>
@ -263,7 +286,7 @@ $result = $db->cache(function ($db) {
});
```
查询缓存可以用于 [ActiveRecord](db-active-record.md) 和 [DAO](db-dao.md)。
查询缓存可以用在[DAO](db-dao.md)和[ActiveRecord](db-active-record.md)上:
```php
$result = Customer::getDb()->cache(function ($db) {
@ -271,24 +294,22 @@ $result = Customer::getDb()->cache(function ($db) {
});
```
> Info: 有些 DBMS (例如:[MySQL](http://dev.mysql.com/doc/refman/5.1/en/query-cache.html)
也支持数据库服务器端的查询缓存。你可以选择使用任一查询缓存机制
上文所述的查询缓存的好处在于你可以指定更灵活的缓存
依赖因此可能更加高效。
> Info: 有些 DBMS (例如:[MySQL](http://dev.mysql.com/doc/refman/5.1/en/query-cache.html))
也支持数据库服务器端的查询缓存。
你可以选择使用任一查询缓存机制。
上文所述的查询缓存的好处在于你可以指定更灵活的缓存依赖因此可能更加高效。
### Cache Flushing <span id="cache-flushing">
### 缓存冲刷 <span id="cache-flushing">
When you need to invalidate all the stored cache data, you can call [[yii\caching\Cache::flush()]].
当你想让所有的缓存数据失效时,可以调用[[yii\caching\Cache::flush()]]。
You can flush the cache from the console by calling `yii cache/flush` as well.
- `yii cache`: lists the available caches in application
- `yii cache/flush cache1 cache2`: flushes the cache components `cache1`, `cache2` (you can pass multiple component
names separated with space)
- `yii cache/flush-all`: flushes all cache components in the application
冲刷缓存数据,你还可以从控制台调用`yii cache/flush`。
- `yii cache`: 列出应用中可用的缓存组件
- `yii cache/flush cache1 cache2`: 冲刷缓存组件`cache1`, `cache2` (可以传递多个用空格分开的缓存组件)
- `yii cache/flush-all`: 冲刷应用中所有的缓存组件
> Info: Console application uses a separate configuration file by default. Ensure, that you have the same caching
components in your web and console application configs to reach the proper effect.
> Info: 默认情况下,控制台应用使用独立的配置文件。所以,为了上述命令发挥作用,请确保Web应用和控制台应用配置相同的缓存组件。
### 配置 <span id="query-caching-configs"></span>
@ -329,8 +350,33 @@ If the result of a query is found valid in the cache, the query will be skipped
from the cache instead. If you do not specify the `$duration` parameter, the value of
[[yii\db\Connection::queryCacheDuration|queryCacheDuration]] will be used instead.
Sometimes within `cache()`, you may want to disable query caching for some particular queries. You can use
[[yii\db\Connection::noCache()]] in this case.
* [[yii\db\Connection::enableQueryCache|enableQueryCache]]:是否开启或关闭查询缓存,默认是`true`。注意,为了有效的开启查询缓存,你还需要配置一个由[[yii\db\Connection::queryCache|queryCache]]属性指定的缓存组件。
* [[yii\db\Connection::queryCacheDuration|queryCacheDuration]]: 这表示查询结果能够保持有效的秒数,设置为0的话,则会在缓存组件中永久缓存。这也是调用[[yii\db\Connection::cache()]]而没有指明缓存持续时间时的默认值。
* [[yii\db\Connection::queryCache|queryCache]]: 缓存应用组件的 ID。默认为 `'cache'`
只有在设置了一个有效的缓存应用组件时,查询缓存才会有效。
### 用法 <span id="query-caching-usages"></span>
如果一次有多个SQL查询想利用查询缓存,你可以用[[yii\db\Connection::cache()]] 。用法如下,
```php
$duration = 60; // cache query results for 60 seconds.
$dependency = ...; // optional dependency
$result = $db->cache(function ($db) {
// ... perform SQL queries here ...
return $result;
}, $duration, $dependency);
```
在匿名函数里的任何一个SQL查询都会伴随指定的duration和dependency来生成缓存。
如果一个SQL查询的结果在缓存中有效,那么这个SQl语句将会被跳过而它的查询结果会直接从缓存中读取。如果你没有指明`$duration`参数,那么使用[[yii\db\Connection::queryCacheDuration|queryCacheDuration]]属性。
有时在`cache()`里,你可能不想缓存某些特殊的查询,这时你可以用[[yii\db\Connection::noCache()]]。
```php
$result = $db->cache(function ($db) {
@ -349,15 +395,14 @@ $result = $db->cache(function ($db) {
});
```
If you just want to use query caching for a single query, you can call [[yii\db\Command::cache()]] when building
the command. For example,
如果仅仅想缓存一个单独的查询,那么在建立查询命令时可以使用[[yii\db\Command::cache()]]。例如,
```php
// use query caching and set query cache duration to be 60 seconds
$customer = $db->createCommand('SELECT * FROM customer WHERE id=1')->cache(60)->queryOne();
```
You can also use [[yii\db\Command::noCache()]] to disable query caching for a single command. For example,
也可以用[[yii\db\Command::noCache()]]来单独设置某些查询命令不缓存。例如,
```php
$result = $db->cache(function ($db) {
@ -376,11 +421,11 @@ $result = $db->cache(function ($db) {
### 限制条件 <span id="query-caching-limitations"></span>
当查询结果中含有资源句柄时,查询缓存无法使用。例如,
在有些 DBMS 中使用了 `BLOB` 列的时候,缓存结果会为
该数据列返回一个资源句柄。
当查询结果中含有资源句柄时,查询缓存无法使用。
例如,在有些 DBMS 中使用了 `BLOB` 列的时候,
缓存结果会为该数据列返回一个资源句柄。
有些缓存存储器有大小限制。例如,memcache 限制每条数据
最大为 1MB。因此,如果查询结果的大小超出了该限制,
有些缓存存储器有大小限制。例如,memcache 限制每条数据最大为 1MB。
因此,如果查询结果的大小超出了该限制,
则会导致缓存失败。

87
docs/guide-zh-CN/caching-fragment.md

@ -2,8 +2,8 @@
================
片段缓存指的是缓存页面内容中的某个片段。例如,一个页面显示了逐年销售额的摘要表格,
可以把表格缓存下来,以消除每次请求都要重新生成表格
的耗时。片段缓存是基于[数据缓存](caching-data.md)实现的。
可以把表格缓存下来,以消除每次请求都要重新生成表格的耗时。
片段缓存是基于[数据缓存](caching-data.md)实现的。
在[视图](structure-views.md)中使用以下结构启用片段缓存:
@ -16,27 +16,27 @@ if ($this->beginCache($id)) {
}
```
调用 [[yii\base\View::beginCache()|beginCache()]] 和 [[yii\base\View::endCache()|endcache()]]
方法包裹内容生成逻辑。如果缓存中存在该内容,[[yii\base\View::beginCache()|beginCache()]]
方法将渲染内容并返回 false,因此将跳过内容生成逻辑。否则,
内容生成逻辑被执行,一直执行到 [[yii\base\View::endCache()|endCache()]]
时,生成的内容将被捕获并存储在缓存中。
调用 [[yii\base\View::beginCache()|beginCache()]] 和 [[yii\base\View::endCache()|endcache()]] 方法包裹内容生成逻辑。
如果缓存中存在该内容,[[yii\base\View::beginCache()|beginCache()]] 方法将渲染内容并返回 false,
因此将跳过内容生成逻辑。否则,内容生成逻辑被执行
一直执行到[[yii\base\View::endCache()|endCache()]] 时,
生成的内容将被捕获并存储在缓存中。
和[[数据缓存]](caching-data.md)一样,每个片段缓存也需要全局唯一的 `$id` 标记。
## 缓存选项 <span id="caching-options"></span>
如果要为片段缓存指定额外配置项,请通过向 [[yii\base\View::beginCache()|beginCache()]]
方法第二个参数传递配置数组。在框架内部,
该数组将被用来配置一个 [[yii\widget\FragmentCache]]
如果要为片段缓存指定额外配置项,
请通过向 [[yii\base\View::beginCache()|beginCache()]]
方法第二个参数传递配置数组。在框架内部,该数组将被用来配置一个 [[yii\widget\FragmentCache]]
小部件用以实现片段缓存功能。
### 过期时间(duration) <span id="duration"></span>
或许片段缓存中最常用的一个配置选项就是
[[yii\widgets\FragmentCache::duration|duration]] 了
它指定了内容被缓存的秒数。以下代码缓存内容最多一小时:
或许片段缓存中最常用的一个配置选项就是 [[yii\widgets\FragmentCache::duration|duration]] 了。
它指定了内容被缓存的秒数
以下代码缓存内容最多一小时:
```php
if ($this->beginCache($id, ['duration' => 3600])) {
@ -47,13 +47,13 @@ if ($this->beginCache($id, ['duration' => 3600])) {
}
```
如果该选项未设置,it will take the default value 60, which means the cached content will expire in 60 seconds.
If the option is not set, it will take the default value 60, which means the cached content will expire in 60 seconds.
### 依赖 <span id="dependencies"></span>
和[[数据缓存]](caching-data.md)一样,片段缓存的内容一样可以设置缓存依赖。例如
一段被缓存的文章,是否重新缓存取决于它是否被修改过。
和[[数据缓存]](caching-data.md)一样,片段缓存的内容一样可以设置缓存依赖。
例如一段被缓存的文章,是否重新缓存取决于它是否被修改过。
通过设置 [[yii\widgets\FragmentCache::dependency|dependency]] 选项来指定依赖,
该选项的值可以是一个 [[yii\caching\Dependency]] 类的派生类,也可以是创建缓存对象的配置数组。
@ -76,8 +76,8 @@ if ($this->beginCache($id, ['dependency' => $dependency])) {
### 变化 <span id="variations"></span>
缓存的内容可能需要根据一些参数的更改而变化。例如一个 Web 应用
支持多语言,同一段视图代码也许需要生成多个语言的内容。
缓存的内容可能需要根据一些参数的更改而变化。
例如一个 Web 应用支持多语言,同一段视图代码也许需要生成多个语言的内容。
因此可以设置缓存根据应用当前语言而变化。
通过设置 [[yii\widgets\FragmentCache::variations|variations]] 选项来指定变化,
@ -96,10 +96,10 @@ if ($this->beginCache($id, ['variations' => [Yii::$app->language]])) {
### 开关 <span id="toggling-caching"></span>
有时你可能只想在特定条件下开启片段缓存。例如,一个显示表单的页面,可能只
需要在初次请求时缓存表单(通过 GET 请求)。随后请求所显示(通过 POST 请求)
的表单不该使用缓存,因为此时表单中可能包含用户输入内容。鉴于此种情况,可以使用
[[yii\widgets\FragmentCache::enabled|enabled]] 选项来指定缓存开关,如下所示:
有时你可能只想在特定条件下开启片段缓存。例如,一个显示表单的页面,可能只需要在初次请求时缓存表单(通过 GET 请求)。
随后请求所显示(通过 POST 请求)的表单不该使用缓存,因为此时表单中可能包含用户输入内容。
鉴于此种情况,可以使用 [[yii\widgets\FragmentCache::enabled|enabled]] 选项来指定缓存开关,
如下所示:
```php
if ($this->beginCache($id, ['enabled' => Yii::$app->request->isGet])) {
@ -114,8 +114,8 @@ if ($this->beginCache($id, ['enabled' => Yii::$app->request->isGet])) {
## 缓存嵌套 <span id="nested-caching"></span>
片段缓存可以被嵌套使用。一个片段缓存可以被另一个包裹。
例如,评论被缓存在里层,同时整个评论的片段又被缓存在
外层的文章中。以下代码展示了片段缓存的嵌套使用:
例如,评论被缓存在里层,同时整个评论的片段又被缓存在外层的文章中。
以下代码展示了片段缓存的嵌套使用:
```php
if ($this->beginCache($id1)) {
@ -135,28 +135,28 @@ if ($this->beginCache($id1)) {
}
```
可以为嵌套的缓存设置不同的配置项。例如,内层缓存和外层缓存使用
不同的过期时间。甚至当外层缓存的数据过期失效了,内层缓存仍然
可能提供有效的片段缓存数据。但是,反之则不然。如果外层片段缓存
没有过期而被视为有效,此时即使内层片段缓存已经失效,它也将继续
提供同样的缓存副本。因此,你必须谨慎处理缓存嵌套中的过期时间和
依赖,否则外层的片段很有可能返回的是不符合你预期的失效数据。
可以为嵌套的缓存设置不同的配置项。例如,内层缓存和外层缓存使用不同的过期时间。
甚至当外层缓存的数据过期失效了,内层缓存仍然可能提供有效的片段缓存数据。
但是,反之则不然。如果外层片段缓存没有过期而被视为有效,
此时即使内层片段缓存已经失效,它也将继续提供同样的缓存副本。
因此,你必须谨慎处理缓存嵌套中的过期时间和依赖,
否则外层的片段很有可能返回的是不符合你预期的失效数据。
> 译注:外层的失效时间应该短于内层,外层的依赖条件应该低于内层,以确保最小的片段,返回的是最新的数据。
## 动态内容 <span id="dynamic-content"></span>
使用片段缓存时,可能会遇到一大段较为静态的内容中有少许动态内
容的情况。例如,一个显示着菜单栏和当前用户名的页面头部。还有
一种可能是缓存的内容可能包含每次请求都需要执行的 PHP 代码
(例如注册资源包的代码)。这两个问题都可以
使用 **动态内容** 功能解决。
使用片段缓存时,可能会遇到一大段较为静态的内容中有少许动态内容的情况。
例如,一个显示着菜单栏和当前用户名的页面头部。
还有一种可能是缓存的内容可能包含每次请求
都需要执行的 PHP 代码(例如注册资源包的代码)。
这两个问题都可以使用**动态内容**功能解决。
动态内容的意思是这部分输出的内容不该被缓存,即便是它被包裹
在片段缓存中。为了使内容保持动态,每次请求都执行 PHP 代码
生成,即使这些代码已经被缓存了。
动态内容的意思是这部分输出的内容不该被缓存,即便是它被包裹在片段缓存中。
为了使内容保持动态,每次请求都执行 PHP 代码生成,
即使这些代码已经被缓存了。
可以在片段缓存中调用 [[yii\base\View::renderDynamic()]] 去
插入动态内容,如下所示:
可以在片段缓存中调用 [[yii\base\View::renderDynamic()]] 去插入动态内容,
如下所示:
```php
if ($this->beginCache($id1)) {
@ -171,6 +171,7 @@ if ($this->beginCache($id1)) {
}
```
[[yii\base\View::renderDynamic()|renderDynamic()]] 方法接受
一段 PHP 代码作为参数。代码的返回值被看作是动态内容。这段代
码将在每次请求时都执行,无论其外层的片段缓存是否被存储。
[[yii\base\View::renderDynamic()|renderDynamic()]] 方法接受一段 PHP 代码作为参数。
代码的返回值被看作是动态内容。这段代码将在每次请求时都执行,
无论其外层的片段缓存是否被存储。

88
docs/guide-zh-CN/caching-http.md

@ -1,12 +1,12 @@
HTTP 缓存
============
除了前面章节讲到的服务器端缓存外, Web 应用还可以利用客户端
缓存去节省相同页面内容的生成和传输时间。
除了前面章节讲到的服务器端缓存外, Web 应用还可以利用客户端缓存
去节省相同页面内容的生成和传输时间。
通过配置 [[yii\filters\HttpCache]] 过滤器,控制器动作渲染的内容就能
缓存在客户端。[[yii\filters\HttpCache|HttpCache]] 过滤器仅对 `GET`
`HEAD` 请求生效,它能为这些请求设置三种与缓存有关的 HTTP 头。
通过配置 [[yii\filters\HttpCache]] 过滤器,控制器操作渲染的内容就能缓存在客户端。
[[yii\filters\HttpCache|HttpCache]] 过滤器仅对 `GET``HEAD` 请求生效,
它能为这些请求设置三种与缓存有关的 HTTP 头。
* [[yii\filters\HttpCache::lastModified|Last-Modified]]
* [[yii\filters\HttpCache::etagSeed|Etag]]
@ -17,9 +17,9 @@ HTTP 缓存
`Last-Modified` 头使用时间戳标明页面自上次客户端缓存后是否被修改过。
通过配置 [[yii\filters\HttpCache::lastModified]] 属性向客户端发送
`Last-Modified` 头。该属性的值应该为 PHP callable 类型,返回的是页
面修改时的 Unix 时间戳。该 callable 的参数和返回值应该如下:
通过配置 [[yii\filters\HttpCache::lastModified]] 属性向客户端发送 `Last-Modified` 头。
该属性的值应该为 PHP callable 类型,返回的是页面修改时的 Unix 时间戳。
该 callable 的参数和返回值应该如下:
```php
/**
@ -48,23 +48,23 @@ public function behaviors()
}
```
上述代码表明 HTTP 缓存只在 `index` 动作时启用。它会基于页面
最后修改时间生成一个 `Last-Modified` HTTP 头。当浏览器第一
次访问 `index` 页时,服务器将会生成页面并发送至客户端浏览器。
之后客户端浏览器在页面没被修改期间访问该页,服务器将不会重新
生成页面,浏览器会使用之前客户端缓存下来的内容。因此服务端
渲染和内容传输都将省去。
上述代码表明 HTTP 缓存只在 `index` 操作时启用。
它会基于页面最后修改时间生成一个 `Last-Modified` HTTP 头。
当浏览器第一次访问 `index` 页时,服务器将会生成页面并发送至客户端浏览器。
之后客户端浏览器在页面没被修改期间访问该页,
服务器将不会重新生成页面,浏览器会使用之前客户端缓存下来的内容。
因此服务端渲染和内容传输都将省去。
## `ETag`<span id="etag"></span>
“Entity Tag”(实体标签,简称 ETag)使用一个哈希值表示页面内容。如果页面
被修改过,哈希值也会随之改变。通过对比客户端的哈希值和服务器端生成的哈
希值,浏览器就能判断页面是否被修改过,进而决定是否应该重新传输内容。
“Entity Tag”(实体标签,简称 ETag)使用一个哈希值表示页面内容。如果页面被修改过,
哈希值也会随之改变。通过对比客户端的哈希值和服务器端生成的哈希值,
浏览器就能判断页面是否被修改过,进而决定是否应该重新传输内容。
通过配置 [[yii\filters\HttpCache::etagSeed]] 属性向客户端发送
`ETag` 头。该属性的值应该为 PHP callable 类型,返回的是一段种
子字符用来生成 ETag 哈希值。该 callable 的参数和返回值应该如下:
通过配置 [[yii\filters\HttpCache::etagSeed]] 属性向客户端发送 `ETag` 头。
该属性的值应该为 PHP callable 类型,返回的是一段种子字符用来生成 ETag 哈希值。
该 callable 的参数和返回值应该如下:
```php
/**
@ -93,31 +93,31 @@ public function behaviors()
}
```
上述代码表明 HTTP 缓存只在 `view` 动作时启用。它会基于用户
请求的标题和内容生成一个 `ETag` HTTP 头。当浏览器第一次访问
`view` 页时,服务器将会生成页面并发送至客户端浏览器。之后
客户端浏览器标题和内容没被修改在期间访问该页,服务器将不会
重新生成页面,浏览器会使用之前客户端缓存下来的内容。
上述代码表明 HTTP 缓存只在 `view` 操作时启用。
它会基于用户请求的标题和内容生成一个 `ETag` HTTP 头。
当浏览器第一次访问 `view` 页时,服务器将会生成页面并发送至客户端浏览器。
之后客户端浏览器标题和内容没被修改在期间访问该页,服务器将不会重新生成页面,
浏览器会使用之前客户端缓存下来的内容。
因此服务端渲染和内容传输都将省去。
ETag 相比 `Last-Modified` 能实现更复杂和更精确的缓存策略。
例如,当站点切换到另一个主题时可以使 ETag 失效。
复杂的 Etag 生成种子可能会违背使用 `HttpCache` 的初衷而引起
不必要的性能开销,因为响应每一次请求都需要重新计算 Etag。
复杂的 Etag 生成种子可能会违背使用 `HttpCache` 的初衷而引起不必要的性能开销,
因为响应每一次请求都需要重新计算 Etag。
请试着找出一个最简单的表达式去触发 Etag 失效。
> 注意:为了遵循 [RFC 7232(HTTP 1.1 协议)](http://tools.ietf.org/html/rfc7232#section-2.4)
如果同时配置了 `ETag``Last-Modified` 头,`HttpCache` 将会同时
发送它们。并且如果客户端同时发送 `If-None-Match`
`If-Modified-Since` 头,则只有前者会被接受。
> Note: 为了遵循 [RFC 7232(HTTP 1.1 协议)](http://tools.ietf.org/html/rfc7232#section-2.4),
如果同时配置了 `ETag``Last-Modified` 头,`HttpCache` 将会同时发送它们。
并且如果客户端同时发送 `If-None-Match``If-Modified-Since` 头,
则只有前者会被接受。
## `Cache-Control`<span id="cache-control"></span>
`Cache-Control` 头指定了页面的常规缓存策略。可以通过配置
[[yii\filters\HttpCache::cacheControlHeader]] 属性发送相
应的头信息。默认发送以下头:
`Cache-Control` 头指定了页面的常规缓存策略。
可以通过配置 [[yii\filters\HttpCache::cacheControlHeader]]
属性发送相应的头信息。默认发送以下头:
```
Cache-Control: public, max-age=3600
@ -125,19 +125,19 @@ Cache-Control: public, max-age=3600
## 会话缓存限制器 <span id="session-cache-limiter"></span>
当页面使 session 时,PHP 将会按照 PHP.INI 中所设置的`session.cache_limiter`
值自动发送一些缓存相关的 HTTP 头。这些 HTTP 头有可能会干扰你原本设置的
`HttpCache` 或让其失效。为了避免此问题,默认情况下 `HttpCache` 禁止
自动发送这些头。想改变这一行为,可以配置
[[yii\filters\HttpCache::sessionCacheLimiter]] 属性。该属性接受一个
字符串值,包括 `public`,`private`,`private_no_expire`,
`nocache`请参考 PHP 手册中的[缓存限制器](http://www.php.net/manual/en/function.session-cache-limiter.php)
当页面使 session 时,PHP 将会按照 PHP.INI
中所设置的 `session.cache_limiter` 值自动发送一些缓存相关的 HTTP 头。
这些 HTTP 头有可能会干扰你原本设置的 `HttpCache` 或让其失效。
为了避免此问题,默认情况下 `HttpCache` 禁止自动发送这些头。
想改变这一行为,可以配置 [[yii\filters\HttpCache::sessionCacheLimiter]] 属性。
该属性接受一个字符串值,包括 `public`,`private`,`private_no_expire`,`nocache`
请参考 PHP 手册中的[缓存限制器](http://www.php.net/manual/en/function.session-cache-limiter.php)
了解这些值的含义。
## SEO 影响 <span id="seo-implications"></span>
搜索引擎趋向于遵循站点的缓存头。因为一些爬虫的
抓取频率有限制,启用缓存头可以可以减少重复请求
数量,增加爬虫抓取效率(译者:大意如此,但搜索引擎的排名规则不了解,好的缓存策略应该是可以为用户体验加分的)。
搜索引擎趋向于遵循站点的缓存头。因为一些爬虫的抓取频率有限制,
启用缓存头可以可以减少重复请求数量,增加爬虫抓取效率
(译者:大意如此,但搜索引擎的排名规则不了解,好的缓存策略应该是可以为用户体验加分的)。

16
docs/guide-zh-CN/caching-overview.md

@ -1,15 +1,15 @@
缓存
=======
缓存是提升 Web 应用性能简便有效的方式。通过将相对静态的数据
存储到缓存并在收到请求时取回缓存,应用程序便节省了每次重新生
成这些数据所需的时间。
缓存是提升 Web 应用性能简便有效的方式。
通过将相对静态的数据存储到缓存并在收到请求时取回缓存,
应用程序便节省了每次重新生成这些数据所需的时间。
缓存可以应用在 Web 应用程序的任何层级任何位置。在服务器端,
在较的低层面,缓存可能用于存储基础数据,例如从数据库中取
出的最新文章列表;在较高的层面,缓存可能用于存储一段或整
个 Web 页面,例如最新文章的渲染结果。在客户端,HTTP 缓存
可能用于将最近访问的页面内容存储到浏览器缓存中。
缓存可以应用在 Web 应用程序的任何层级任何位置。
服务器端,在较的低层面,缓存可能用于存储基础数据,例如从数据库中取出的最新文章列表;
在较高的层面,缓存可能用于存储一段或整个 Web 页面,
例如最新文章的渲染结果。在客户端,HTTP 缓存可能用于
将最近访问的页面内容存储到浏览器缓存中。
Yii 支持如上所有缓存机制:

24
docs/guide-zh-CN/caching-page.md

@ -1,11 +1,11 @@
页面缓存
============
页面缓存指的是在服务器端缓存整个页面的内容。随后当同一个页面
被请求时,内容将从缓存中取出,而不是重新生成。
页面缓存指的是在服务器端缓存整个页面的内容。
随后当同一个页面被请求时,内容将从缓存中取出,而不是重新生成。
页面缓存由 [[yii\filters\PageCache]] 类提供支持,该类是一个
[过滤器](structure-filters.md)。它可以像这样在控制器类中使用:
页面缓存由 [[yii\filters\PageCache]] 类提供支持,该类是一个[过滤器](structure-filters.md)。
它可以像这样在控制器类中使用:
```php
public function behaviors()
@ -27,14 +27,14 @@ public function behaviors()
}
```
上述代码表示页面缓存只在 `index` 动作时启用,页面内容最多被缓存
60 秒,会随着当前应用的语言更改而变化。如果文章总数发生变化则缓
存的页面会失效。
上述代码表示页面缓存只在 `index` 操作时启用,页面内容最多被缓存 60 秒,
会随着当前应用的语言更改而变化。
如果文章总数发生变化则缓存的页面会失效。
如你所见,页面缓存和[片段缓存](caching-fragment.md)极其相似。它们都支持 `duration`,`dependencies`,
`variations``enabled` 配置选项。它们的主要区别是页面缓存是由[过滤器](structure-filters.md)实现,
而片段缓存则是一个[小部件](structure-widgets.md)。
如你所见,页面缓存和[片段缓存](caching-fragment.md)极其相似。
它们都支持 `duration`,`dependencies`,`variations``enabled` 配置选项。
它们的主要区别是页面缓存是由[过滤器](structure-filters.md)实现,而片段缓存则是一个[小部件](structure-widgets.md)。
你可以在使用页面缓存的同时,使用[片段缓存](caching-fragment.md)和
[动态内容](caching-fragment.md#dynamic-content)。
你可以在使用页面缓存的同时,
使用[片段缓存](caching-fragment.md)和[动态内容](caching-fragment.md#dynamic-content)。

66
docs/guide-zh-CN/concept-aliases.md

@ -1,12 +1,12 @@
别名(Aliases)
=======
别名用来表示文件路径和 URL,这样就避免了在代码中硬编码一些绝对路径
和 URL。一个别名必须以 `@` 字符开头,以区别于传统的文件路径和 URL。
Alias defined without leading `@` will be prefixed with `@` character.
别名用来表示文件路径和 URL,这样就避免了在代码中硬编码一些绝对路径和 URL。
一个别名必须以 `@` 字符开头,以区别于传统的文件路径和 URL。
Yii 预定义了大量可用的别名。例如,别名 `@yii` 指的是 Yii 框架本身的安装目录,而 `@web` 表示的是当前运行应用的根 URL。
Yii 预定义了大量可用的别名。例如,别名 `@yii` 指的是 Yii 框架本身的安装
目录,而 `@web` 表示的是当前运行应用的根 URL。
Yii has many pre-defined aliases already available. For example, the alias `@yii` represents the installation path of
the Yii framework; `@web` represents the base URL for the currently running Web application.
定义别名 <span id="defining-aliases"></span>
----------------
@ -23,10 +23,10 @@ Yii::setAlias('@bar', 'http://www.example.com');
> 注意:别名所指向的文件路径或 URL 不一定是真实存在的文件或资源。
可以通过在一个别名后面加斜杠 `/` 和一至多个路径分段生成新别名
(无需调用 [[Yii::setAlias()]])。我们把通过 [[Yii::setAlias()]]
定义的别名称为**根别名**,而用他们衍生出去的别名成为**衍生别名**。
例如,`@foo` 就是根别名,`@foo/bar/file.php` 是一个衍生别名。
可以通过在一个别名后面加斜杠 `/` 和一至多个路径分段生成新别名(无需调用 [[Yii::setAlias()]])。
们把通过 [[Yii::setAlias()]] 定义的别名称为**根别名**,
而用他们衍生出去的别名成为**衍生别名**。例如,`@foo` 就是根别名,
`@foo/bar/file.php` 是一个衍生别名。
你还可以用别名去定义新别名(根别名与衍生别名均可):
@ -34,10 +34,10 @@ Yii::setAlias('@bar', 'http://www.example.com');
Yii::setAlias('@foobar', '@foo/bar');
```
根别名通常在[引导](runtime-bootstrapping.md)阶段定义。比如你可以在
[入口脚本](structure-entry-scripts.md)里调用 [[Yii::setAlias()]]。为
了方便起见,[应用](structure-applications.md)提供了一个名为 `aliases`
可写属性,你可以在应用[配置](concept-configurations.md)中设置它,就像这样:
根别名通常在[引导](runtime-bootstrapping.md)阶段定义。
比如你可以在[入口脚本](structure-entry-scripts.md)里调用 [[Yii::setAlias()]]。为了方便起见,
[应用](structure-applications.md)提供了一个名为 `aliases` 可写属性,
你可以在应用[配置](concept-configurations.md)中设置它,就像这样:
```php
return [
@ -62,15 +62,15 @@ echo Yii::getAlias('@bar'); // 输出:http://www.example.com
echo Yii::getAlias('@foo/bar/file.php'); // 输出:/path/to/foo/bar/file.php
```
由衍生别名所解析出的文件路径和 URL 是通过替换掉衍生别名
中的根别名部分得到的。
由衍生别名所解析出的文件路径和 URL
是通过替换掉衍生别名中的根别名部分得到的。
> 注意:[[Yii::getAlias()]] 并不检查结果路径/URL 所指向的资源是否真实存在。
根别名可能也会包含斜杠 `/`[[Yii::getAlias()]]
足够智能到判断一个别名中的哪部分是根别名,因此
能正确解析文件路径/URL。例如:
根别名可能也会包含斜杠 `/`
[[Yii::getAlias()]] 足够智能到判断一个别名中的哪部分是根别名,因此能正确解析文件路径/URL。
例如:
```php
Yii::setAlias('@foo', '/path/to/foo');
@ -85,9 +85,9 @@ echo Yii::getAlias('@foo/bar/file.php'); // 输出:/path2/bar/file.php
使用别名 <span id="using-aliases"></span>
-------------
别名在 Yii 的很多地方都会被正确识别,无需调用 [[Yii::getAlias()]]
来把它们转换为路径/URL。例如,[[yii\caching\FileCache::cachePath]]
能同时接受文件路径或是指向文件路径的别名,
别名在 Yii 的很多地方都会被正确识别,
无需调用 [[Yii::getAlias()]] 来把它们转换为路径/URL。
例如,[[yii\caching\FileCache::cachePath]] 能同时接受文件路径或是指向文件路径的别名,
因为通过 `@` 前缀能区分它们。
```php
@ -106,15 +106,15 @@ $cache = new FileCache([
Yii 预定义了一系列别名来简化常用路径和 URL 的使用:
- `@yii`, `BaseYii.php` 文件所在的目录(也被称为框架安装目录)
- `@app`, 当前运行的应用 [[yii\base\Application::basePath|根路径(base path)]]
- `@runtime`, 当前运行的应用的 [[yii\base\Application::runtimePath|运行环境(runtime)路径]]. Defaults to `@app/runtime`.
- `@webroot`, the Web root directory of the currently running Web application. It is determined based on the directory
containing the [entry script](structure-entry-scripts.md).
- `@web`,the base URL of the currently running Web application. It has the same value as [[yii\web\Request::baseUrl]].
- `@vendor`,[[yii\base\Application::vendorPath|Composer 供应商目录]]. Defaults to `@app/vendor`.
- `@bower`, the root directory that contains [bower packages](http://bower.io/). Defaults to `@vendor/bower`.
- `@npm`, the root directory that contains [npm packages](https://www.npmjs.org/). Defaults to `@vendor/npm`.
- `@yii`,`BaseYii.php` 文件所在的目录(也被称为框架安装目录)
- `@app`,当前运行的应用 [[yii\base\Application::basePath|根路径(base path)]]。
- `@runtime`,当前运行的应用的 [[yii\base\Application::runtimePath|运行环境(runtime)路径]]。默认为 `@app/runtime`
- `@webroot`,当前运行的Web应用程序的Web根目录。
它是根据包含 [入口脚本](structure-entry-scripts.md) 的目录确定的。
- `@web`,当前运行的Web应用程序的 base URL。它的值与 [[yii\web\Request::baseUrl]] 相同。
- `@vendor`,[[yii\base\Application::vendorPath|Composer vendor 目录]]。
- `@bower`,包含 [bower 包](http://bower.io/) 的根目录。默认为 `@vendor/bower`
- `@npm`,包含 [npm 包](https://www.npmjs.org/) 的根目录。默认为 `@vendor/npm`
`@yii` 别名是在[入口脚本](structure-entry-scripts.md)里包含 `Yii.php` 文件时定义的,
其他的别名都是在[配置应用](concept-configurations.md)的时候,
@ -125,9 +125,9 @@ Yii 预定义了一系列别名来简化常用路径和 URL 的使用:
-----------------
每一个通过 Composer 安装的 [扩展](structure-extensions.md) 都自动添加了一个别名。
该别名会以该扩展在 `composer.json` 文件中所声明的根命名空间为名,且他直接代指该包的根目录。
例如,如果你安装有 `yiisoft/yii2-jui` 扩展,
会自动得到 `@yii/jui` 别名,它定义于[引导启动](runtime-bootstrapping.md)阶段:
该别名会以该扩展在 `composer.json` 文件中所声明的根命名空间为名,
且他直接代指该包的根目录。例如,如果你安装有 `yiisoft/yii2-jui` 扩展,会自动得到 `@yii/jui` 别名
它定义于[引导启动](runtime-bootstrapping.md)阶段:
```php
Yii::setAlias('@yii/jui', 'VendorPath/yiisoft/yii2-jui');

48
docs/guide-zh-CN/concept-autoloading.md

@ -2,12 +2,12 @@
=================
Yii 依靠[类自动加载机制](http://www.php.net/manual/en/language.oop5.autoload.php)来定位和包含所需的类文件。
它提供一个高性能且完美支持[PSR-4 标准](https://github.com/php-fig/fig-standards/blob/master/proposed/psr-4-autoloader/psr-4-autoloader.md)
它提供一个高性能且完美支持[PSR-4 标准](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md)
([中文汉化](https://github.com/hfcorriez/fig-standards/blob/zh_CN/%E6%8E%A5%E5%8F%97/PSR-4-autoloader.md))的自动加载器。
该自动加载器会在引入框架文件 `Yii.php` 时安装好。
> 注意:为了简化叙述,本篇文档中我们只会提及类的自动加载。
不过,要记得文中的描述同样也适用于接口和Trait(特质)的自动加载哦。
> Note: 为了简化叙述,本篇文档中我们只会提及类的自动加载。
不过,要记得文中的描述同样也适用于接口和Trait(特质)的自动加载哦。
使用 Yii 自动加载器 <span id="using-yii-autoloader"></span>
@ -27,9 +27,9 @@ $classFile = Yii::getAlias('@' . str_replace('\\', '/', $className) . '.php');
为了让该别名能被正确解析为文件路径,`@foo` 或 `@foo/bar`
中的一个必须是[根别名](concept-aliases.md#defining-aliases)。
当我们使用[基本应用模版](start-installation.md)时,可以把你的类放置在顶级命名空间 `app` 下,
这样它们就可以被 Yii 自动加载,而无需定义一个新的别名。
这是因为 `@app` 本身是一个[预定义别名](concept-aliases.md#predefined-aliases),且类似于 `app\components\MyClass` 这样的类名,
当我们使用[基本应用模版](start-installation.md)时,可以把你的类放置在顶级命名空间 `app` 下,这样它们就可以被 Yii 自动加载,
而无需定义一个新的别名。这是因为 `@app` 本身是一个[预定义别名](concept-aliases.md#predefined-aliases),
且类似于 `app\components\MyClass` 这样的类名,
基于我们刚才所提到的算法,可以正确解析出 `AppBasePath/components/MyClass.php` 路径。
在[高级应用模版](tutorial-advanced-app.md)里,每一逻辑层级会使用他自己的根别名。
@ -37,14 +37,16 @@ $classFile = Yii::getAlias('@' . str_replace('\\', '/', $className) . '.php');
因此,你可以把前端的类放在 `frontend` 命名空间,而后端的类放在 `backend`
这样这些类就可以被 Yii 自动加载了。
To add a custom namespace to the autoloader you need to define an alias for the base directory of the namespace using [[Yii::setAlias()]].
For example to load classes in the `foo` namespace that are located in the `path/to/foo` directory you will call `Yii::setAlias('@foo', 'path/to/foo')`.
类映射表(Class Map) <span id="class-map"></span>
---------
Yii 类自动加载器支持**类映射表**功能,该功能会建立一个从类的名字到类文件路径的映射。
当自动加载器加载一个文件时,他首先检查映射表里有没有该类。
如果有,对应的文件路径就直接加载了,省掉了进一步的检查。
这让类的自动加载变得超级快。事实上所有的 Yii 核心类都是这样加载的。
如果有,对应的文件路径就直接加载了,省掉了进一步的检查。这让类的自动加载变得超级快。
事实上所有的 Yii 核心类都是这样加载的。
你可以用 `Yii::$classMap` 方法向映射表中添加类,
@ -52,22 +54,22 @@ Yii 类自动加载器支持**类映射表**功能,该功能会建立一个从
Yii::$classMap['foo\bar\MyClass'] = 'path/to/MyClass.php';
```
[别名](concept-aliases.md)可以被用于指定类文件的路径。
你应该在[引导启动](runtime-bootstrapping.md)的过程中设置类映射表,这样映射表就可以在你使用具体类之前就准备好。
[别名](concept-aliases.md)可以被用于指定类文件的路径。你应该在[引导启动](runtime-bootstrapping.md)的过程中设置类映射表,
这样映射表就可以在你使用具体类之前就准备好。
用其他自动加载器 <span id="using-other-autoloaders"></span>
-----------------------
因为 Yii 完全支持 Composer 管理依赖包,
所以推荐你也同时安装 Composer 的自动加载器,如果你用了一些自带自动加载器的第三方类库,
因为 Yii 完全支持 Composer 管理依赖包,所以推荐你也同时安装 Composer 的自动加载器,
如果你用了一些自带自动加载器的第三方类库,
你应该也安装下它们。
当你同时使用其他自动加载器和 Yii 自动加载器时,应该在其他自动加载器安装成功**之后**,再包含 `Yii.php` 文件。
这将使 Yii 成为第一个响应任何类自动加载请求的自动加载器。
举例来说,以下代码提取自[基本应用模版](start-installation.md)的[入口脚本](structure-entry-scripts.md) 。
第一行安装了 Composer 的自动加载器,
第二行才是 Yii 的自动加载器:
当你同时使用其他自动加载器和 Yii 自动加载器时,应该在其他自动加载器安装成功**之后**,
再包含 `Yii.php` 文件。这将使 Yii 成为第一个响应任何类自动加载请求的自动加载器。
举例来说,以下代码提取自[基本应用模版](start-installation.md)的
[入口脚本](structure-entry-scripts.md) 。
一行安装了 Composer 的自动加载器,第二行才是 Yii 的自动加载器:
```php
require(__DIR__ . '/../vendor/autoload.php');
@ -75,18 +77,18 @@ require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
```
你也可以只使用 Composer 的自动加载,而不用 Yii 的自动加载。
不过这样做的话,类的加载效率会下降,且你必须遵循 Composer 所设定的规则,
从而让你的类满足可以被自动加载的要求。
不过这样做的话,类的加载效率会下降,
且你必须遵循 Composer 所设定的规则,从而让你的类满足可以被自动加载的要求。
> 补充:若你不想要使用 Yii 的自动加载器,你必须创建一个你自己版本的 `Yii.php` 文件,
并把它包含进你的[入口脚本](structure-entry-scripts.md)里。
> Info: 若你不想要使用 Yii 的自动加载器,你必须创建一个你自己版本的 `Yii.php` 文件,
并把它包含进你的[入口脚本](structure-entry-scripts.md)里。
自动加载扩展类 <span id="autoloading-extension-classes"></span>
-----------------------------
Yii 自动加载器支持自动加载[扩展](structure-extensions.md)的类。唯一的要求是它需要在 `composer.json`
文件里正确地定义 `autoload` 部分。请参考 [Composer 文档(英文)](https://getcomposer.org/doc/04-schema.md#autoload)
Yii 自动加载器支持自动加载[扩展](structure-extensions.md)的类。唯一的要求是它需要在 `composer.json` 文件里正确地定义 `autoload` 部分。
请参考 [Composer 文档(英文)](https://getcomposer.org/doc/04-schema.md#autoload)
([中文汉化](https://github.com/5-say/composer-doc-cn/blob/master/cn-introduction/04-schema.md#autoload)),来了解如何正确描述 `autoload` 的更多细节。
在你不使用 Yii 的自动加载器时,Composer 的自动加载器仍然可以帮你自动加载扩展内的类。

42
docs/guide-zh-CN/concept-behaviors.md

@ -4,9 +4,9 @@
行为是 [[yii\base\Behavior]] 或其子类的实例。
行为,也称为 [mixins](http://en.wikipedia.org/wiki/Mixin),
可以无须改变类继承关系即可增强一个已有的 [[yii\base\Component|组件]] 类功能。
当行为附加到组件后,它将“注入”它的方法和属性到组件,然后可以像访问组件内定义的方法和属性一样访问它们。
此外,行为通过组件能响应被触发的[事件](basic-events.md),
从而自定义或调整组件正常执行的代码。
当行为附加到组件后,它将“注入”它的方法和属性到组件,
然后可以像访问组件内定义的方法和属性一样访问它们。
此外,行为通过组件能响应被触发的[事件](basic-events.md),从而自定义或调整组件正常执行的代码。
定义行为
@ -197,8 +197,8 @@ $component->attachBehaviors([
使用行为,必须像前文描述的一样先把它附加到 [[yii\base\Component|component]] 类或其子类。一旦行为附加到组件,就可以直接使用它。
行为附加到组件后,可以通过组件访问一个行为的**公共**成员变量或 getter 和 setter 方法定义的
[属性](concept-properties.md):
行为附加到组件后,可以通过组件访问一个行为的**公共**成员变量
或 getter 和 setter 方法定义的[属性](concept-properties.md):
```php
// "prop1" 是定义在行为类的属性
@ -219,8 +219,8 @@ $component->foo();
如果两个行为都定义了一样的属性或方法,并且它们都附加到同一个组件,
那么**首先**附加上的行为在属性或方法被访问时有优先权。
附加行为到组件时的命名行为,
可以使用这个名称来访问行为对象,如下所示:
附加行为到组件时的命名行为,可以使用这个名称来访问行为对象,
如下所示:
```php
$behavior = $component->getBehavior('myBehavior');
@ -287,14 +287,14 @@ class User extends ActiveRecord
以上指定的行为数组:
* 当记录插入时,
行为将当前的 UNIX 时间戳赋值给 `created_at``updated_at` 属性;
* 当记录更新时,行为将当前的 UNIX 时间戳赋值给 `updated_at` 属性。
* 当记录插入时,行为将当前时间戳赋值给
`created_at``updated_at` 属性;
* 当记录更新时,行为将当前时间戳赋值给 `updated_at` 属性。
> Note: For the above implementation to work with MySQL database, please declare the columns(`created_at`, `updated_at`) as int(11) for being UNIX timestamp.
保存 `User` 对象,
将会发现它的 `created_at``updated_at` 属性自动填充了当前时间戳:
With that code in place, if you have a `User` object and try to save it, you will find its `created_at` and `updated_at` are automatically
filled with the current UNIX timestamp:
```php
$user = new User;
@ -303,7 +303,7 @@ $user->save();
echo $user->created_at; // 显示当前时间戳
```
[[yii\behaviors\TimestampBehavior|TimestampBehavior]] 行为还提供了一个有用的方法
[[yii\behaviors\TimestampBehavior|TimestampBehavior]] 行为还提供了一个有用的方法
[[yii\behaviors\TimestampBehavior::touch()|touch()]],
这个方法能将当前时间戳赋值给指定属性并保存到数据库:
@ -311,7 +311,7 @@ echo $user->created_at; // 显示当前时间戳
$user->touch('login_time');
```
Other behaviors
其它行为
---------------
There are several built-in and external behaviors available:
@ -326,7 +326,7 @@ There are several built-in and external behaviors available:
- [yii2tech\ar\position\PositionBehavior](https://github.com/yii2tech/ar-position) - allows managing records order in an
integer field by providing reordering methods.
Comparing Behaviors with Traits <span id="comparison-with-traits"></span>
比较行为与 Traits <span id="comparison-with-traits"></span>
----------------------
While behaviors are similar to [traits](http://www.php.net/traits) in that they both "inject" their
@ -334,13 +334,13 @@ properties and methods to the primary class, they differ in many aspects. As exp
both have pros and cons. They are more like complements to each other rather than alternatives.
### Reasons to Use Behaviors <span id="pros-for-behaviors"></span>
### 使用行为的原因 <span id="pros-for-behaviors"></span>
Behavior classes, like normal classes, support inheritance. Traits, on the other hand,
can be considered as language-supported copy and paste. They do not support inheritance.
行为类像普通类支持继承。另一方面,traits 可以视为 PHP 语言支持的复制粘贴功能,
它不支持继承。
Behaviors can be attached and detached to a component dynamically without requiring modification of the component class.
To use a trait, you must modify the code of the class using it.
行为无须修改组件类就可动态附加到组件或移除。
要使用 traits,必须修改使用它的类。
Behaviors are configurable while traits are not.
@ -352,7 +352,7 @@ Name conflicts caused by different traits requires manual resolution by renaming
properties or methods.
### Reasons to Use Traits <span id="pros-for-traits"></span>
### 使用 Traits 的原因 <span id="pros-for-traits"></span>
Traits are much more efficient than behaviors as behaviors are objects that take both time and memory.

27
docs/guide-zh-CN/concept-components.md

@ -26,10 +26,10 @@ echo DatePicker::widget([
这个小部件继承自 [[yii\base\Component]],它的各项属性改写起来会很容易。
正是因为组件功能的强大,他们比常规的对象(Object)稍微重量级一点,
因为他们要使用额外的内存和 CPU 时间来处理 [事件](concept-events.md) 和 [行为](concept-behaviors.md) 。
如果你不需要这两项功能,可以继承 [[yii\base\Object]] 而不是 [[yii\base\Component]]。
这样组件可以像普通 PHP 对象一样高效,
正是因为组件功能的强大,他们比常规的对象(Object)稍微重量级一点,因为他们要使用额外的内存和 CPU 时间来处理
[事件](concept-events.md) 和 [行为](concept-behaviors.md) 。
如果你不需要这两项功能,可以继承 [[yii\base\Object]]
而不是 [[yii\base\Component]]。这样组件可以像普通 PHP 对象一样高效,
同时还支持[属性(Property)](concept-properties.md)功能。
当继承 [[yii\base\Component]] 或 [[yii\base\Object]] 时,
@ -43,18 +43,20 @@ echo DatePicker::widget([
例子如下:
```php
<?php
namespace yii\components\MyClass;
use yii\base\Object;
use yii\base\BaseObject;
class MyClass extends Object
class MyClass extends BaseObject
{
public $prop1;
public $prop2;
public function __construct($param1, $param2, $config = [])
{
// ... 配置生效前的初始化过程
// ... initialization before configuration is applied
parent::__construct($config);
}
@ -63,7 +65,7 @@ class MyClass extends Object
{
parent::init();
// ... 配置生效后的初始化过程
// ... initialization after configuration is applied
}
}
```
@ -80,8 +82,8 @@ $component = \Yii::createObject([
], [1, 2]);
```
> 补充:尽管调用 [[Yii::createObject()]] 的方法看起来更加复杂,
> 但这主要因为它更加灵活强大,它是基于[依赖注入容器](concept-di-container.md)实现的。
> Info: 尽管调用 [[Yii::createObject()]] 的方法看起来更加复杂,但这主要因为它更加灵活强大
> 它是基于[依赖注入容器](concept-di-container.md)实现的。
[[yii\base\Object]] 类执行时的生命周期如下:
@ -91,5 +93,6 @@ $component = \Yii::createObject([
3. 在 [[yii\base\Object::init()|init()]] 方法内进行初始化后的收尾工作。你可以通过重写此方法,进行一些良品检验,属性的初始化之类的工作。
4. 对象方法调用。
前三步都是在对象的构造方法内发生的。
这意味着一旦你获得了一个对象实例,那么它就已经初始化就绪可供使用。
前三步都是在对象的构造方法内发生的。这意味着一旦你获得了一个对象实例,
那么它就已经初始化就绪可供使用。

102
docs/guide-zh-CN/concept-configurations.md

@ -1,7 +1,11 @@
配置
=============
在 Yii 中,创建新对象和初始化已存在对象时广泛使用配置。配置通常包含被创建对象的类名和一组将要赋值给对象[属性](concept-properties.md)的初始值。还可能包含一组将被附加到对象[事件](concept-events.md)上的句柄。和一组将被附加到对象上的[行为](concept-behaviors.md)。
在 Yii 中,创建新对象和初始化已存在对象时广泛使用配置。
配置通常包含被创建对象的类名和一组将要赋值给对象
[属性](concept-properties.md)的初始值。
还可能包含一组将被附加到对象[事件](concept-events.md)上的句柄。
和一组将被附加到对象上的[行为](concept-behaviors.md)。
以下代码中的配置被用来创建并初始化一个数据库连接:
@ -17,9 +21,12 @@ $config = [
$db = Yii::createObject($config);
```
[[Yii::createObject()]] 方法接受一个配置数组并根据数组中指定的类名创建对象。对象实例化后,剩余的参数被用来初始化对象的属性,事件处理和行为。
[[Yii::createObject()]] 方法接受一个配置数组并根据数组中指定的类名创建对象。
对象实例化后,剩余的参数被用来初始化对象的属性,
事件处理和行为。
对于已存在的对象,可以使用 [[Yii::configure()]] 方法根据配置去初始化其属性,就像这样:
对于已存在的对象,可以使用 [[Yii::configure()]] 方法根据配置去初始化其属性,
就像这样:
```php
Yii::configure($object, $config);
@ -44,10 +51,15 @@ Yii::configure($object, $config);
其中
* `class` 元素指定了将要创建的对象的完全限定类名。
* `propertyName` 元素指定了对象属性的初始值。键名是属性名,值是该属性对应的初始值。只有公共成员变量以及通过 getter/setter 定义的[属性](concept-properties.md)可以被配置。
* `on eventName` 元素指定了附加到对象[事件](concept-events.md)上的句柄是什么。请注意,数组的键名由 `on ` 前缀加事件名组成。请参考[事件](concept-events.md)章节了解事件句柄格式。
* `as behaviorName` 元素指定了附加到对象的[行为](concept-behaviors.md)。请注意,数组的键名由 `as ` 前缀加行为名组成。`$behaviorConfig`
值表示创建行为的配置信息,格式与我们之前描述的配置格式一样。
* `propertyName` 元素指定了对象属性的初始值。键名是属性名,值是该属性对应的初始值。
只有公共成员变量以及通过 getter/setter 定义的
[属性](concept-properties.md)可以被配置。
* `on eventName` 元素指定了附加到对象[事件](concept-events.md)上的句柄是什么。
请注意,数组的键名由 `on ` 前缀加事件名组成。
请参考[事件](concept-events.md)章节了解事件句柄格式。
* `as behaviorName` 元素指定了附加到对象的[行为](concept-behaviors.md)。
请注意,数组的键名由 `as ` 前缀加行为名组成。`$behaviorConfig`
值表示创建行为的配置信息,格式与我们之前描述的配置格式一样。
下面是一个配置了初始化属性值,事件句柄和行为的示例:
@ -68,12 +80,18 @@ Yii::configure($object, $config);
## 使用配置
Yii 中的配置可以用在很多场景。本章开头我们展示了如何使用 [[Yii::creatObject()]] 根据配置信息创建对象。本小节将介绍配置的两种主要用法 —— 配置应用与配置小部件。
Yii 中的配置可以用在很多场景。本章开头我们展示了如何使用 [[Yii::creatObject()]]
根据配置信息创建对象。本小节将介绍配置的两种
主要用法 —— 配置应用与配置小部件。
### 应用的配置 <span id="application-configurations"></span>
[应用](structure-applications.md)的配置可能是最复杂的配置之一。因为 [[yii\web\Application|application]] 类拥有很多可配置的属性和事件。更重要的是它的 [[yii\web\Application::components|components]] 属性可以接收配置数组并通过应用注册为组件。以下是一个针对[基础应用模板](start-installation.md)的应用配置概要:
[应用](structure-applications.md)的配置可能是最复杂的配置之一。
因为 [[yii\web\Application|application]] 类拥有很多可配置的属性和事件。
更重要的是它的 [[yii\web\Application::components|components]]
属性可以接收配置数组并通过应用注册为组件。
以下是一个针对[基础应用模板](start-installation.md)的应用配置概要:
```php
$config = [
@ -107,18 +125,44 @@ $config = [
];
```
配置中没有 `class` 键的原因是这段配置应用在下面的入口脚本中,类名已经指定了。
配置中没有 `class` 键的原因是这段配置应用在下面的入口脚本中,
类名已经指定了。
```php
(new yii\web\Application($config))->run();
```
更多关于应用 `components` 属性配置的信息可以查阅[应用](structure-applications.md)以及[服务定位器](concept-service-locator.md)章节。
更多关于应用 `components` 属性配置的信息可以查阅[应用](structure-applications.md)
以及[服务定位器](concept-service-locator.md)章节。
Since version 2.0.11, the application configuration supports [Dependency Injection Container](concept-di-container.md)
configuration using `container` property. For example:
```php
$config = [
'id' => 'basic',
'basePath' => dirname(__DIR__),
'extensions' => require __DIR__ . '/../vendor/yiisoft/extensions.php',
'container' => [
'definitions' => [
'yii\widgets\LinkPager' => ['maxButtonCount' => 5]
],
'singletons' => [
// Dependency Injection Container singletons configuration
]
]
];
```
To know more about the possible values of `definitions` and `singletons` configuration arrays and real-life examples,
please read [Advanced Practical Usage](concept-di-container.md#advanced-practical-usage) subsection of the
[Dependency Injection Container](concept-di-container.md) article.
### 小部件的配置 <span id="widget-configurations"></span>
使用[小部件](structure-widgets.md)时,常常需要配置以便自定义其属性。 [[yii\base\Widget::widget()]] 和 [[yii\base\Widget::begin()]] 方法都可以用来创建小部件。它们可以接受配置数组:
使用[小部件](structure-widgets.md)时,常常需要配置以便自定义其属性。
[[yii\base\Widget::widget()]] 和 [[yii\base\Widget::begin()]] 方法都可以用来创建小部件。
它们可以接受配置数组:
```php
use yii\widgets\Menu;
@ -133,14 +177,17 @@ echo Menu::widget([
]);
```
上述代码创建了一个小部件 `Menu` 并将其 `activateItems` 属性初始化为 false。`item` 属性也配置成了将要显示的菜单条目。
上述代码创建了一个小部件 `Menu` 并将其 `activateItems` 属性初始化为 false。
`item` 属性也配置成了将要显示的菜单条目。
请注意,代码中已经给出了类名 `yii\widgets\Menu`,配置数组**不应该**再包含 `class` 键。
## 配置文件 <span id="configuration-files"></span>
当配置的内容十分复杂,通用做法是将其存储在一或多个 PHP 文件中,这些文件被称为**配置文件**。一个配置文件返回的是 PHP 数组。例如,像这样把应用配置信息存储在名为 `web.php` 的文件中:
当配置的内容十分复杂,通用做法是将其存储在一或多个 PHP 文件中,
这些文件被称为**配置文件**。一个配置文件返回的是 PHP 数组。
例如,像这样把应用配置信息存储在名为 `web.php` 的文件中:
```php
return [
@ -151,7 +198,8 @@ return [
];
```
鉴于 `components` 配置也很复杂,上述代码把它们存储在单独的 `components.php` 文件中,并且包含在 `web.php` 里。`components.php` 的内容如下:
鉴于 `components` 配置也很复杂,上述代码把它们存储在单独的 `components.php` 文件中,并且包含在 `web.php` 里。
`components.php` 的内容如下:
```php
return [
@ -190,9 +238,13 @@ $config = require('path/to/web.php');
## 默认配置 <span id="default-configurations"></span>
[[Yii::createObject()]] 方法基于[依赖注入容器](concept-di-container.md)实现。使用 [[Yii::creatObject()]] 创建对象时,可以附加一系列**默认配置**到指定类的任何实例。默认配置还可以在[入口脚本](runtime-bootstrapping.md)中调用 `Yii::$container->set()` 来定义。
[[Yii::createObject()]] 方法基于[依赖注入容器](concept-di-container.md)实现。
使用 [[Yii::creatObject()]] 创建对象时,可以附加一系列**默认配置**到指定类的任何实例。
默认配置还可以在[入口脚本](runtime-bootstrapping.md)
中调用 `Yii::$container->set()` 来定义。
例如,如果你想自定义 [[yii\widgets\LinkPager]] 小部件,以便让分页器最多只显示 5 个翻页按钮(默认是 10 个),你可以用下述代码实现:
例如,如果你想自定义 [[yii\widgets\LinkPager]] 小部件,以便让分页器最多只显示 5 个翻页按钮(默认是 10 个),
你可以用下述代码实现:
```php
\Yii::$container->set('yii\widgets\LinkPager', [
@ -200,12 +252,17 @@ $config = require('path/to/web.php');
]);
```
不使用默认配置的话,你就得在任何使用分页器的地方,都配置 `maxButtonCount` 的值。
不使用默认配置的话,你就得在任何使用分页器的地方,
都配置 `maxButtonCount` 的值。
## 环境常量 <span id="environment-constants"></span>
配置经常要随着应用运行的不同环境更改。例如在开发环境中,你可能使用名为 `mydb_dev` 的数据库,而生产环境则使用 `mydb_prod` 数据库。为了便于切换使用环境,Yii 提供了一个定义在入口脚本中的 `YII_ENV` 常量。如下:
配置经常要随着应用运行的不同环境更改。例如在开发环境中,
你可能使用名为 `mydb_dev` 的数据库,
而生产环境则使用 `mydb_prod` 数据库。
为了便于切换使用环境,Yii 提供了一个定义在入口脚本中的 `YII_ENV` 常量。
如下:
```php
defined('YII_ENV') or define('YII_ENV', 'dev');
@ -213,11 +270,14 @@ defined('YII_ENV') or define('YII_ENV', 'dev');
你可以把 `YII_ENV` 定义成以下任何一种值:
- `prod`:生产环境。常量 `YII_ENV_PROD` 将被看作 true。如果你没修改过,这就是 `YII_ENV` 的默认值。
- `prod`:生产环境。常量 `YII_ENV_PROD` 将被看作 true。
如果你没修改过,这就是 `YII_ENV` 的默认值。
- `dev`:开发环境。常量 `YII_ENV_DEV` 将被看作 true。
- `test`:测试环境。常量 `YII_ENV_TEST` 将被看作 true。
有了这些环境常量,你就可以根据当下应用运行环境的不同,进行差异化配置。例如,应用可以包含下述代码只在开发环境中开启[调试工具](tool-debugger.md)。
有了这些环境常量,你就可以根据当下应用运行环境的不同,进行差异化配置。
例如,应用可以包含下述代码只在开发环境中开启
[调试工具](tool-debugger.md)。
```php
$config = [...];

299
docs/guide-zh-CN/concept-di-container.md

@ -1,22 +1,29 @@
依赖注入容器
==============================
依赖注入(Dependency Injection,DI)容器就是一个对象,它知道怎样初始化并配置对象及其依赖的所有对象。[Martin 的文章](http://martinfowler.com/articles/injection.html) 已经解释了 DI 容器为什么很有用。这里我们主要讲解 Yii 提供的 DI 容器的使用方法。
依赖注入(Dependency Injection,DI)容器就是一个对象,它知道怎样初始化并配置对象及其依赖的所有对象。
[Martin 的文章](http://martinfowler.com/articles/injection.html) 已经解释了 DI 容器为什么很有用。
这里我们主要讲解 Yii 提供的 DI 容器的使用方法。
依赖注入 <span id="dependency-injection"></span>
--------------------
Yii 通过 [[yii\di\Container]] 类提供 DI 容器特性。它支持如下几种类型的依赖注入:
Yii 通过 [[yii\di\Container]] 类提供 DI 容器特性。
它支持如下几种类型的依赖注入:
* 构造方法注入;
* Method injection;
* Setter 和属性注入;
* PHP 回调注入.
### 构造方法注入 <span id="constructor-injection"></span>
在参数类型提示的帮助下,DI 容器实现了构造方法注入。当容器被用于创建一个新对象时,类型提示会告诉它要依赖什么类或接口。容器会尝试获取它所依赖的类或接口的实例,然后通过构造器将其注入新的对象。例如:
在参数类型提示的帮助下,DI 容器实现了构造方法注入。当容器被用于创建一个新对象时,
类型提示会告诉它要依赖什么类或接口。
容器会尝试获取它所依赖的类或接口的实例,
然后通过构造器将其注入新的对象。例如:
```php
class Foo
@ -33,9 +40,42 @@ $foo = new Foo($bar);
```
### Method Injection <span id="method-injection"></span>
Usually the dependencies of a class are passed to the constructor and are available inside of the class during the whole lifecycle.
With Method Injection it is possible to provide a dependency that is only needed by a single method of the class
and passing it to the constructor may not be possible or may cause too much overhead in the majority of use cases.
A class method can be defined like the `doSomething()` method in the following example:
```php
class MyClass extends \yii\base\Component
{
public function __construct(/*Some lightweight dependencies here*/, $config = [])
{
// ...
}
public function doSomething($param1, \my\heavy\Dependency $something)
{
// do something with $something
}
}
```
You may call that method either by passing an instance of `\my\heavy\Dependency` yourself or using [[yii\di\Container::invoke()]] like the following:
```php
$obj = new MyClass(/*...*/);
Yii::$container->invoke([$obj, 'doSomething'], ['param1' => 42]); // $something will be provided by the DI container
```
### Setter 和属性注入 <span id="setter-and-property-injection"></span>
Setter 和属性注入是通过[配置](concept-configurations.md)提供支持的。当注册一个依赖或创建一个新对象时,你可以提供一个配置,该配置会提供给容器用于通过相应的 Setter 或属性注入依赖。例如:
Setter 和属性注入是通过[配置](concept-configurations.md)提供支持的。
当注册一个依赖或创建一个新对象时,你可以提供一个配置,
该配置会提供给容器用于通过相应的 Setter 或属性注入依赖。
例如:
```php
use yii\base\Object;
@ -63,24 +103,56 @@ $container->get('Foo', [], [
]);
```
> Info: The [[yii\di\Container::get()]] method takes its third parameter as a configuration array that should
be applied to the object being created. If the class implements the [[yii\base\Configurable]] interface (e.g.
[[yii\base\BaseObject]]), the configuration array will be passed as the last parameter to the class constructor;
otherwise, the configuration will be applied *after* the object is created.
### PHP 回调注入 <span id="php-callable-injection"></span>
这种情况下,容器将使用一个注册过的 PHP 回调创建一个类的新实例。回调负责解决依赖并将其恰当地注入新创建的对象。例如:
In this case, the container will use a registered PHP callable to build new instances of a class.
Each time when [[yii\di\Container::get()]] is called, the corresponding callable will be invoked.
The callable is responsible to resolve the dependencies and inject them appropriately to the newly
created objects. For example,
```php
$container->set('Foo', function () {
return new Foo(new Bar);
$foo = new Foo(new Bar);
// ... other initializations ...
return $foo;
});
$foo = $container->get('Foo');
```
To hide the complex logic for building a new object, you may use a static class method as callable. For example,
```php
class FooBuilder
{
public static function build()
{
$foo = new Foo(new Bar);
// ... other initializations ...
return $foo;
}
}
$container->set('Foo', ['app\helper\FooBuilder', 'build']);
$foo = $container->get('Foo');
```
By doing so, the person who wants to configure the `Foo` class no longer needs to be aware of how it is built.
注册依赖关系 <span id="registering-dependencies"></span>
------------------------
可以用 [[yii\di\Container::set()]] 注册依赖关系。注册会用到一个依赖关系名称和一个依赖关系的定义。依赖关系名称可以是一个类名,一个接口名或一个别名。依赖关系的定义可以是一个类名,一个配置数组,或者一个 PHP 回调。
可以用 [[yii\di\Container::set()]] 注册依赖关系。注册会用到一个依赖关系名称和一个依赖关系的定义。
依赖关系名称可以是一个类名,一个接口名或一个别名。
依赖关系的定义可以是一个类名,一个配置数组,或者一个 PHP 回调。
```php
$container = new \yii\di\Container;
@ -89,7 +161,8 @@ $container = new \yii\di\Container;
$container->set('yii\db\Connection');
// 注册一个接口
// 当一个类依赖这个接口时,相应的类会被初始化作为依赖对象。
// 当一个类依赖这个接口时,
//相应的类会被初始化作为依赖对象。
$container->set('yii\mail\MailInterface', 'yii\swiftmailer\Mailer');
// 注册一个别名。
@ -126,9 +199,12 @@ $container->set('db', function ($container, $params, $config) {
$container->set('pageCache', new FileCache);
```
> Tip: 如果依赖关系名称和依赖关系的定义相同,则不需要通过 DI 容器注册该依赖关系。
> Tip: 如果依赖关系名称和依赖关系的定义相同,
则不需要通过 DI 容器注册该依赖关系。
通过 `set()` 注册的依赖关系,在每次使用时都会产生一个新实例。可以使用 [[yii\di\Container::setSingleton()]] 注册一个单例的依赖关系:
通过 `set()` 注册的依赖关系,在每次使用时都会产生一个新实例。
可以使用 [[yii\di\Container::setSingleton()]]
注册一个单例的依赖关系:
```php
$container->setSingleton('yii\db\Connection', [
@ -143,9 +219,18 @@ $container->setSingleton('yii\db\Connection', [
解决依赖关系 <span id="resolving-dependencies"></span>
----------------------
注册依赖关系后,就可以使用 DI 容器创建新对象了。容器会自动解决依赖关系,将依赖实例化并注入新创建的对象。依赖关系的解决是递归的,如果一个依赖关系中还有其他依赖关系,则这些依赖关系都会被自动解决。
注册依赖关系后,就可以使用 DI 容器创建新对象了。容器会自动解决依赖关系,
将依赖实例化并注入新创建的对象。依赖关系的解决是递归的,
如果一个依赖关系中还有其他依赖关系,
则这些依赖关系都会被自动解决。
可以使用 [[yii\di\Container::get()]] 创建新的对象。
该方法接收一个依赖关系名称,它可以是一个类名,
一个接口名或一个别名。依赖关系名或许是通过 `set()``setSingleton()` 注册的。
你可以随意地提供一个类的构造器参数列表和一个
[configuration](concept-configurations.md) 用于配置新创建的对象。
可以使用 [[yii\di\Container::get()]] 创建新的对象。该方法接收一个依赖关系名称,它可以是一个类名,一个接口名或一个别名。依赖关系名或许是通过 `set()``setSingleton()` 注册的。你可以随意地提供一个类的构造器参数列表和一个[configuration](concept-configurations.md) 用于配置新创建的对象。例如:
例如:
```php
// "db" 是前面定义过的一个别名
@ -155,9 +240,15 @@ $db = $container->get('db');
$engine = $container->get('app\components\SearchEngine', [$apiKey], ['type' => 1]);
```
代码背后,DI 容器做了比创建对象多的多的工作。容器首先将检查类的构造方法,找出依赖的类或接口名,然后自动递归解决这些依赖关系。
代码背后,DI 容器做了比创建对象多的多的工作。
容器首先将检查类的构造方法,找出依赖的类或接口名,
然后自动递归解决这些依赖关系。
如下代码展示了一个更复杂的示例。`UserLister` 类依赖一个实现了 `UserFinderInterface` 接口的对象;`UserFinder` 类实现了这个接口,并依赖于一个 `Connection` 对象。所有这些依赖关系都是通过类构造器参数的类型提示定义的。通过属性依赖关系的注册,DI 容器可以自动解决这些依赖关系并能通过一个简单的 `get('userLister')` 调用创建一个新的 `UserLister` 实例。
如下代码展示了一个更复杂的示例。`UserLister` 类依赖一个实现了 `UserFinderInterface` 接口的对象;
`UserFinder` 类实现了这个接口,并依赖于一个 `Connection` 对象。
所有这些依赖关系都是通过类构造器参数的类型提示定义的。
通过属性依赖关系的注册,DI 容器可以自动解决这些依赖关系并能通过一个
简单的 `get('userLister')` 调用创建一个新的 `UserLister` 实例。
```php
namespace app\models;
@ -219,8 +310,12 @@ $lister = new UserLister($finder);
实践中的运用 <span id="practical-usage"></span>
---------------
当在应用程序的[入口脚本](structure-entry-scripts.md)中引入 `Yii.php` 文件时,Yii 就创建了一个 DI 容器。这个 DI 容器可以通过 [[Yii::$container]] 访问。当调用 [[Yii::createObject()]] 时,此方法实际上会调用这个容器的 [[yii\di\Container::get()|get()]] 方法创建新对象。如上所述,DI 容器会自动解决依赖关系(如果有)并将其注入新创建的对象中。因为 Yii 在其多数核心代码中都使用了
[[Yii::createObject()]] 创建新对象,所以你可以通过 [[Yii::$container]] 全局性地自定义这些对象。
当在应用程序的[入口脚本](structure-entry-scripts.md)中引入 `Yii.php` 文件时,
Yii 就创建了一个 DI 容器。这个 DI 容器可以通过 [[Yii::$container]] 访问。
当调用 [[Yii::createObject()]] 时,此方法实际上会调用这个容器的 [[yii\di\Container::get()|get()]] 方法创建新对象。
如上所述,DI 容器会自动解决依赖关系(如果有)并将其注入新创建的对象中。
因为 Yii 在其多数核心代码中都使用了[[Yii::createObject()]] 创建新对象,
所以你可以通过 [[Yii::$container]] 全局性地自定义这些对象。
例如,你可以全局性自定义 [[yii\widgets\LinkPager]] 中分页按钮的默认数量:
@ -228,7 +323,8 @@ $lister = new UserLister($finder);
\Yii::$container->set('yii\widgets\LinkPager', ['maxButtonCount' => 5]);
```
这样如果你通过如下代码在一个视图里使用这个挂件,它的 `maxButtonCount` 属性就会被初始化为 5 而不是类中定义的默认值 10。
这样如果你通过如下代码在一个视图里使用这个挂件,
它的 `maxButtonCount` 属性就会被初始化为 5 而不是类中定义的默认值 10。
```php
echo \yii\widgets\LinkPager::widget();
@ -240,7 +336,13 @@ echo \yii\widgets\LinkPager::widget();
echo \yii\widgets\LinkPager::widget(['maxButtonCount' => 20]);
```
另一个例子是借用 DI 容器中自动构造方法注入带来的好处。假设你的控制器类依赖一些其他对象,例如一个旅馆预订服务。你可以通过一个构造器参数声明依赖关系,然后让 DI 容器帮你自动解决这个依赖关系。
> Note: Properties given in the widget call will always override the definition in the DI container.
> Even if you specify an array, e.g. `'options' => ['id' => 'mypager']` these will not be merged
> with other options but replace them.
另一个例子是借用 DI 容器中自动构造方法注入带来的好处。
假设你的控制器类依赖一些其他对象,例如一个旅馆预订服务。
你可以通过一个构造器参数声明依赖关系,然后让 DI 容器帮你自动解决这个依赖关系。
```php
namespace app\controllers;
@ -260,28 +362,175 @@ class HotelController extends Controller
}
```
如果你从浏览器中访问这个控制器,你将看到一个报错信息,提醒你 `BookingInterface` 无法被实例化。这是因为你需要告诉 DI 容器怎样处理这个依赖关系。
如果你从浏览器中访问这个控制器,你将看到一个报错信息,提醒你 `BookingInterface` 无法被实例化。
这是因为你需要告诉 DI 容器怎样处理这个依赖关系。
```php
\Yii::$container->set('app\components\BookingInterface', 'app\components\BookingService');
```
现在如果你再次访问这个控制器,一个 `app\components\BookingService` 的实例就会被创建并被作为第三个参数注入到控制器的构造器中。
现在如果你再次访问这个控制器,一个 `app\components\BookingService`
的实例就会被创建并被作为第三个参数注入到控制器的构造器中。
Advanced Practical Usage <span id="advanced-practical-usage"></span>
---------------
Say we work on API application and have:
- `app\components\Request` class that extends `yii\web\Request` and provides additional functionality
- `app\components\Response` class that extends `yii\web\Response` and should have `format` property
set to `json` on creation
- `app\storage\FileStorage` and `app\storage\DocumentsReader` classes that implement some logic on
working with documents that are located in some file storage:
```php
class FileStorage
{
public function __construct($root) {
// whatever
}
}
class DocumentsReader
{
public function __construct(FileStorage $fs) {
// whatever
}
}
```
It is possible to configure multiple definitions at once, passing configuration array to
[[yii\di\Container::setDefinitions()|setDefinitions()]] or [[yii\di\Container::setSingletons()|setSingletons()]] method.
Iterating over the configuration array, the methods will call [[yii\di\Container::set()|set()]]
or [[yii\di\Container::setSingleton()|setSingleton()]] respectively for each item.
The configuration array format is:
- `key`: class name, interface name or alias name. The key will be passed to the
[[yii\di\Container::set()|set()]] method as a first argument `$class`.
- `value`: the definition associated with `$class`. Possible values are described in [[yii\di\Container::set()|set()]]
documentation for the `$definition` parameter. Will be passed to the [[set()]] method as
the second argument `$definition`.
For example, let's configure our container to follow the aforementioned requirements:
```php
$container->setDefinitions([
'yii\web\Request' => 'app\components\Request',
'yii\web\Response' => [
'class' => 'app\components\Response',
'format' => 'json'
],
'app\storage\DocumentsReader' => function () {
$fs = new app\storage\FileStorage('/var/tempfiles');
return new app\storage\DocumentsReader($fs);
}
]);
$reader = $container->get('app\storage\DocumentsReader);
// Will create DocumentReader object with its dependencies as described in the config
```
> Tip: Container may be configured in declarative style using application configuration since version 2.0.11.
Check out the [Application Configurations](concept-configurations.md#application-configurations) subsection of
the [Configurations](concept-configurations.md) guide article.
Everything works, but in case we need to create `DocumentWriter` class,
we shall copy-paste the line that creates `FileStorage` object, that is not the smartest way, obviously.
As described in the [Resolving Dependencies](#resolving-dependencies) subsection, [[yii\di\Container::set()|set()]]
and [[yii\di\Container::setSingleton()|setSingleton()]] can optionally take dependency's constructor parameters as
a third argument. To set the constructor parameters, you may use the following configuration array format:
- `key`: class name, interface name or alias name. The key will be passed to the
[[yii\di\Container::set()|set()]] method as a first argument `$class`.
- `value`: array of two elements. The first element will be passed to the [[yii\di\Container::set()|set()]] method as the
second argument `$definition`, the second one — as `$params`.
Let's modify our example:
```php
$container->setDefinitions([
'tempFileStorage' => [ // we've created an alias for convenience
['class' => 'app\storage\FileStorage'],
['/var/tempfiles'] // could be extracted from some config files
],
'app\storage\DocumentsReader' => [
['class' => 'app\storage\DocumentsReader'],
[Instance::of('tempFileStorage')]
],
'app\storage\DocumentsWriter' => [
['class' => 'app\storage\DocumentsWriter'],
[Instance::of('tempFileStorage')]
]
]);
$reader = $container->get('app\storage\DocumentsReader);
// Will behave exactly the same as in the previous example.
```
You might notice `Instance::of('tempFileStorage')` notation. It means, that the [[yii\di\Container|Container]]
will implicitly provide a dependency registered with the name of `tempFileStorage` and pass it as the first argument
of `app\storage\DocumentsWriter` constructor.
> Note: [[yii\di\Container::setDefinitions()|setDefinitions()]] and [[yii\di\Container::setSingletons()|setSingletons()]]
methods are available since version 2.0.11.
Another step on configuration optimization is to register some dependencies as singletons.
A dependency registered via [[yii\di\Container::set()|set()]] will be instantiated each time it is needed.
Some classes do not change the state during runtime, therefore they may be registered as singletons
in order to increase the application performance.
A good example could be `app\storage\FileStorage` class, that executes some operations on file system with a simple
API (e.g. `$fs->read()`, `$fs->write()`). These operations do not change the internal class state, so we can
create its instance once and use it multiple times.
```php
$container->setSingletons([
'tempFileStorage' => [
['class' => 'app\storage\FileStorage'],
['/var/tempfiles']
],
]);
$container->setDefinitions([
'app\storage\DocumentsReader' => [
['class' => 'app\storage\DocumentsReader'],
[Instance::of('tempFileStorage')]
],
'app\storage\DocumentsWriter' => [
['class' => 'app\storage\DocumentsWriter'],
[Instance::of('tempFileStorage')]
]
]);
$reader = $container->get('app\storage\DocumentsReader');
什么时候注册依赖关系 <span id="when-to-register-dependencies"></span>
-----------------------------
由于依赖关系在创建新对象时需要解决,因此它们的注册应该尽早完成。如下是推荐的实践:
由于依赖关系在创建新对象时需要解决,因此它们的注册应该尽早完成。
如下是推荐的实践:
* 如果你是一个应用程序的开发者,你可以在应用程序的[入口脚本](structure-entry-scripts.md)或者被入口脚本引入的脚本中注册依赖关系。
* 如果你是一个可再分发[扩展](structure-extensions.md)的开发者,你可以将依赖关系注册到扩展的引导类中。
* 如果你是一个应用程序的开发者,
你可以在应用程序的[入口脚本](structure-entry-scripts.md)
或者被入口脚本引入的脚本中注册依赖关系。
* 如果你是一个可再分发[扩展](structure-extensions.md)的开发者,
你可以将依赖关系注册到扩展的引导类中。
总结 <span id="summary"></span>
-------
依赖注入和[服务定位器](concept-service-locator.md)都是流行的设计模式,它们使你可以用充分解耦且更利于测试的风格构建软件。强烈推荐你阅读 [Martin 的文章](http://martinfowler.com/articles/injection.html) ,对依赖注入和服务定位器有个更深入的理解。
依赖注入和[服务定位器](concept-service-locator.md)都是流行的设计模式,
它们使你可以用充分解耦且更利于测试的风格构建软件。
强烈推荐你阅读 [Martin 的文章](http://martinfowler.com/articles/injection.html) ,
对依赖注入和服务定位器有个更深入的理解。
Yii 在依赖住入(DI)容器之上实现了它的[服务定位器](concept-service-locator.md)。
当一个服务定位器尝试创建一个新的对象实例时,它会把调用转发到 DI 容器。
后者将会像前文所述那样自动解决依赖关系。
Yii 在依赖住入(DI)容器之上实现了它的[服务定位器](concept-service-locator.md)。当一个服务定位器尝试创建一个新的对象实例时,它会把调用转发到 DI 容器。后者将会像前文所述那样自动解决依赖关系。

169
docs/guide-zh-CN/concept-events.md

@ -1,15 +1,20 @@
事件
======
事件可以将自定义代码“注入”到现有代码中的特定执行点。附加自定义代码到某个事件,当这个事件被触发时,这些代码就会自动执行。例如,邮件程序对象成功发出消息时可触发 `messageSent` 事件。如想追踪成功发送的消息,可以附加相应追踪代码到 `messageSent` 事件。
事件可以将自定义代码“注入”到现有代码中的特定执行点。
附加自定义代码到某个事件,当这个事件被触发时,这些代码就会自动执行。
例如,邮件程序对象成功发出消息时可触发 `messageSent` 事件。
如想追踪成功发送的消息,可以附加相应追踪代码到 `messageSent` 事件。
Yii 引入了名为 [[yii\base\Component]] 的基类以支持事件。如果一个类需要触发事件就应该继承 [[yii\base\Component]] 或其子类。
Yii 引入了名为 [[yii\base\Component]] 的基类以支持事件。
如果一个类需要触发事件就应该继承 [[yii\base\Component]] 或其子类。
事件处理器(Event Handlers)
事件处理器 <span id="event-handlers"></span>
--------------
事件处理器是一个[PHP 回调函数](http://www.php.net/manual/en/language.types.callable.php),当它所附加到的事件被触发时它就会执行。可以使用以下回调函数之一:
事件处理器是一个[PHP 回调函数](http://www.php.net/manual/en/language.types.callable.php),
当它所附加到的事件被触发时它就会执行。可以使用以下回调函数之一:
- 字符串形式指定的 PHP 全局函数,如 `'trim'`
- 对象名和方法名数组形式指定的对象方法,如 `[$object, $method]`
@ -54,21 +59,29 @@ $foo->on(Foo::EVENT_HELLO, function ($event) {
});
```
附加事件处理器时可以提供额外数据作为 [[yii\base\Component::on()]] 方法的第三个参数。数据在事件被触发和处理器被调用时能被处理器使用。如:
You may also attach event handlers through [configurations](concept-configurations.md). For more details, please
refer to the [Configurations](concept-configurations.md#configuration-format) section.
附加事件处理器时可以提供额外数据作为 [[yii\base\Component::on()]] 方法的第三个参数。
数据在事件被触发和处理器被调用时能被处理器使用。如:
```php
// 当事件被触发时以下代码显示 "abc"
// 因为 $event->data 包括被传递到 "on" 方法的数据
$foo->on(Foo::EVENT_HELLO, function ($event) {
$foo->on(Foo::EVENT_HELLO, 'function_name', 'abc');
function function_name($event) {
echo $event->data;
}, 'abc');
}
```
事件处理器顺序
-----------------
可以附加一个或多个处理器到一个事件。当事件被触发,已附加的处理器将按附加次序依次调用。如果某个处理器需要停止其后的处理器调用,可以设置 `$event` 参数的 [[yii\base\Event::handled]] 属性为真,如下:
可以附加一个或多个处理器到一个事件。当事件被触发,已附加的处理器将按附加次序依次调用。
如果某个处理器需要停止其后的处理器调用,可以设置 `$event` 参数的 [[yii\base\Event::handled]] 属性为真,
如下:
```php
$foo->on(Foo::EVENT_HELLO, function ($event) {
@ -76,7 +89,9 @@ $foo->on(Foo::EVENT_HELLO, function ($event) {
});
```
默认新附加的事件处理器排在已存在处理器队列的最后。因此,这个处理器将在事件被触发时最后一个调用。在处理器队列最前面插入新处理器将使该处理器最先调用,可以传递第四个参数 `$append` 为假并调用 [[yii\base\Component::on()]] 方法实现:
默认新附加的事件处理器排在已存在处理器队列的最后。
因此,这个处理器将在事件被触发时最后一个调用。
在处理器队列最前面插入新处理器将使该处理器最先调用,可以传递第四个参数 `$append` 为假并调用 [[yii\base\Component::on()]] 方法实现:
```php
$foo->on(Foo::EVENT_HELLO, function ($event) {
@ -84,11 +99,11 @@ $foo->on(Foo::EVENT_HELLO, function ($event) {
}, $data, false);
```
触发事件
触发事件 <span id="triggering-events"></span>
----------
事件通过调用 [[yii\base\Component::trigger()]] 方法触发,此方法须传递**事件名**,还可以传递一个事件对象,用来传递参数到事件处理器。如:
事件通过调用 [[yii\base\Component::trigger()]] 方法触发,此方法须传递**事件名**,
还可以传递一个事件对象,用来传递参数到事件处理器。如:
```php
namespace app\components;
@ -109,9 +124,15 @@ class Foo extends Component
以上代码当调用 `bar()` ,它将触发名为 `hello` 的事件。
> 提示:推荐使用类常量来表示事件名。上例中,常量 `EVENT_HELLO` 用来表示 `hello` 。这有两个好处。第一,它可以防止拼写错误并支持 IDE 的自动完成。第二,只要简单检查常量声明就能了解一个类支持哪些事件。
> Tip: 推荐使用类常量来表示事件名。上例中,常量 `EVENT_HELLO` 用来表示 `hello`
这有两个好处。第一,它可以防止拼写错误并支持 IDE 的自动完成。
第二,只要简单检查常量声明就能了解一个类支持哪些事件。
有时想要在触发事件时同时传递一些额外信息到事件处理器。例如,邮件程序要传递消息信息到 `messageSent` 事件的处理器以便处理器了解哪些消息被发送了。为此,可以提供一个事件对象作为 [[yii\base\Component::trigger()]] 方法的第二个参数。这个事件对象必须是 [[yii\base\Event]] 类或其子类的实例。如:
有时想要在触发事件时同时传递一些额外信息到事件处理器。
例如,邮件程序要传递消息信息到 `messageSent` 事件的处理器以便处理器了解哪些消息被发送了。
为此,可以提供一个事件对象作为 [[yii\base\Component::trigger()]] 方法的第二个参数。
这个事件对象必须是 [[yii\base\Event]] 类或其子类的实例。
如:
```php
namespace app\components;
@ -139,7 +160,8 @@ class Mailer extends Component
}
```
当 [[yii\base\Component::trigger()]] 方法被调用时,它将调用所有附加到命名事件(trigger 方法第一个参数)的事件处理器。
当 [[yii\base\Component::trigger()]] 方法被调用时,
它将调用所有附加到命名事件(trigger 方法第一个参数)的事件处理器。
移除事件处理器
@ -161,7 +183,9 @@ $foo->off(Foo::EVENT_HELLO, ['app\components\Bar', 'methodName']);
$foo->off(Foo::EVENT_HELLO, $anonymousFunction);
```
注意当匿名函数附加到事件后一般不要尝试移除匿名函数,除非你在某处存储了它。以上示例中,假设匿名函数存储为变量 `$anonymousFunction`
注意当匿名函数附加到事件后一般不要尝试移除匿名函数,
除非你在某处存储了它。以上示例中,
假设匿名函数存储为变量 `$anonymousFunction`
移除事件的全部处理器,简单调用 [[yii\base\Component::off()]] 即可,不需要第二个参数:
@ -169,12 +193,18 @@ $foo->off(Foo::EVENT_HELLO, $anonymousFunction);
$foo->off(Foo::EVENT_HELLO);
```
类级别的事件处理器
-------------------
以上部分,我们叙述了在**实例级别**如何附加处理器到事件。有时想要一个类的所有实例而不是一个指定的实例都响应一个被触发的事件,并不是一个个附加事件处理器到每个实例,而是通过调用静态方法 [[yii\base\Event::on()]] 在**类级别**附加处理器。
以上部分,我们叙述了在**实例级别**如何附加处理器到事件。
有时想要一个类的所有实例而不是一个指定的实例都响应一个被触发的事件,
并不是一个个附加事件处理器到每个实例,
而是通过调用静态方法 [[yii\base\Event::on()]] 在**类级别**附加处理器。
例如,[活动记录](db-active-record.md)对象要在每次往数据库新增一条新记录时触发一个 [[yii\db\BaseActiveRecord::EVENT_AFTER_INSERT|EVENT_AFTER_INSERT]] 事件。要追踪每个[活动记录](db-active-record.md)对象的新增记录完成情况,应如下写代码:
例如,[活动记录](db-active-record.md)对象要在每次往数据库新增一条新记录时触发一个
[[yii\db\BaseActiveRecord::EVENT_AFTER_INSERT|EVENT_AFTER_INSERT]] 事件。
要追踪每个[活动记录](db-active-record.md)对象的新增记录完成情况,应如下写代码:
```php
use Yii;
@ -186,11 +216,15 @@ Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function
});
```
每当 [[yii\db\BaseActiveRecord|ActiveRecord]] 或其子类的实例触发 [[yii\db\BaseActiveRecord::EVENT_AFTER_INSERT|EVENT_AFTER_INSERT]] 事件时,这个事件处理器都会执行。在这个处理器中,可以通过 `$event->sender` 获取触发事件的对象。
每当 [[yii\db\BaseActiveRecord|ActiveRecord]] 或其子类的实例触发
[[yii\db\BaseActiveRecord::EVENT_AFTER_INSERT|EVENT_AFTER_INSERT]] 事件时,
这个事件处理器都会执行。在这个处理器中,可以通过 `$event->sender` 获取触发事件的对象。
当对象触发事件时,它首先调用实例级别的处理器,然后才会调用类级别处理器。
可调用静态方法[[yii\base\Event::trigger()]]来触发一个**类级别**事件。类级别事件不与特定对象相关联。因此,它只会引起类级别事件处理器的调用。如:
可调用静态方法[[yii\base\Event::trigger()]]来触发一个**类级别**事件。
类级别事件不与特定对象相关联。因此,它只会引起类级别事件处理器的调用。
如:
```php
use yii\base\Event;
@ -204,7 +238,8 @@ Event::trigger(Foo::className(), Foo::EVENT_HELLO);
注意这种情况下 `$event->sender` 指向触发事件的类名而不是对象实例。
> 注意:因为类级别的处理器响应类和其子类的所有实例触发的事件,必须谨慎使用,尤其是底层的基类,如 [[yii\base\Object]]。
> Note: 因为类级别的处理器响应类和其子类的所有实例触发的事件,
必须谨慎使用,尤其是底层的基类,如 [[yii\base\Object]]。
移除类级别的事件处理器只需调用[[yii\base\Event::off()]],如:
@ -217,12 +252,90 @@ Event::off(Foo::className(), Foo::EVENT_HELLO);
```
Events using interfaces <span id="interface-level-event-handlers"></span>
-------------
There is even more abstract way to deal with events. You can create a separated interface for the special event and
implement it in classes, where you need it.
For example, we can create the following interface:
```php
namespace app\interfaces;
interface DanceEventInterface
{
const EVENT_DANCE = 'dance';
}
```
And two classes, that implement it:
```php
class Dog extends Component implements DanceEventInterface
{
public function meetBuddy()
{
echo "Woof!";
$this->trigger(DanceEventInterface::EVENT_DANCE);
}
}
class Developer extends Component implements DanceEventInterface
{
public function testsPassed()
{
echo "Yay!";
$this->trigger(DanceEventInterface::EVENT_DANCE);
}
}
```
To handle the `EVENT_DANCE`, triggered by any of these classes, call [[yii\base\Event::on()|Event::on()]] and
pass the interface class name as the first argument:
```php
Event::on('app\interfaces\DanceEventInterface', DanceEventInterface::EVENT_DANCE, function ($event) {
Yii::trace(get_class($event->sender) . ' just danced'); // Will log that Dog or Developer danced
});
```
You can trigger the event of those classes:
```php
// trigger event for Dog class
Event::trigger(Dog::className(), DanceEventInterface::EVENT_DANCE);
// trigger event for Developer class
Event::trigger(Developer::className(), DanceEventInterface::EVENT_DANCE);
```
But please notice, that you can not trigger all the classes, that implement the interface:
```php
// DOES NOT WORK. Classes that implement this interface will NOT be triggered.
Event::trigger('app\interfaces\DanceEventInterface', DanceEventInterface::EVENT_DANCE);
```
To detach event handler, call [[yii\base\Event::off()|Event::off()]]. For example:
```php
// detaches $handler
Event::off('app\interfaces\DanceEventInterface', DanceEventInterface::EVENT_DANCE, $handler);
// detaches all handlers of DanceEventInterface::EVENT_DANCE
Event::off('app\interfaces\DanceEventInterface', DanceEventInterface::EVENT_DANCE);
```
全局事件
-------------
所谓**全局事件**实际上是一个基于以上叙述的事件机制的戏法。它需要一个全局可访问的单例,如[应用](structure-applications.md)实例。
所谓**全局事件**实际上是一个基于以上叙述的事件机制的戏法。它需要一个全局可访问的单例,
如[应用](structure-applications.md)实例。
事件触发者不调用其自身的 `trigger()` 方法,而是调用单例的 `trigger()` 方法来触发全局事件。类似地,事件处理器被附加到单例的事件。如:
事件触发者不调用其自身的 `trigger()` 方法,而是调用单例的 `trigger()` 方法来触发全局事件。
类似地,事件处理器被附加到单例的事件。如:
```php
use Yii;
@ -236,6 +349,10 @@ Yii::$app->on('bar', function ($event) {
Yii::$app->trigger('bar', new Event(['sender' => new Foo]));
```
全局事件的一个好处是当附加处理器到一个对象要触发的事件时,不需要产生该对象。相反,处理器附加和事件触发都通过单例(如应用实例)完成。
全局事件的一个好处是当附加处理器到一个对象要触发的事件时,
不需要产生该对象。相反,处理器附加和事件触发都通过单例
(如应用实例)完成。
然而,因为全局事件的命名空间由各方共享,应合理命名全局事件,
如引入一些命名空间(例:"frontend.mail.sent", "backend.mail.sent")。
然而,因为全局事件的命名空间由各方共享,应合理命名全局事件,如引入一些命名空间(例:"frontend.mail.sent", "backend.mail.sent")。

38
docs/guide-zh-CN/concept-properties.md

@ -1,8 +1,8 @@
属性(Property)
==========
在 PHP 中,类的成员变量也被称为**属性(properties)**。
它们是类定义的一部分,用来表现一个实例的状态(也就是区分类的不同实例)。
在 PHP 中,类的成员变量也被称为**属性(properties)**。它们是类定义的一部分,
用来表现一个实例的状态(也就是区分类的不同实例)。
在具体实践中,常常会想用一个稍微特殊些的方法实现属性的读写。
例如,如果有需求每次都要对 `label` 属性执行 trim 操作,
就可以用以下代码实现:
@ -13,19 +13,19 @@ $object->label = trim($label);
上述代码的缺点是只要修改 `label` 属性就必须再次调用 `trim()` 函数。
若将来需要用其它方式处理 `label` 属性,比如首字母大写,
就不得不修改所有给 `label` 属性赋值的代码。
这种代码的重复会导致 bug,这种实践显然需要尽可能避免。
就不得不修改所有给 `label` 属性赋值的代码。这种代码的重复会导致 bug,
这种实践显然需要尽可能避免。
为解决该问题,Yii 引入了一个名为 [[yii\base\Object]] 的基类,
它支持基于类内的 **getter****setter**(读取器和设定器)方法来定义属性。
如果某类需要支持这个特性,只需要继承 [[yii\base\Object]] 或其子类即可。
> 补充:几乎每个 Yii 框架的核心类都继承自 [[yii\base\Object]] 或其子类。
> Info: 几乎每个 Yii 框架的核心类都继承自 [[yii\base\Object]] 或其子类。
这意味着只要在核心类中见到 getter 或 setter 方法,就可以像调用属性一样调用它。
getter 方法是名称以 `get` 开头的方法,而 setter 方法名以 `set` 开头。
方法名中 `get``set` 后面的部分就定义了该属性的名字。
如下面代码所示,getter 方法 `getLabel()` 和 setter 方法 `setLabel()` 操作的是 `label` 属性,:
方法名中 `get``set` 后面的部分就定义了该属性的名字。如下面代码所示,
getter 方法 `getLabel()` 和 setter 方法 `setLabel()` 操作的是 `label` 属性,:
```php
namespace app\components;
@ -48,12 +48,12 @@ class Foo extend Object
}
```
详细解释:getter 和 setter 方法创建了一个名为 `label` 的属性,
在这个例子里,它指向一个私有的内部属性 `_label`
详细解释:getter 和 setter 方法创建了一个名为 `label` 的属性,
在这个例子里,它指向一个私有的内部属性 `_label`
getter/setter 定义的属性用法与类成员变量一样。
两者主要的区别是:当这种属性被读取时,对应的 getter 方法将被调用;
而当属性被赋值时,对应的 setter 方法就调用。如:
getter/setter 定义的属性用法与类成员变量一样。两者主要的区别是:
当这种属性被读取时,对应的 getter 方法将被调用;而当属性被赋值时,
对应的 setter 方法就调用。如:
```php
// 等效于 $label = $object->getLabel();
@ -65,20 +65,20 @@ $object->label = 'abc';
只定义了 getter 没有 setter 的属性是**只读属性**。
尝试赋值给这样的属性将导致 [[yii\base\InvalidCallException|InvalidCallException]] (无效调用)异常。
类似的,只有 setter 方法而没有 getter 方法定义的属性是**只写属性**,尝试读取这种属性也会触发异常。
使用只写属性的情况几乎没有。
类似的,只有 setter 方法而没有 getter 方法定义的属性是**只写属性**,
尝试读取这种属性也会触发异常。使用只写属性的情况几乎没有。
通过 getter 和 setter 定义的属性也有一些特殊规则和限制:
* 这类属性的名字是**不区分大小写**的。如,`$object->label` 和 `$object->Label` 是同一个属性。
因为 PHP 方法名是不区分大小写的。
* 如果此类属性名和类成员变量相同,以后者为准。
例如,假设以上 `Foo` 类有个 `label` 成员变量,
然后给 `$object->label = 'abc'` 赋值,将赋给成员变量而不是 setter `setLabel()` 方法。
* 如果此类属性名和类成员变量相同,以后者为准。例如,
假设以上 `Foo` 类有个 `label` 成员变量,然后给 `$object->label = 'abc'` 赋值
将赋给成员变量而不是 setter `setLabel()` 方法。
* 这类属性不支持可见性(访问限制)。定义属性的 getter 和 setter 方法是 public、protected 还是 private 对属性的可见性没有任何影响。
* 这类属性的 getter 和 setter 方法只能定义为**非静态**的,若定义为静态方法(static)则不会以相同方式处理。
* `property_exists()` 不能确定魔术属性的正常调用。你应该调用 [[yii\base\Object::canGetProperty()|canGetProperty()]]
或 [[yii\base\Object::canSetProperty()|canSetProperty()]]。
* A normal call to `property_exists()` does not work to determine magic properties. You should call [[yii\base\BaseObject::canGetProperty()|canGetProperty()]]
or [[yii\base\BaseObject::canSetProperty()|canSetProperty()]] respectively.
回到开头提到的问题,与其处处要调用 `trim()` 函数,
现在我们只需在 setter `setLabel()` 方法内调用一次。

29
docs/guide-zh-CN/concept-service-locator.md

@ -1,21 +1,21 @@
服务定位器
===============
服务定位器是一个了解如何提供各种应用所需的服务(或组件)的对象。
在服务定位器中,每个组件都只有一个单独的实例,并通过ID 唯一地标识。
服务定位器是一个了解如何提供各种应用所需的服务(或组件)的对象。在服务定位器中,
每个组件都只有一个单独的实例,并通过ID 唯一地标识。
用这个 ID 就能从服务定位器中得到这个组件。
在 Yii 中,服务定位器是 [[yii\di\ServiceLocator]] 或其子类的一个实例。
最常用的服务定位器是**application(应用)**对象,可以通过 `\Yii::$app` 访问。
它所提供的服务被称为**application components(应用组件)**,比如:`request`、`response`、`urlManager` 组件。
可以通过服务定位器所提供的功能,非常容易地配置这些组件
或甚至是用你自己的实现替换掉他们。
它所提供的服务被称为**application components(应用组件)**,
比如:`request`、`response`、`urlManager` 组件。可以通过服务定位器所提供的功能,
非常容易地配置这些组件,或甚至是用你自己的实现替换掉他们。
除了 application 对象,每个模块对象本身也是一个服务定位器。
要使用服务定位器,第一步是要注册相关组件。
组件可以通过 [[yii\di\ServiceLocator::set()]] 方法进行注册。以下的方法展示了注册组件的不同方法:
要使用服务定位器,第一步是要注册相关组件。组件可以通过 [[yii\di\ServiceLocator::set()]] 方法进行注册。
以下的方法展示了注册组件的不同方法:
```php
use yii\di\ServiceLocator;
@ -52,8 +52,8 @@ $cache = $locator->cache;
```
如上所示, [[yii\di\ServiceLocator]] 允许通过组件 ID 像访问一个属性值那样访问一个组件。
当你第一次访问某组件时,
[[yii\di\ServiceLocator]] 会通过该组件的注册信息创建一个该组件的实例,并返回它。
当你第一次访问某组件时,[[yii\di\ServiceLocator]]
会通过该组件的注册信息创建一个该组件的实例,并返回它。
之后,如果再次访问,则服务定位器会返回同一个实例。
你可以通过 [[yii\di\ServiceLocator::has()]] 检查某组件 ID 是否被注册。
@ -61,10 +61,10 @@ $cache = $locator->cache;
因为服务定位器,经常会在创建时附带[配置信息](concept-configurations.md),
因此我们提供了一个可写的属性,
名为 [[yii\di\ServiceLocator::setComponents()|components]],
因此我们提供了一个可写的属性,名为 [[yii\di\ServiceLocator::setComponents()|components]],
这样就可以配置该属性,或一次性注册多个组件。
下面的代码展示了如何用一个配置数组,配置一个应用并注册"db","cache" 和 "search" 三个组件:
下面的代码展示了如何用一个配置数组,配置一个应用并注册
"db","cache" 和 "search" 三个组件:
```php
return [
@ -77,6 +77,9 @@ return [
'password' => '',
],
'cache' => 'yii\caching\ApcCache',
'tz' => function() {
return new \DateTimeZone(Yii::$app->formatter->defaultTimeZone);
},
'search' => function () {
$solr = new app\components\SolrService('127.0.0.1');
// ... other initializations ...
@ -86,7 +89,7 @@ return [
];
```
在上面的代码中,有一个替代方法来配置“搜索”组件。
在上面的代码中,有一个替代方法来配置 `search` 组件。
而不是直接写一个 PHP 回调建立 `SolrService`实例,你可以使用一个静态类方法来返回这样的回调,
如下所示:

2
docs/guide-zh-CN/db-dao.md

@ -2,7 +2,7 @@
========
Yii 包含了一个建立在 PHP PDO 之上的数据访问层 (DAO)。DAO为不同的数据库提供了一套统一的API。
其中```ActiveRecord``` 提供了数据库与模型(MVC 中的 M,Model) 的交互,```QueryBuilder``` 用于创建动态的查询语句。
其中 `ActiveRecord` 提供了数据库与模型(MVC 中的 M,Model) 的交互,`QueryBuilder` 用于创建动态的查询语句。
DAO提供了简单高效的SQL查询,可以用在与数据库交互的各个地方.
使用 Yii DAO 时,你主要需要处理纯 SQL 语句和 PHP 数组。因此,这是访问数据库最高效的方法。

16
docs/guide-zh-CN/input-multiple-models.md

@ -27,12 +27,16 @@ class UserController extends Controller
public function actionUpdate($id)
{
$user = User::findOne($id);
$profile = Profile::findOne($id);
if (!isset($user, $profile)) {
if (!$user) {
throw new NotFoundHttpException("The user was not found.");
}
$profile = Profile::findOne($user->profile_id);
if (!$profile) {
throw new NotFoundHttpException("The user has no profile.");
}
$user->scenario = 'update';
$profile->scenario = 'update';
@ -55,8 +59,10 @@ class UserController extends Controller
```
In the `update` action, we first load the `$user` and `$profile` models to be updated from the database. We then call
[[yii\base\Model::load()]] to populate these two models with the user input. If successful we will validate
the two models and save them. Otherwise we will render the `update` view which has the following content:
[[yii\base\Model::load()]] to populate these two models with the user input. If loading is successful, we will validate
the two models and then save them &mdash; please note that we use `save(false)` to skip over validations inside the models
as the user input data have already been validated. If loading is not successful, we will render the `update` view which
has the following content:
```php
<?php

149
docs/guide-zh-CN/intro-upgrade-from-v1.md

@ -2,24 +2,24 @@
===============
2.0 版框架是完全重写的,在 1.1 和 2.0 两个版本之间存在相当多差异。
因此从 1.1 版升级并不像小版本间的跨越那么简单,通过本指南你将会
了解两个版本间主要的不同之处。
因此从 1.1 版升级并不像小版本间的跨越那么简单,
通过本指南你将会了解两个版本间主要的不同之处。
如果你之前没有用过 Yii 1.1,可以跳过本章,直接从"[入门篇](start-installation.md)"开始读起。
请注意,Yii 2.0 引入了很多本章并没有涉及到的新功能。强烈建议你通读整部权威指南
来了解所有新特性。这样有可能会发现一些以前你要自己开发的功能,而现在已经被包含
在核心代码中了。
请注意,Yii 2.0 引入了很多本章并没有涉及到的新功能。
强烈建议你通读整部权威指南来了解所有新特性。
这样有可能会发现一些以前你要自己开发的功能,而现在已经被包含在核心代码中了。
安装
------------
Yii 2.0 完全拥抱 [Composer](https://getcomposer.org/),它是事实上的 PHP 依赖管理工具。
核心框架以及扩展的安装都通过 Composer 来处理。想要了解更多如何安装 Yii 2.0 请参阅本
指南的 [安装 Yii](start-installation.md) 章节。如果你想创建新扩展,或者把你已有的
Yii 1.1 的扩展改写成兼容 2.0 的版本,你可以参考
[创建扩展](structure-extensions.md#creating-extensions) 章节。
核心框架以及扩展的安装都通过 Composer 来处理。想要了解更多如何安装 Yii 2.0 请参阅本指南的
[安装 Yii](start-installation.md) 章节。如果你想创建新扩展,
或者把你已有的 Yii 1.1 的扩展改写成兼容 2.0 的版本,
你可以参考 [创建扩展](structure-extensions.md#creating-extensions) 章节。
PHP 需求
@ -45,24 +45,24 @@ Yii 2.0 需要 PHP 5.4 或更高版本,该版本相对于 Yii 1.1 所需求的
---------
Yii 2.0 里最明显的改动就数命名空间的使用了。几乎每一个核心类都引入了命名空间,
比如 `yii\web\Request`。1.1 版类名前缀 “C” 已经不再使用。当前的命名方案与目录结构相吻合。
例如,`yii\web\Request` 就表明对应的类文件是
Yii 框架文件夹下的 `web/Request.php` 文件。
比如 `yii\web\Request`。1.1 版类名前缀 “C” 已经不再使用。
当前的命名方案与目录结构相吻合。例如,`yii\web\Request`
就表明对应的类文件是 Yii 框架文件夹下的 `web/Request.php` 文件。
(有了 Yii 的类自动加载器,你可以直接使用全部核心类而不需要显式包含
具体文件。)
(有了 Yii 的类自动加载器,
你可以直接使用全部核心类而不需要显式包含具体文件。)
组件(Component)与对象(Object)
--------------------
Yii 2.0 把 1.1 中的 `CComponent` 类拆分成了两个类:[[yii\base\Object]] 和 [[yii\base\Component]]。
[[yii\base\Object|Object]] 类是一个轻量级的基类,你可以通过 getters 和 setters 来定义
[对象的属性](concept-properties.md)。[[yii\base\Component|Component]] 类继承自 [[yii\base\Object|Object]],
[[yii\base\Object|Object]] 类是一个轻量级的基类,你可以通过 getters 和 setters 来定义[对象的属性](concept-properties.md)。
[[yii\base\Component|Component]] 类继承自 [[yii\base\Object|Object]],
同时进一步支持 [事件](concept-events.md) 和 [行为](concept-behaviors.md)。
如果你不需要用到事件或行为,应该考虑使用
[[yii\base\Object|Object]] 类作为基类。
如果你不需要用到事件或行为,
应该考虑使用 [[yii\base\Object|Object]] 类作为基类。
这种类通常用来表示基本的数据结构。
@ -70,8 +70,8 @@ Yii 2.0 把 1.1 中的 `CComponent` 类拆分成了两个类:[[yii\base\Object
--------------------
[[yii\base\Object|Object]] 类引入了一种统一对象配置的方法。
所有 [[yii\base\Object|Object]] 的子类都应该用以下方法声明
它的构造方法(如果需要的话),以正确配置它自身:
所有 [[yii\base\Object|Object]] 的子类都应该用以下方法声明它的构造方法(如果需要的话),
以正确配置它自身:
```php
class MyClass extends \yii\base\Object
@ -93,9 +93,9 @@ class MyClass extends \yii\base\Object
```
在上面的例子里,构造方法的最后一个参数必须传入一个配置数组,
包含一系列用于在方法结尾初始化相关属性的键值对。你可以重写
[[yii\base\Object::init()|init()]] 方法来执行一些需要在配置
生效后进行的初始化工作。
包含一系列用于在方法结尾初始化相关属性的键值对。
你可以重写 [[yii\base\Object::init()|init()]]
方法来执行一些需要在配置生效后进行的初始化工作。
你可以通过遵循以下约定俗成的编码习惯,
来使用配置数组创建并配置新的对象:
@ -114,8 +114,8 @@ $object = Yii::createObject([
事件(Event)
------
在 Yii 1 中,通常通过定义 `on` 开头的方法(例如 `onBeforeSave`)来创建事件。而在 Yii 2 中,你可以使用任意的事件名了。
同时通过调用 [[yii\base\Component::trigger()|trigger()]] 方法来触发相关事件:
在 Yii 1 中,通常通过定义 `on` 开头的方法(例如 `onBeforeSave`)来创建事件。
而在 Yii 2 中,你可以使用任意的事件名了。同时通过调用 [[yii\base\Component::trigger()|trigger()]] 方法来触发相关事件:
```php
$event = new \yii\base\Event;
@ -136,18 +136,18 @@ $component->on($eventName, $handler);
路径别名(Path Alias)
------------
Yii 2.0 将路径别名的应用扩大至文件/目录路径和 URL。
Yii 2.0 中路径别名必须以 `@` 符号开头,
Yii 2.0 将路径别名的应用扩大至文件/目录路径和 URL。Yii 2.0 中路径别名必须以 `@` 符号开头,
以区别于普通文件目录路径或 URL。例如 `@yii` 就是指向 Yii 安装目录的别名。
绝大多数 Yii 核心代码都支持别名。例如 [[yii\caching\FileCache::cachePath]]
绝大多数 Yii 核心代码都支持别名。
例如 [[yii\caching\FileCache::cachePath]]
就同时支持路径别名或普通的目录地址。
路径别名也和类的命名空间密切相关。建议给每一个根命名空间定义一个路径别名,
从而无须额外配置,便可启动 Yii 的类自动加载机制。
例如,因为有 `@yii` 指向 Yii 安装目录,那类似 `yii\web\Request`
的类就能被 Yii 自动加载。同理,若你用了一个第三方的类库,
如 Zend Framework,你只需定义一个名为 `@Zend` 的路径别名指向该
框架的安装目录。之后 Yii 就可以自动加载任意 Zend Framework 中的类了。
例如,因为有 `@yii` 指向 Yii 安装目录,
那类似 `yii\web\Request` 的类就能被 Yii 自动加载。同理,若你用了一个第三方的类库,
如 Zend Framework,你只需定义一个名为 `@Zend` 的路径别名指向该框架的安装目录。
之后 Yii 就可以自动加载任意 Zend Framework 中的类了。
更多路径别名信息请参阅[路径别名](concept-aliases.md)章节。
@ -156,9 +156,9 @@ Yii 2.0 中路径别名必须以 `@` 符号开头,
-----
Yii 2 中视图最明显的改动是视图内的特殊变量 `$this` 不再指向当前控制器或小部件,
而是指向**视图**对象,它是 2.0 中引入的全新概念。**视图**对象为
[[yii\web\View]] 的实例,他代表了 MVC 模式中的视图部分。
如果你想要在视图中访问一个控制器或小部件,可以使用 `$this->context`
而是指向**视图**对象,它是 2.0 中引入的全新概念。**视图**对象为 [[yii\web\View]] 的实例,
他代表了 MVC 模式中的视图部分。如果你想要在视图中访问一个控制器或小部件,
可以使用 `$this->context`
要在其他视图里渲染一个局部视图,使用 `$this->render()`,而不是 `$this->renderPartial()`
`render()` 现在只返回渲染结果,而不是直接显示它,所以现在你必须显式地把它 **echo** 出来。像这样:
@ -167,18 +167,18 @@ Yii 2 中视图最明显的改动是视图内的特殊变量 `$this` 不再指
echo $this->render('_item', ['item' => $item]);
```
除了使用 PHP 作为主要的模板语言,Yii 2.0 也装备了两种流行模板引擎的官方支持:
Smarty 和 Twig。过去的 Prado 模板引擎不再被支持。要使用这些模板引擎,
你需要配置 `view` 应用组件,给它设置
[[yii\base\View::$renderers|View::$renderers]] 属性。
除了使用 PHP 作为主要的模板语言,Yii 2.0 也装备了两种流行模板引擎的官方支持:Smarty 和 Twig。
过去的 Prado 模板引擎不再被支持。要使用这些模板引擎,
你需要配置 `view` 应用组件,
给它设置 [[yii\base\View::$renderers|View::$renderers]] 属性。
具体请参阅[模板引擎](tutorial-template-engines.md)章节。
模型(Model)
------
Yii 2.0 使用 [[yii\base\Model]] 作为模型基类,类似于 1.1 的 `CModel``CFormModel` 被完全弃用了,
现在要创建表单模型类,可以通过继承 [[yii\base\Model]] 类来实现。
Yii 2.0 使用 [[yii\base\Model]] 作为模型基类,类似于 1.1 的 `CModel`
`CFormModel` 被完全弃用了,现在要创建表单模型类,可以通过继承 [[yii\base\Model]] 类来实现。
Yii 2.0 引进了名为 [[yii\base\Model::scenarios()|scenarios()]] 的新方法来声明支持的场景,
并指明在哪个场景下某属性必须经过验证,可否被视为安全值等等。如:
@ -193,9 +193,9 @@ public function scenarios()
}
```
上面的代码声明了两个场景:`backend` 和 `frontend` 。对于 `backend` 场景,
`email``role` 属性值都是安全的,且能进行批量赋值。对于 `frontend` 场景,
`email` 能批量赋值而 `role` 不能。 `email` `role` 都必须通过规则验证。
上面的代码声明了两个场景:`backend` 和 `frontend` 。对于 `backend` 场景,`email` 和 `role` 属性值都是安全的,
且能进行批量赋值。对于 `frontend` 场景,`email` 能批量赋值而 `role` 不能。
`email``role` 都必须通过规则验证。
[[yii\base\Model::rules()|rules()]] 方法仍用于声明验证规则。注意,由于引入了 [[yii\base\Model::scenarios()|scenarios()]],现在已经没有 `unsafe` 验证器了。
@ -209,8 +209,8 @@ public function scenarios()
控制器(Controller)
-----------
Yii 2.0 使用 [[yii\web\Controller]] 作为控制器的基类,它类似于 1.1 的 `CController`
使用 [[yii\base\Action]] 作为操作类的基类。
Yii 2.0 使用 [[yii\web\Controller]] 作为控制器的基类,
它类似于 1.1 的 `CController`使用 [[yii\base\Action]] 作为操作类的基类。
这些变化最明显的影响是,当你在写控制器操作的代码时,
应该返回(return)要渲染的内容而不是输出(echo)它:
@ -261,14 +261,14 @@ ActiveForm::end();
主题(Theme)
------
2.0 主题的运作方式跟以往完全不同了。它们现在基于**路径映射机制**,
该机制会把一个源视图文件的路径映射到一个主题视图文件路径。
2.0 主题的运作方式跟以往完全不同了。它们现在基于**路径映射机制**,该机制会把一个源视图文件的路径映射到一个主题视图文件路径。
举例来说,如果路径映射为 `['/web/views' => '/web/themes/basic']`
那么 `/web/views/site/index.php` 视图经过主题修饰的版本就会是 `/web/themes/basic/site/index.php`
也因此让主题现在可以应用在任何视图文件之上,甚至是渲染控制器上下文环境之外的视图文件或小部件。
也因此让主题现在可以应用在任何视图文件之上,
甚至是渲染控制器上下文环境之外的视图文件或小部件。
同样,`CThemeManager` 组件已经被移除了。取而代之的 `theme` 成为了 `view`
应用组件的一个可配置属性。
同样,`CThemeManager` 组件已经被移除了。
取而代之的 `theme` 成为了 `view` 应用组件的一个可配置属性。
更多细节请参考[主题](output-theming.md)章节。
@ -276,13 +276,13 @@ ActiveForm::end();
控制台应用(Console Application)
--------------------
控制台应用现在如普通的 Web 应用程序一样,由控制器组成,控制台的控制器继承自 [[yii\console\Controller]],
类似于 1.1 的 `CConsoleCommand`
控制台应用现在如普通的 Web 应用程序一样,由控制器组成,
控制台的控制器继承自 [[yii\console\Controller]],类似于 1.1 的 `CConsoleCommand`
运行控制台命令使用 `yii <route>`其中 `<route>`
代表控制器的路由(如 `sitemap/index`)。
额外的匿名参数传递到对应的控制器操作方法,而有名的参数根据
[[yii\console\Controller::options()]] 的声明来解析。
运行控制台命令使用 `yii <route>`
其中 `<route>` 代表控制器的路由(如 `sitemap/index`)。
额外的匿名参数传递到对应的控制器操作方法,
而有名的参数根据 [[yii\console\Controller::options()]] 的声明来解析。
Yii 2.0 支持基于代码注释自动生成相的关命令行帮助(help)信息。
@ -304,8 +304,8 @@ Yii 2.0 移除了原来内置的日期格式器和数字格式器,为了支持
动作过滤器(Action Filters)
--------------
作的过滤现在通过行为(behavior)来实现。要定义一个新的,自定义的过滤器,
请继承 [[yii\base\ActionFilter]] 类。要使用一个过滤器,需要把过滤器类作为一个 `behavior` 绑定到控制器上。
作的过滤现在通过行为(behavior)来实现。要定义一个新的,自定义的过滤器,请继承 [[yii\base\ActionFilter]] 类。
要使用一个过滤器,需要把过滤器类作为一个 `behavior` 绑定到控制器上。
例如,要使用 [[yii\filters\AccessControl]] 过滤器,你需要在控制器内添加如下代码:
```php
@ -400,11 +400,11 @@ $rows = $command->queryAll();
活动记录(Active Record)
-------------
Yii 2.0 的[活动记录](db-active-record.md)改动了很多。两个最显而易见的改动分别涉及查询语句的生成
(query building)和关联查询的处理(relational query handling)。
Yii 2.0 的[活动记录](db-active-record.md)改动了很多。
两个最显而易见的改动分别涉及查询语句的生成(query building)和关联查询的处理(relational query handling)。
1.1 中的 `CDbCriteria` 类在 Yii 2 中被 [[yii\db\ActiveQuery]] 所替代。这个类是继承自 [[yii\db\Query]],
因此也继承了所有查询生成方法。开始拼装一个查询可以调用 [[yii\db\ActiveRecord::find()]] 方法进行:
1.1 中的 `CDbCriteria` 类在 Yii 2 中被 [[yii\db\ActiveQuery]] 所替代。
这个类是继承自 [[yii\db\Query]],因此也继承了所有查询生成方法。开始拼装一个查询可以调用 [[yii\db\ActiveRecord::find()]] 方法进行:
```php
// 检索所有“活动的”客户和订单,并以 ID 排序:
@ -415,8 +415,8 @@ $customers = Customer::find()
```
要声明一个关联关系,只需简单地定义一个 getter 方法来返回一个 [[yii\db\ActiveQuery|ActiveQuery]] 对象。
getter 方法定义的属性名代表关联表名称。如,以下代码声明了一个名为 `orders` 的关系
(1.1 中必须在 `relations()` 方法内声明关系):
getter 方法定义的属性名代表关联表名称。
如,以下代码声明了一个名为 `orders` 的关系(1.1 中必须在 `relations()` 方法内声明关系):
```php
class Customer extends \yii\db\ActiveRecord
@ -431,7 +431,6 @@ class Customer extends \yii\db\ActiveRecord
现在你就可以通过调用 `$customer->orders` 来访问关联表中某用户的订单了。
你还可以用以下代码进行一场指定条件的实时关联查询:
```php
$orders = $customer->getOrders()->andWhere('status=1')->all();
```
@ -441,8 +440,8 @@ $orders = $customer->getOrders()->andWhere('status=1')->all();
第二条通过主表记录经主键筛选后查询关联表记录。
当生成返回大量记录的查询时,可以链式书写 [[yii\db\ActiveQuery::asArray()|asArray()]] 方法,
这样会以数组的形式返回查询结果,而不必返回[[yii\db\ActiveRecord|ActiveRecord]] 对象,
这能显著降低因大量记录读取所消耗的 CPU 时间和内存。如:
这样会以数组的形式返回查询结果,而不必返回
[[yii\db\ActiveRecord|ActiveRecord]] 对象,这能显著降低因大量记录读取所消耗的 CPU 时间和内存。如:
```php
$customers = Customer::find()->asArray()->all();
@ -459,8 +458,8 @@ public function init()
}
```
曾几何时,在 1.1 中重写一个活动记录类的构造方法会导致一些问题。
它们不会在 2.0 中出现了。需要注意的是,如果你需要在构造方法中添加一些参数,恐怕必须重写 [[yii\db\ActiveRecord::instantiate()]] 方法。
曾几何时,在 1.1 中重写一个活动记录类的构造方法会导致一些问题。它们不会在 2.0 中出现了。
需要注意的是,如果你需要在构造方法中添加一些参数,恐怕必须重写 [[yii\db\ActiveRecord::instantiate()]] 方法。
活动记录方面还有很多其他的变化与改进,
请参考[活动记录](db-active-record.md)章节以了解更多细节。
@ -501,8 +500,8 @@ class MyBehavior extends Behavior
用户及身份验证接口(IdentityInterface)
-------------------------------------
1.1 中的 `CWebUser` 类现在被 [[yii\web\User]] 所取代,随之 `CUserIdentity` 类也不在了。与之相对的,
为达到相同目的,你可以实现 [[yii\web\IdentityInterface]] 接口,它使用起来更直观。
1.1 中的 `CWebUser` 类现在被 [[yii\web\User]] 所取代,随之 `CUserIdentity` 类也不在了。
与之相对的,为达到相同目的,你可以实现 [[yii\web\IdentityInterface]] 接口,它使用起来更直观。
在高级应用模版里提供了一个这样的一个例子。
要了解更多细节请参考[认证(Authentication)](security-authentication.md),[授权(Authorization)](security-authorization.md)以及[高级应用模版](tutorial-advanced-app.md) 这三个章节。
@ -512,9 +511,9 @@ URL 管理
--------
Yii 2.0 的 URL 管理跟 1.1 中很像。一个主要的改进是现在的 URL 管理支持**可选参数**了。
比如,如果你在 2.0 中定义了一个下面这样的规则,那么它可以同时匹配 `post/popular`
`post/1/popular` 两种 URL。而在 1.1 中为达成相同效果,
必须要使用两条规则。
比如,如果你在 2.0 中定义了一个下面这样的规则,那么它可以同时匹配
`post/popular` `post/1/popular` 两种 URL。
而在 1.1 中为达成相同效果,必须要使用两条规则。
```php
[

31
docs/guide-zh-CN/intro-yii.md

@ -11,8 +11,8 @@ Yii 最适合做什么?
Yii 是一个通用的 Web 编程框架,即可以用于开发各种用 PHP 构建的 Web 应用。
因为基于组件的框架结构和设计精巧的缓存支持,它特别适合开发大型应用,
如门户网站、社区、内容管理系统(CMS)、电子商务项目
和 RESTful Web 服务等。
如门户网站、社区、内容管理系统(CMS)、
电子商务项目和 RESTful Web 服务等。
Yii 和其他框架相比呢?
@ -22,8 +22,8 @@ Yii 和其他框架相比呢?
- 和其他 PHP 框架类似,Yii 实现了 MVC(Model-View-Controller)
设计模式并基于该模式组织代码。
- Yii 的代码简洁优雅,这是它的编程哲学。它永远不会为了刻板地
遵照某种设计模式而对代码进行过度的设计。
- Yii 的代码简洁优雅,这是它的编程哲学。
它永远不会为了刻板地遵照某种设计模式而对代码进行过度的设计。
- Yii 是一个全栈框架,提供了大量久经考验,开箱即用的特性:
对关系型和 NoSQL 数据库都提供了查询生成器和
ActiveRecord;RESTful API 的开发支持;多层缓存支持,等等。
@ -31,9 +31,9 @@ Yii 和其他框架相比呢?
坚实可靠的扩展架构,使用、再开发或再发布扩展。
- 高性能始终是 Yii 的首要目标之一。
Yii 不是一场独角戏,它由一个[强大的开发者团队](http://www.yiiframework.com/about/)
提供支持,也有一个庞大的专家社区,持续不断地对 Yii 的开发作出贡献。Yii 开发者团队
始终对 Web 开发趋势和其他框架及项目中的最佳实践和特性保持密切关注,
Yii 不是一场独角戏,它由一个[强大的开发者团队](http://www.yiiframework.com/about/)提供支持,
也有一个庞大的专家社区,持续不断地对 Yii 的开发作出贡献。
Yii 开发者团队始终对 Web 开发趋势和其他框架及项目中的最佳实践和特性保持密切关注,
那些有意义的最佳实践及特性会被不定期的整合进核心框架中,
并提供简单优雅的接口。
@ -43,18 +43,19 @@ Yii 版本
------------
Yii 当前有两个主要版本:1.1 和 2.0。 1.1 版是上代的老版本,现在处于维护状态。
2.0 版是一个完全重写的版本,采用了最新的技术和协议,包括依赖包管理器
Composer、PHP 代码规范 PSR、命名空间、Traits(特质)等等。 2.0 版代表新一代框架,
是未来几年中我们的主要开发版本。本指南主要基于 2.0 版编写。
2.0 版是一个完全重写的版本,采用了最新的技术和协议,包括依赖包管理器 Composer、PHP 代码规范 PSR、命名空间、Traits(特质)等等。
2.0 版代表新一代框架,是未来几年中我们的主要开发版本。
本指南主要基于 2.0 版编写。
系统要求和先决条件
------------------------------
Yii 2.0 需要 PHP 5.4.0 或以上版本支持。你可以通过运行任何 Yii 发行包
中附带的系统要求检查器查看每个具体特性所需的 PHP 配置。
Yii 2.0 需要 PHP 5.4.0 或以上版本支持。你可以通过运行任何
Yii 发行包中附带的系统要求检查器查看每个具体特性所需的 PHP 配置。
使用 Yii 需要对面向对象编程(OOP)有基本了解,因为 Yii 是一个纯面向对象的框架。
Yii 2.0 还使用了 PHP 的最新特性,例如[命名空间](http://www.php.net/manual/en/language.namespaces.php)
和[Trait(特质)](http://www.php.net/manual/en/language.oop5.traits.php) 。理解这些概念将有助于你更快地掌握 Yii 2.0。
使用 Yii 需要对面向对象编程(OOP)有基本了解,因为 Yii 是一个纯面向对象的框架。Yii 2.0 还使用了 PHP 的最新特性,
例如[命名空间](http://www.php.net/manual/en/language.namespaces.php)
和[Trait(特质)](http://www.php.net/manual/en/language.oop5.traits.php)。
理解这些概念将有助于你更快地掌握 Yii 2.0。

22
docs/guide-zh-CN/rest-authentication.md

@ -14,12 +14,12 @@
当作用户名发送,应用在access token可安全存在API使用端的场景,
例如,API使用端是运行在一台服务器上的程序。
* 请求参数: access token 当作API URL请求参数发送,例如
`https://example.com/users?access-token=xxxxxxxx`
`https://example.com/users?access-token=xxxxxxxx`
由于大多数服务器都会保存请求参数到日志,
这种方式应主要用于`JSONP` 请求,因为它不能使用HTTP头来发送access token
* [OAuth 2](http://oauth.net/2/): 使用者从认证服务器上获取基于
OAuth2协议的access token,然后通过
[HTTP Bearer Tokens](http://tools.ietf.org/html/rfc6750) 发送到API 服务器。
* [OAuth 2](http://oauth.net/2/): 使用者从认证服务器上获取基于OAuth2协议的access token,
然后通过[HTTP Bearer Tokens](http://tools.ietf.org/html/rfc6750)
发送到API 服务器。
Yii 支持上述的认证方式,你也可很方便的创建新的认证方式。
@ -36,8 +36,8 @@ Yii 支持上述的认证方式,你也可很方便的创建新的认证方式
当[[yii\web\User::enableSession|enableSession]]为false,
请求中的用户认证状态就不能通过session来保持,每个请求的认证通过步骤2和3来实现。
> 提示: 如果你将RESTful APIs作为应用开发,可以设置应用配置中
> `user` 组件的[[yii\web\User::enableSession|enableSession]],
> Tip: 如果你将RESTful APIs作为应用开发,可以设置应用配置中 `user` 组件的
> [[yii\web\User::enableSession|enableSession]],
> 如果将RESTful APIs作为模块开发,可以在模块的 `init()` 方法中增加如下代码,如下所示:
> ```php
@ -106,19 +106,19 @@ class User extends ActiveRecord implements IdentityInterface
}
```
在上述认证启用后,对于每个API请求,请求控制器都会在它的`beforeAction()`
步骤中对用户进行认证。
在上述认证启用后,对于每个API请求,
请求控制器都会在它的`beforeAction()`步骤中对用户进行认证。
如果认证成功,控制器再执行其他检查(如频率限制,操作权限),然后再执行动作,
授权用户信息可使用`Yii::$app->user->identity`获取.
如果认证失败,会发送一个HTTP状态码为401的响应,并带有其他相关信息头
(如HTTP 基本认证会有`WWW-Authenticate` 头信息).
如果认证失败,会发送一个HTTP状态码为401的响应,
并带有其他相关信息头(如HTTP 基本认证会有`WWW-Authenticate` 头信息).
## 授权 <a name="authorization"></a>
在用户认证成功后,你可能想要检查他是否有权限执行对应的作来获取资源,
在用户认证成功后,你可能想要检查他是否有权限执行对应的作来获取资源,
这个过程称为 *authorization*
详情请参考 [Authorization section](security-authorization.md).

83
docs/guide-zh-CN/rest-controllers.md

@ -1,14 +1,14 @@
控制器
===========
在创建资源类和指定资源格输出式化后,下一步就是创建控制器动作将资源
通过RESTful APIs展现给终端用户。
Yii 提供两个控制器基类来简化创建 RESTful 动作的工作:
[[yii\rest\Controller]] 和 [[yii\rest\ActiveController]],
两个类的差别是后者提供一系列将资源处理成[Active Record](db-active-record.md)
的动作。因此如果使用[Active Record](db-active-record.md)
内置的动作会比较方便,可考虑将控制器类继承[[yii\rest\ActiveController]],
在创建资源类和指定资源格输出式化后,
下一步就是创建控制器操作将资源通过RESTful APIs展现给终端用户。
Yii 提供两个控制器基类来简化创建RESTful
操作的工作:[[yii\rest\Controller]] 和 [[yii\rest\ActiveController]],
两个类的差别是后者提供一系列将资源处理成[Active Record](db-active-record.md)的操作。
因此如果使用[Active Record](db-active-record.md)内置的操作会比较方便,可考虑将控制器类
继承[[yii\rest\ActiveController]],
它会让你用最少的代码完成强大的RESTful APIs.
[[yii\rest\Controller]] 和 [[yii\rest\ActiveController]] 提供以下功能,
@ -27,15 +27,15 @@ Yii 提供两个控制器基类来简化创建 RESTful 动作的工作:
## 创建控制器类 <span id="creating-controller"></span>
当创建一个新的控制器类,控制器类的命名最好使用资源
名称的单数格式,例如,提供用户信息的控制器
当创建一个新的控制器类,控制器类的命名最好使用资源名称的单数格式,
例如,提供用户信息的控制器
可命名为`UserController`.
创建新的动作和Web应用中创建操作类似,唯一的差别是Web应用中
调用`render()`方法渲染一个视图作为返回值,对于RESTful动作
直接返回数据,[[yii\rest\Controller::serializer|serializer]] 和
[[yii\web\Response|response object]] 会处理原始数据到请求格式的转换,
例如
创建新的操作和Web应用中创建操作类似,
唯一的差别是Web应用中调用`render()`方法渲染一个视图作为返回值,
对于RESTful操作直接返回数据,
[[yii\rest\Controller::serializer|serializer]] 和[[yii\web\Response|response object]]
会处理原始数据到请求格式的转换,例如
```php
public function actionView($id)
@ -52,7 +52,7 @@ public function actionView($id)
* [[yii\filters\ContentNegotiator|contentNegotiator]]: 支持内容协商,
在 [响应格式化](rest-response-formatting.md) 一节描述;
* [[yii\filters\VerbFilter|verbFilter]]: 支持HTTP 方法验证;the [Authentication](rest-authentication.md) section;
* [[yii\filters\VerbFilter|verbFilter]]: 支持HTTP 方法验证;
* [[yii\filters\auth\AuthMethod|authenticator]]: 支持用户认证,
在[认证](rest-authentication.md)一节描述;
* [[yii\filters\RateLimiter|rateLimiter]]: 支持频率限制,
@ -75,11 +75,46 @@ public function behaviors()
}
```
### CORS <span id="cors"></span>
Adding the [Cross-Origin Resource Sharing](structure-filters.md#cors) filter to a controller is a bit more complicated
than adding other filters described above, because the CORS filter has to be applied before authentication methods
and thus needs a slightly different approach compared to other filters. Also authentication has to be disabled for the
[CORS Preflight requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests)
so that a browser can safely determine whether a request can be made beforehand without the need for sending
authentication credentials. The following shows the code that is needed to add the [[yii\filters\Cors]] filter
to an existing controller that extends from [[yii\rest\ActiveController]]:
```php
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
$behaviors = parent::behaviors();
// remove authentication filter
$auth = $behaviors['authenticator'];
unset($behaviors['authenticator']);
// add CORS filter
$behaviors['corsFilter'] = [
'class' => \yii\filters\Cors::className(),
];
// re-add authentication filter
$behaviors['authenticator'] = $auth;
// avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
$behaviors['authenticator']['except'] = ['options'];
return $behaviors;
}
```
## 继承 `ActiveController` <span id="extending-active-controller"></span>
如果你的控制器继承[[yii\rest\ActiveController]],应设置
[[yii\rest\ActiveController::modelClass|modelClass]] 属性
如果你的控制器继承[[yii\rest\ActiveController]],
应设置[[yii\rest\ActiveController::modelClass|modelClass]] 属性
为通过该控制器返回给用户的资源类名,该类必须继承[[yii\db\ActiveRecord]].
@ -122,9 +157,9 @@ public function prepareDataProvider()
### 执行访问检查 <span id="performing-access-check"></span>
通过RESTful APIs显示数据时,经常需要检查当前用户是否有权限访问和作所请求的资源,
在[[yii\rest\ActiveController]]中,可覆盖[[yii\rest\ActiveController::checkAccess()|checkAccess()]]
方法来完成权限检查。
通过RESTful APIs显示数据时,经常需要检查当前用户是否有权限访问和作所请求的资源,
在[[yii\rest\ActiveController]]中,
可覆盖[[yii\rest\ActiveController::checkAccess()|checkAccess()]]方法来完成权限检查。
```php
/**
@ -135,14 +170,14 @@ public function prepareDataProvider()
* If the user does not have access, a [[ForbiddenHttpException]] should be thrown.
*
* @param string $action the ID of the action to be executed
* @param \yii\base\Model $model the model to be accessed. If null, it means no specific model is being accessed.
* @param \yii\base\Model $model the model to be accessed. If `null`, it means no specific model is being accessed.
* @param array $params additional parameters
* @throws ForbiddenHttpException if the user does not have access
*/
public function checkAccess($action, $model = null, $params = [])
{
// 检查用户能否访问 $action 和 $model
// 访问被拒绝应抛出ForbiddenHttpException
// check if the user can access $action and $model
// throw ForbiddenHttpException if access should be denied
if ($action === 'update' || $action === 'delete') {
if ($model->author_id !== \Yii::$app->user->id)
throw new \yii\web\ForbiddenHttpException(sprintf('You can only %s articles that you\'ve created.', $action));

9
docs/guide-zh-CN/rest-error-handling.md

@ -4,10 +4,11 @@
处理一个 RESTful API 请求时, 如果有一个用户请求错误或服务器发生意外时,
你可以简单地抛出一个异常来通知用户出错了。
如果你能找出错误的原因 (例如,所请求的资源不存在),你应该
考虑抛出一个适当的HTTP状态代码的异常 (例如, [[yii\web\NotFoundHttpException]]
意味着一个404 HTTP状态代码)。 Yii 将通过HTTP状态码和文本
发送相应的响应。 它还将包括在响应主体异常的
序列化表示形式。 例如,
考虑抛出一个适当的HTTP状态代码的异常
(例如, [[yii\web\NotFoundHttpException]]意味着一个404 HTTP状态代码)。
Yii 将通过HTTP状态码和文本发送相应的响应。
它还将包括在响应主体异常的序列化表示形式。
例如,
```
HTTP/1.1 404 Not Found

10
docs/guide-zh-CN/rest-quick-start.md

@ -37,8 +37,8 @@ class UserController extends ActiveController
}
```
控制器类扩展自 [[yii\rest\ActiveController]]。通过指定
[[yii\rest\ActiveController::modelClass|modelClass]]
控制器类扩展自 [[yii\rest\ActiveController]]。
通过指定 [[yii\rest\ActiveController::modelClass|modelClass]]
作为 `app\models\User`, 控制器就能知道使用哪个模型去获取和处理数据。
@ -60,6 +60,9 @@ class UserController extends ActiveController
上面的配置主要是为`user`控制器增加一个 URL 规则。这样,
用户的数据就能通过美化的 URL 和有意义的 http 动词进行访问和操作。
> Note: Yii will automatically pluralize controller names for use in endpoints (see [Trying it Out](#trying-it-out) section below).
> You can configure this using the [[yii\rest\UrlRule::$pluralize]] property.
## 启用 JSON 输入 <span id="enabling-json-input"></span>
@ -93,9 +96,6 @@ class UserController extends ActiveController
* `OPTIONS /users`: 显示关于末端 `/users` 支持的动词
* `OPTIONS /users/123`: 显示有关末端 `/users/123` 支持的动词
> 提示: Yii 将在末端使用的控制器的名称自动变为复数。(译注:个人感觉这里应该变为注意)
> 你可以用 [[yii\rest\UrlRule::$pluralize]]-属性来配置此项。
你可以访问你的API用 `curl` 命令如下,
```

30
docs/guide-zh-CN/rest-rate-limiting.md

@ -8,15 +8,15 @@
要启用速率限制, [[yii\web\User::identityClass|user identity class]] 应该实现 [[yii\filters\RateLimitInterface]].
这个接口需要实现以下三个方法:
* `getRateLimit()`: 返回允许的请求的最大数目及时间,例如,`[100, 600]` 表示在600秒内最多100次的API调用。
* `loadAllowance()`: 返回剩余的允许的请求和相应的UNIX时间戳数
当最后一次速率限制检查时
* `saveAllowance()`: 保存允许剩余的请求数和当前的UNIX时间戳。
* `getRateLimit()`: 返回允许的请求的最大数目及时间,例如,`[100, 600]` 表示在 600 秒内最多 100 次的 API 调用。
* `loadAllowance()`: 返回剩余的允许的请求和最后一次速率限制检查时
相应的 UNIX 时间戳数
* `saveAllowance()`: 保存剩余的允许请求数和当前的 UNIX 时间戳。
你可以在user表中使用两列来记录容差和时间戳信息。
`loadAllowance()``saveAllowance()` 可以通过实现对符合当前身份验证的用户
的这两列值的读和保存。为了提高性能,你也可以
考虑使用缓存或NoSQL存储这些信息。
你可以在 user 表中使用两列来记录容差和时间戳信息。
`loadAllowance()``saveAllowance()`
可以通过实现对符合当前身份验证的用户的这两列值的读和保存。
为了提高性能,你也可以考虑使用缓存或 NoSQL 存储这些信息。
Implementation in the `User` model could look like the following:
@ -39,12 +39,12 @@ public function saveAllowance($request, $action, $allowance, $timestamp)
}
```
一旦 identity 实现所需的接口, Yii 会自动使用 [[yii\filters\RateLimiter]]为 [[yii\rest\Controller]]
配置一个行为过滤器来执行速率限制检查。 如果速度超出限制该速率限制器将抛出一个 [[yii\web\TooManyRequestsHttpException]]。
你可以在你的 REST 控制器类里配置速率限制,
一旦 identity 实现所需的接口, Yii 会自动使用 [[yii\filters\RateLimiter]]
为 [[yii\rest\Controller]] 配置一个行为过滤器来执行速率限制检查。如果速度超出限制,
该速率限制器将抛出一个 [[yii\web\TooManyRequestsHttpException]]。你可以参考以下代码在你的 REST 控制器类里配置速率限制:
你可以在 user 表中使用两列来记录容差和时间戳信息。`loadAllowance()` 和 `saveAllowance()` 可以通过实现对符合当前身份
验证的用户的这两列值的读和保存。为了提高性能,你也可以考虑使用缓存或 NoSQL 存储这些信息。
You may configure the rate limiter
as follows in your REST controller classes:
```php
public function behaviors()
@ -55,8 +55,8 @@ public function behaviors()
}
```
当速率限制被激活,默认情况下每个响应将包含以下 HTTP
头发送目前的速率限制信息:
当速率限制被激活,默认情况下每个响应将包含以下
HTTP 头发送目前的速率限制信息:
* `X-Rate-Limit-Limit`: 同一个时间段所允许的请求的最大数目;
* `X-Rate-Limit-Remaining`: 在当前时间段内剩余的请求的数量;

98
docs/guide-zh-CN/rest-resources.md

@ -4,19 +4,19 @@
RESTful 的 API 都是关于访问和操作 *资源*,可将资源看成MVC模式中的
[模型](structure-models.md)
在如何代表一个资源没有固定的限定,在Yii中通常使用 [[yii\base\Model]]
或它的子类(如 [[yii\db\ActiveRecord]])
在如何代表一个资源没有固定的限定,在Yii中通常使用
[[yii\base\Model]] 或它的子类(如 [[yii\db\ActiveRecord]])
代表资源,是为以下原因:
* [[yii\base\Model]] 实现了 [[yii\base\Arrayable]] 接口,它允许你通过RESTful API
自定义你想要公开的资源数据。
* [[yii\base\Model]] 支持 [输入验证](input-validation.md), 在你的RESTful API
需要支持数据输入时非常有用。
* [[yii\base\Model]] 实现了 [[yii\base\Arrayable]] 接口,
它允许你通过RESTful API自定义你想要公开的资源数据。
* [[yii\base\Model]] 支持 [输入验证](input-validation.md),
在你的RESTful API需要支持数据输入时非常有用。
* [[yii\db\ActiveRecord]] 提供了强大的数据库访问和操作方面的支持,
如资源数据需要存到数据库它提供了完美的支持。
本节主要描述资源类如何从 [[yii\base\Model]] (或它的子类)
继承并指定哪些数据可通过RESTful API返回,如果资源类没有
本节主要描述资源类如何从 [[yii\base\Model]] (或它的子类) 继承
并指定哪些数据可通过RESTful API返回,如果资源类没有
继承 [[yii\base\Model]] 会将它所有的公开成员变量返回。
@ -30,9 +30,9 @@ Yii将这个过程分成两步,首先,资源会被[[yii\rest\Serializer]]转
通过覆盖 [[yii\base\Model::fields()|fields()]] 和/或
[[yii\base\Model::extraFields()|extraFields()]] 方法,
可指定资源中称为 *字段* 的数据放入展现数组中,两个方法的差别为前者指定默认包含到展现数组的字段集合,
后者指定由于终端用户的请求包含 `expand` 参数哪些额外的字段应被包含到展现数组
例如,
可指定资源中称为 *字段* 的数据放入展现数组中,
两个方法的差别为前者指定默认包含到展现数组的字段集合
后者指定由于终端用户的请求包含 `expand` 参数哪些额外的字段应被包含到展现数组,例如,
```
// 返回fields()方法中申明的所有字段
@ -54,15 +54,15 @@ http://localhost/users?fields=id,email&expand=profile
[[yii\base\Model::fields()]] 默认返回模型的所有属性作为字段,
[[yii\db\ActiveRecord::fields()]] 只返回和数据表关联的属性作为字段。
可覆盖 `fields()` 方法来增加、删除、重命名、重定义字段,`fields()` 的返回值应为数组,
数组的键为字段名数组的值为对应的字段定义,
可为属性名或返回对应的字段值的匿名函数,
可覆盖 `fields()` 方法来增加、删除、重命名、重定义字段,
`fields()` 的返回值应为数组,数组的键为字段名
数组的值为对应的字段定义,可为属性名或返回对应的字段值的匿名函数,
特殊情况下,如果字段名和属性名相同,
可省略数组的键,例如
```php
// 明确列出每个字段,适用于你希望数据表或模型属性
//修改时不导致你的字段修改(保持后端API兼容性)
// 明确列出每个字段,适用于你希望数据表或
// 模型属性修改时不导致你的字段修改(保持后端API兼容性)
public function fields()
{
return [
@ -77,8 +77,8 @@ public function fields()
];
}
// 过滤掉一些字段,适用于你希望继承父类
//实现同时你想屏蔽掉一些敏感字段
// 过滤掉一些字段,适用于你希望继承
// 父类实现同时你想屏蔽掉一些敏感字段
public function fields()
{
$fields = parent::fields();
@ -90,7 +90,7 @@ public function fields()
}
```
> 警告: 模型的所有属性默认会被包含到API结果中,
> Warning: 模型的所有属性默认会被包含到API结果中,
> 应检查数据确保没包含敏感数据,如果有敏感数据,
> 应覆盖`fields()`过滤掉,在上述例子中,我们选择过滤掉 `auth_key`,
> `password_hash``password_reset_token`.
@ -98,11 +98,11 @@ public function fields()
### 覆盖 `extraFields()` 方法 <span id="overriding-extra-fields"></span>
[[yii\base\Model::extraFields()]] 默认返回空值,[[yii\db\ActiveRecord::extraFields()]]
返回和数据表关联的属性。
[[yii\base\Model::extraFields()]] 默认返回空值,
[[yii\db\ActiveRecord::extraFields()]] 返回和数据表关联的属性。
`extraFields()` 返回的数据格式和 `fields()` 相同,一般`extraFields()`
主要用于指定哪些值为对象的字段,
`extraFields()` 返回的数据格式和 `fields()` 相同,
一般`extraFields()` 主要用于指定哪些值为对象的字段,
例如,给定以下字段申明
```php
@ -136,34 +136,52 @@ public function extraFields()
## 链接 <span id="links"></span>
[HATEOAS](http://en.wikipedia.org/wiki/HATEOAS),
Hypermedia as the Engine of Application State的缩写,
[HATEOAS](http://en.wikipedia.org/wiki/HATEOAS),
Hypermedia as the Engine of Application State的缩写,
提升RESTful API 应返回允许终端用户访问的资源操作的信息,
HATEOAS 的目的是在API中返回包含相关链接信息的资源数据。
资源类通过实现[[yii\web\Linkable]] 接口来支持HATEOAS,
该接口包含方法 [[yii\web\Linkable::getLinks()|getLinks()]] 来返回
[[yii\web\Link|links]] 列表,典型情况下应返回包含代表本资源对象URL的 `self` 链接,例如
[[yii\web\Link|links]] 列表,典型情况下应返回包含代表本资源对象URL的 `self` 链接,例如
```php
use yii\db\ActiveRecord;
use yii\web\Link;
use yii\base\Model;
use yii\web\Link; // represents a link object as defined in JSON Hypermedia API Language.
use yii\web\Linkable;
use yii\helpers\Url;
class User extends ActiveRecord implements Linkable
class UserResource extends Model implements Linkable
{
public $id;
public $email;
//...
public function fields()
{
return ['id', 'email'];
}
public function extraFields()
{
return ['profile'];
}
public function getLinks()
{
return [
Link::REL_SELF => Url::to(['user/view', 'id' => $this->id], true),
'edit' => Url::to(['user/view', 'id' => $this->id], true),
'profile' => Url::to(['user/profile/view', 'id' => $this->id], true),
'index' => Url::to(['users'], true),
];
}
}
```
当响应中返回一个`User` 对象,它会包含一个 `_links`
单元表示和用户相关的链接,例如
当响应中返回一个`User` 对象,
它会包含一个 `_links` 单元表示和用户相关的链接,例如
```
{
@ -173,6 +191,15 @@ class User extends ActiveRecord implements Linkable
"_links" => {
"self": {
"href": "https://example.com/users/100"
},
"edit": {
"href": "https://example.com/users/100"
},
"profile": {
"href": "https://example.com/users/profile/100"
},
"index": {
"href": "https://example.com/users"
}
}
}
@ -181,8 +208,8 @@ class User extends ActiveRecord implements Linkable
## 集合 <span id="collections"></span>
资源对象可以组成 *集合*每个集合包含一组相同
类型的资源对象。
资源对象可以组成 *集合*
每个集合包含一组相同类型的资源对象。
集合可被展现成数组,更多情况下展现成 [data providers](output-data-providers.md).
因为data providers支持资源的排序和分页,这个特性在 RESTful API 返回集合时也用到,
@ -207,8 +234,8 @@ class PostController extends Controller
}
```
当在RESTful API响应中发送data provider 时, [[yii\rest\Serializer]]
会取出资源的当前页并组装成资源对象数组,
当在RESTful API响应中发送data provider 时,
[[yii\rest\Serializer]] 会取出资源的当前页并组装成资源对象数组,
[[yii\rest\Serializer]] 也通过如下HTTP头包含页码信息:
* `X-Pagination-Total-Count`: 资源所有数量;
@ -218,3 +245,4 @@ class PostController extends Controller
* `Link`: 允许客户端一页一页遍历资源的导航链接集合.
可在[快速入门](rest-quick-start.md#trying-it-out) 一节中找到样例.

34
docs/guide-zh-CN/rest-response-formatting.md

@ -10,8 +10,8 @@
通过 [[yii\rest\Serializer]] 来完成。
3. 通过内容协商步骤将数组转换成字符串。
[[yii\web\ResponseFormatterInterface|response formatters]] 通过
[[yii\web\Response::formatters|response]]
[应用程序组件]((structure-application-components.md))来注册完成。
[[yii\web\Response::formatters|response]] 应用程序
组件来注册完成。
## 内容协商 <span id="content-negotiation"></span>
@ -155,3 +155,33 @@ Content-Type: application/json; charset=UTF-8
}
}
```
### Controlling JSON output
The JSON response is generated by the [[yii\web\JsonResponseFormatter|JsonResponseFormatter]] class which will
use the [[yii\helpers\Json|JSON helper]] internally. This formatter can be configured with different options like
for example the [[yii\web\JsonResponseFormatter::$prettyPrint|$prettyPrint]] option, which is useful on development for
better readable responses, or [[yii\web\JsonResponseFormatter::$encodeOptions|$encodeOptions]] to control the output
of the JSON encoding.
The formatter can be configured in the [[yii\web\Response::formatters|formatters]] property of the `response` application
component in the application [configuration](concept-configuration.md) like the following:
```php
'response' => [
// ...
'formatters' => [
\yii\web\Response::FORMAT_JSON => [
'class' => 'yii\web\JsonResponseFormatter',
'prettyPrint' => YII_DEBUG, // use "pretty" output in debug mode
'encodeOptions' => JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE,
// ...
],
],
],
```
When returning data from a database using the [DAO](db-dao.md) database layer all data will be represented
as strings, which is not always the expected result especially numeric values should be represented as
numbers in JSON. When using the ActiveRecord layer for retrieving data from the database, the values for numeric
columns will be converted to integers when data is fetched from the database in [[yii\db\ActiveRecord::populateRecord()]].

25
docs/guide-zh-CN/rest-routing.md

@ -73,9 +73,9 @@
]
```
您可能已经注意到控制器ID`user`以复数形式出现在`users`末端。这是因为 [[yii\rest\UrlRule]]
能够为他们使用的末端全自动复数化控制器ID。您可以通过设置 [[yii\rest\UrlRule::pluralize]]
为false 来禁用此行为,如果您想使用一些特殊的名字您可以通过配置 [[yii\rest\UrlRule::controller]] 属性。
您可能已经注意到控制器ID`user`以复数形式出现在`users`末端。这是因为 [[yii\rest\UrlRule]] 能够为他们使用的末端全自动复数化控制器ID。
您可以通过设置 [[yii\rest\UrlRule::pluralize]] 为false 来禁用此行为,如果您想
使用一些特殊的名字您可以通过配置 [[yii\rest\UrlRule::controller]] 属性。
> Info: The pluralization of controller IDs is done by [[yii\helpers\Inflector::pluralize()]]. The method respects
special pluralization rules. For example, the word `box` will be pluralized as `boxes` instead of `boxs`.
@ -90,3 +90,22 @@ a controller ID. For example, the following code maps the name `u` to the contro
'controller' => ['u' => 'user'],
]
```
## Extra configuration for contained rules
It could be useful to specify extra configuration that is applied to each rule contained within [[yii\rest\UrlRule]].
A good example would be specifying defaults for `expand` parameter:
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => ['user'],
'ruleConfig' => [
'class' => 'yii\web\UrlRule',
'defaults' => [
'expand' => 'profile',
]
],
],
```

4
docs/guide-zh-CN/rest-versioning.md

@ -70,10 +70,10 @@ api/
return [
'modules' => [
'v1' => [
'basePath' => '@app/modules/v1',
'class' => 'app\modules\v1\Module',
],
'v2' => [
'basePath' => '@app/modules/v2',
'class' => 'app\modules\v2\Module',
],
],
'components' => [

10
docs/guide-zh-CN/runtime-bootstrapping.md

@ -19,20 +19,20 @@
4. 通过调用 [[yii\base\Application::init()|init()]](初始化)方法,它会顺次调用
[[yii\base\Application::bootstrap()|bootstrap()]] 从而运行引导组件。
- 加载扩展清单文件(extension manifest file) `vendor/yiisoft/extensions.php`
- 创建并运行各个扩展声明的
- 创建并运行各个扩展声明的
[引导组件(bootstrap components)](structure-extensions.md#bootstrapping-classes)。
- 创建并运行各个 [应用组件](structure-application-components.md)
以及在应用的 [Bootstrap 属性](structure-applications.md#bootstrap)中声明的各个
[模块(modules)组件](structure-modules.md)(如果有)。
因为引导工作必须在处理**每一次**请求之前都进行一遍,
因此让该过程尽可能轻量化就异常重要,请尽可能地优化这一步骤。
因为引导工作必须在处理**每一次**请求之前都进行一遍,因此让该过程尽可能轻量化就异常重要,
请尽可能地优化这一步骤。
请尽量不要注册太多引导组件。只有他需要在 HTTP 请求处理的全部生命周期中都作用时才需要使用它。
举一个用到它的范例:一个模块需要注册额外的 URL 解析规则,就应该把它列在应用的
[bootstrap 属性](structure-applications.md#bootstrap)之中,
这样该 URL 解析规则才能在解析请求之前生效。
(译注:换言之,为了性能需要,除了 URL 解析等少量操作之外,绝大多数组件都应该按需加载,而不是都放在引导过程中。)
这样该 URL 解析规则才能在解析请求之前生效。(译注:换言之,为了性能需要,除了 URL
解析等少量操作之外,绝大多数组件都应该按需加载,而不是都放在引导过程中。)
在生产环境中,可以开启字节码缓存,比如 APC,
来进一步最小化加载和解析 PHP 文件所需的时间。

41
docs/guide-zh-CN/runtime-handling-errors.md

@ -7,7 +7,7 @@ Yii错误处理器做以下工作来提升错误处理效果:
* 所有非致命PHP错误(如,警告,提示)会转换成可获取异常;
* 异常和致命的PHP错误会被显示,
在调试模式会显示详细的函数调用栈和源代码行数。
* 支持使用专用的 [控制器](structure-controllers.md#actions) 来显示错误;
* 支持使用专用的 [控制器](structure-controllers.md#actions) 来显示错误;
* 支持不同的错误响应格式;
[[yii\web\ErrorHandler|error handler]] 错误处理器默认启用,
@ -48,10 +48,10 @@ try {
```
如果你想显示一个错误页面告诉用户请求是无效的或无法处理的,
可简单地抛出一个 [[yii\web\HttpException|HTTP exception]]异常,如 [[yii\web\NotFoundHttpException]]。
可简单地抛出一个 [[yii\web\HttpException|HTTP exception]]异常,
如 [[yii\web\NotFoundHttpException]]。
错误处理器会正确地设置响应的HTTP状态码并使用合适的错误视图页面来显示错误信息。
```php
use yii\web\NotFoundHttpException;
@ -61,14 +61,14 @@ throw new NotFoundHttpException();
## 自定义错误显示 <span id="customizing-error-display"></span>
[[yii\web\ErrorHandler|error handler]]错误处理器根据常量
`YII_DEBUG`的值来调整错误显示,当`YII_DEBUG` 为 true (表示在调试模式),
[[yii\web\ErrorHandler|error handler]]错误处理器根据常量`YII_DEBUG`的值来调整错误显示,
当`YII_DEBUG` 为 true (表示在调试模式),
错误处理器会显示异常以及详细的函数调用栈和源代码行数来帮助调试,
当`YII_DEBUG` 为 false,只有错误信息会被显示以防止应用的敏感信息泄漏。
> Info: 如果异常是继承 [[yii\base\UserException]],
不管`YII_DEBUG`为何值,函数调用栈信息都不会显示,
这是因为这种错误会被认为是用户产生的错误,开发人员不需要去修正。
不管`YII_DEBUG`为何值,函数调用栈信息都不会显示,
这是因为这种错误会被认为是用户产生的错误,开发人员不需要去修正。
[[yii\web\ErrorHandler|error handler]] 错误处理器默认使用两个[视图](structure-views.md)显示错误:
@ -82,7 +82,7 @@ throw new NotFoundHttpException();
### 使用错误动作 <span id="using-error-actions"></span>
使用指定的错误[作](structure-controllers.md) 来自定义错误显示更方便,
使用指定的错误[作](structure-controllers.md) 来自定义错误显示更方便,
为此,首先配置`errorHandler`组件的 [[yii\web\ErrorHandler::errorAction|errorAction]] 属性,
类似如下:
@ -97,8 +97,8 @@ return [
```
[[yii\web\ErrorHandler::errorAction|errorAction]] 属性使用
[路由](structure-controllers.md#routes)到一个作,
上述配置表示不用显示函数调用栈信息的错误会通过执行`site/error`作来显示。
[路由](structure-controllers.md#routes)到一个作,
上述配置表示不用显示函数调用栈信息的错误会通过执行`site/error`作来显示。
可以创建 `site/error` 动作如下所示:
@ -121,7 +121,7 @@ class SiteController extends Controller
}
```
上述代码定义 `error` 动作使用 [[yii\web\ErrorAction]] 类,
上述代码定义`error` 操作使用[[yii\web\ErrorAction]] 类,
该类渲染名为`error`视图来显示错误。
除了使用[[yii\web\ErrorAction]], 可定义`error` 动作使用类似如下的操作方法:
@ -141,8 +141,8 @@ public function actionError()
* `name`: 错误名称
* `message`: 错误信息
* `exception`: 更多详细信息的异常对象,如HTTP 状态码,错误码,
错误调用栈等。
* `exception`: 更多详细信息的异常对象,如HTTP 状态码,
错误码,错误调用栈等。
> Info: 如果你使用 [基础应用模板](start-installation.md) 或 [高级应用模板](tutorial-advanced-app.md),
错误动作和错误视图已经定义好了。
@ -153,14 +153,21 @@ public function actionError()
> return;
> ```
> Note: If you need to redirect in an error handler, do it the following way:
>
> ```php
> Yii::$app->getResponse()->redirect($url)->send();
> return;
> ```
### 自定义错误格式 <span id="error-format"></span>
错误处理器根据[响应](runtime-responses.md)设置的格式来显示错误,
如果[[yii\web\Response::format|response format]] 响应格式为`html`,
会使用错误或异常视图来显示错误信息,如上一小节所述。
对于其他的响应格式,错误处理器会错误信息作为数组赋值给[[yii\web\Response::data]]属性,
然后转换到对应的格式,
对于其他的响应格式,错误处理器会错误信息作为数组赋值
给[[yii\web\Response::data]]属性,然后转换到对应的格式,
例如,如果响应格式为`json`,可以看到如下响应信息:
```
@ -178,8 +185,8 @@ Content-Type: application/json; charset=UTF-8
}
```
可在应用配置中响应`response`组件的`beforeSend`
事件来自定义错误响应格式。
可在应用配置中响应`response`组件的
`beforeSend`事件来自定义错误响应格式。
```php
return [

4
docs/guide-zh-CN/runtime-overview.md

@ -6,8 +6,8 @@
1. 用户提交指向 [入口脚本](structure-entry-scripts.md) `web/index.php` 的请求。
2. 入口脚本会加载 [配置数组](concept-configurations.md) 并创建一个
[应用](structure-applications.md) 实例用于处理该请求。
3. 应用会通过 [request(请求)](runtime-requests.md)
应用组件解析被请求的 [路由](runtime-routing.md)。
3. 应用会通过 [request(请求)](runtime-requests.md) 应用组件
解析被请求的 [路由](runtime-routing.md)。
4. 应用创建一个 [controller(控制器)](structure-controllers.md) 实例具体处理请求。
5. 控制器会创建一个 [action(动作)](structure-controllers.md) 实例并为该动作执行相关的 Filters(访问过滤器)。
6. 如果任何一个过滤器验证失败,该动作会被取消。

49
docs/guide-zh-CN/runtime-responses.md

@ -5,7 +5,7 @@
响应对象包含的信息有HTTP状态码,HTTP头和主体内容等,
网页应用开发的最终目的本质上就是根据不同的请求构建这些响应对象。
在大多情况下主要处理继承自 [[yii\web\Response]] 的
在大多情况下主要处理继承自 [[yii\web\Response]] 的
`response` [应用组件](structure-application-components.md),
尽管如此,Yii也允许你创建你自己的响应对象并发送给终端用户,这方面后续会阐述。
@ -73,8 +73,8 @@ $headers->set('Pragma', 'no-cache');
$values = $headers->remove('Pragma');
```
> Info: 头名称是大小写敏感的,在[[yii\web\Response::send()]]
方法调用前新注册的头信息并不会发送给用户。
> Info: 头名称是大小写敏感的,在[[yii\web\Response::send()]]方法
调用前新注册的头信息并不会发送给用户。
## 响应主体 <span id="response-body"></span>
@ -107,8 +107,8 @@ Yii支持以下可直接使用的格式,每个实现了[[yii\web\ResponseForma
* [[yii\web\Response::FORMAT_JSONP|JSONP]]: 通过 [[yii\web\JsonResponseFormatter]]来实现.
* [[yii\web\Response::FORMAT_RAW|RAW]]: use this format if you want to send the response directly without applying any formatting.
上述响应主体可明确地被设置,但是在大多数情况下是通过 [操作](structure-controllers.md) 方法的返回值隐式地设置,
常用场景如下所示:
上述响应主体可明确地被设置,但是在大多数情况下是通过 [操作](structure-controllers.md)
方法的返回值隐式地设置,常用场景如下所示:
```php
public function actionIndex()
@ -117,12 +117,12 @@ public function actionIndex()
}
```
上述的 `index` 作返回 `index` 视图渲染结果,
上述的 `index` 作返回 `index` 视图渲染结果,
返回值会被 `response` 组件格式化后发送给终端用户。
因为响应格式默认为[[yii\web\Response::FORMAT_HTML|HTML]],
只需要在动作方法中返回一个字符串
如果想使用其他响应格式,应在返回数据前先设置格式,例如:
因为响应格式默认为[[yii\web\Response::FORMAT_HTML|HTML]], 只需要在操作方法中返回一个字符串,
如果想使用其他响应格式,应在返回数据前先设置格式
例如:
```php
public function actionInfo()
@ -136,7 +136,7 @@ public function actionInfo()
```
如上所述,触雷使用默认的 `response` 应用组件,也可创建自己的响应对象并发送给终端用户,
可在作方法中返回该响应对象,如下所示:
可在作方法中返回该响应对象,如下所示:
```php
public function actionInfo()
@ -159,12 +159,12 @@ public function actionInfo()
## 浏览器跳转 <span id="browser-redirection"></span>
浏览器跳转依赖于发送一个`Location` HTTP 头,
因为该功能通常被使用,Yii提供对它提供了特别的支持。
浏览器跳转依赖于发送一个`Location` HTTP 头,因为该功能通常被使用,
Yii提供对它提供了特别的支持。
可调用[[yii\web\Response::redirect()]] 方法将用户浏览器跳转到一个URL地址,该方法设置合适的
带指定URL的 `Location` 头并返回它自己为响应对象,
在动作的方法中,可调用缩写版[[yii\web\Controller::redirect()]],例如:
带指定URL的 `Location` 头并返回它自己为响应对象,在操作的方法中,
可调用缩写版[[yii\web\Controller::redirect()]],例如:
```php
public function actionOld()
@ -173,8 +173,8 @@ public function actionOld()
}
```
在如上代码中,作的方法返回`redirect()` 方法的结果,如前所述,
作的方法返回的响应对象会被当总响应发送给终端用户。
在如上代码中,作的方法返回`redirect()` 方法的结果,如前所述,
作的方法返回的响应对象会被当总响应发送给终端用户。
除了动作方法外,可直接调用[[yii\web\Response::redirect()]] 再调用
[[yii\web\Response::send()]] 方法来确保没有其他内容追加到响应中。
@ -184,19 +184,20 @@ public function actionOld()
```
> Info: [[yii\web\Response::redirect()]] 方法默认会设置响应状态码为302,该状态码会告诉浏览器请求的资源
*临时* 放在另一个URI地址上,
可传递一个301状态码告知浏览器请求的资源已经 *永久* 重定向到新的URId地址。
*临时* 放在另一个URI地址上,可传递一个301状态码告知浏览器请求
的资源已经 *永久* 重定向到新的URId地址。
如果当前请求为AJAX 请求,
发送一个 `Location` 头不会自动使浏览器跳转,为解决这个问题,
[[yii\web\Response::redirect()]] 方法设置一个值为要跳转的URL的`X-Redirect` 头,
在客户端可编写JavaScript 代码读取该头部值然后让浏览器跳转对应的URL。
在客户端可编写JavaScript
代码读取该头部值然后让浏览器跳转对应的URL。
> Info: Yii 配备了一个`yii.js` JavaScript 文件提供常用JavaScript功能,包括基于`X-Redirect`头的浏览器跳转,
> Info: Yii 配备了一个`yii.js` JavaScript 文件提供常用JavaScript功能,
包括基于`X-Redirect`头的浏览器跳转,
因此,如果你使用该JavaScript 文件(通过[[yii\web\YiiAsset]] 资源包注册),
就不需要编写AJAX跳转的代码。
## 发送文件 <span id="sending-files"></span>
和浏览器跳转类似,文件发送是另一个依赖指定HTTP头的功能,
@ -208,7 +209,7 @@ Yii提供方法集合来支持各种文件发送需求,它们对HTTP头都有
这些方法都将响应对象作为返回值,如果要发送的文件非常大,应考虑使用
[[yii\web\Response::sendStreamAsFile()]] 因为它更节约内存,
以下示例显示在控制器作中如何发送文件:
以下示例显示在控制器作中如何发送文件:
```php
public function actionDownload()
@ -217,8 +218,8 @@ public function actionDownload()
}
```
如果不是在动作方法中调用文件发送方法,
在后面还应调用 [[yii\web\Response::send()]] 没有其他内容追加到响应中。
如果不是在操作方法中调用文件发送方法,在后面还应调用
[[yii\web\Response::send()]] 没有其他内容追加到响应中。
```php
\Yii::$app->response->sendFile('path/to/file.txt')->send();

61
docs/guide-zh-CN/runtime-sessions-cookies.md

@ -9,7 +9,7 @@ Sessions 和 Cookies
## Sessions <span id="sessions"></span>
和 [请求](runtime-requests.md) 和 [响应](runtime-responses.md)类似,
默认可通过为[[yii\web\Session]] 实例的`session`
默认可通过为[[yii\web\Session]] 实例的`session`
[应用组件](structure-application-components.md) 来访问sessions。
@ -69,9 +69,9 @@ foreach ($session as $name => $value) ...
foreach ($_SESSION as $name => $value) ...
```
> 注意: 当使用`session`组件访问session数据时候,
如果session没有开启会自动开启,
这和通过`$_SESSION`不同,`$_SESSION`要求先执行`session_start()`。
> Info: 当使用`session`组件访问session数据时候,
如果session没有开启会自动开启,
这和通过`$_SESSION`不同,`$_SESSION`要求先执行`session_start()`。
当session数据为数组时,`session`组件会限制你直接修改数据中的单元项,
例如:
@ -137,7 +137,7 @@ Yii提供以下session类实现不同的session存储方式:
所有这些session类支持相同的API方法集,因此,
切换到不同的session存储介质不需要修改项目使用session的代码。
> 注意: 如果通过`$_SESSION`访问使用自定义存储介质的session,
> Note: 如果通过`$_SESSION`访问使用自定义存储介质的session,
需要确保session已经用[[yii\web\Session::open()]] 开启,
这是因为在该方法中注册自定义session存储处理器。
@ -174,10 +174,35 @@ CREATE TABLE session
- PostgreSQL: BYTEA
- MSSQL: BLOB
> 注意: 根据php.ini 设置的 `session.hash_function`,你需要调整`id`列的长度,
> Note: 根据 php.ini 设置的 `session.hash_function`,你需要调整`id`列的长度,
例如,如果 `session.hash_function=sha256`
应使用长度为64而不是40的char类型。
Alternatively, this can be accomplished with the following migration:
```php
<?php
use yii\db\Migration;
class m170529_050554_create_table_session extends Migration
{
public function up()
{
$this->createTable('{{%session}}', [
'id' => $this->char(64)->notNull(),
'expire' => $this->integer(),
'data' => $this->binary()
]);
$this->addPrimaryKey('pk-id', '{{%session}}', 'id');
}
public function down()
{
$this->dropTable('{{%session}}');
}
}
```
### Flash 数据 <span id="flash-data"></span>
@ -242,9 +267,9 @@ $alerts = $session->getFlash('alerts');
## Cookies <span id="cookies"></span>
Yii使用 [[yii\web\Cookie]]对象来代表每个cookie,[[yii\web\Request]] 和 [[yii\web\Response]]
通过名为'cookies'的属性维护一个cookie集合,
前者的cookie 集合代表请求提交的cookies,
Yii使用 [[yii\web\Cookie]]对象来代表每个cookie,
[[yii\web\Request]] 和 [[yii\web\Response]]
通过名为'cookies'的属性维护一个cookie集合,前者的cookie 集合代表请求提交的cookies,
后者的cookie集合表示发送给用户的cookies。
The part of the application dealing with request and response directly is controller. Therefore, cookies should be
@ -302,22 +327,22 @@ unset($cookies['language']);
[[yii\web\Cookie::domain|domain]], [[yii\web\Cookie::expire|expire]]
可配置这些属性到cookie中并添加到响应的cookie集合中。
> 注意: 为安全起见[[yii\web\Cookie::httpOnly]] 被设置为true,
这可减少客户端脚本访问受保护cookie(如果浏览器支持)的风险,
更多详情可阅读 [httpOnly wiki article](https://www.owasp.org/index.php/HttpOnly) for more details.
> Note: 为安全起见[[yii\web\Cookie::httpOnly]] 被设置为true,
这可减少客户端脚本访问受保护cookie(如果浏览器支持)的风险,
更多详情可阅读 [httpOnly wiki article](https://www.owasp.org/index.php/HttpOnly) for more details.
### Cookie验证 <span id="cookie-validation"></span>
在上两节中,当通过`request` 和 `response` 组件读取和发送cookie时,
你会喜欢扩展的cookie验证的保障安全功能,它能
使cookie不被客户端修改。该功能通过给每个cookie签发一个
哈希字符串来告知服务端cookie是否在客户端被修改,
如果被修改,通过`request`组件的[[yii\web\Request::cookies|cookie collection]]cookie集合访问不到该cookie。
使cookie不被客户端修改。该功能通过给每个cookie签发一个哈希字符串来告知服务端cookie是否在客户端被修改,
如果被修改,通过`request`组件的
[[yii\web\Request::cookies|cookie collection]]cookie集合访问不到该cookie。
> 注意: Cookie验证只保护cookie值被修改,如果一个cookie验证失败,
仍然可以通过`$_COOKIE`来访问该cookie,
因为这是第三方库对未通过cookie验证自定义的操作方式。
> Note: Cookie验证只保护cookie值被修改,如果一个cookie验证失败,
仍然可以通过`$_COOKIE`来访问该cookie,
因为这是第三方库对未通过cookie验证自定义的操作方式。
Cookie验证默认启用,可以设置[[yii\web\Request::enableCookieValidation]]属性为false来禁用它,
尽管如此,我们强烈建议启用它。

56
docs/guide-zh-CN/start-databases.md

@ -1,10 +1,10 @@
使用数据库
======================
本章节将介绍如何创建一个从数据表 `country` 中读取国家数据并显示出来的页面。
为了实现这个目标,你将会配置一个数据库连接,创建一个[活动记录](db-active-record.md)类,
并且创建一个[动作](structure-controllers.md)及一个[视图](structure-views.md)。
本章节将介绍如何如何创建一个从数据表 `country` 中读取国家数据并显示出来的页面。
为了实现这个目标,你将会配置一个数据库连接,
创建一个[活动记录](db-active-record.md)类,
并且创建一个[操作](structure-controllers.md)及一个[视图](structure-views.md)。
贯穿整个章节,你将会学到:
@ -20,8 +20,8 @@
准备数据库 <span id="preparing-database"></span>
--------------------
首先创建一个名为 `yii2basic` 的数据库,应用将从这个数据库中读取数据。你可以创建 SQLite,MySQL,PostregSQL,MSSQL 或 Oracle 数据库,
Yii 内置多种数据库支持。简单起见,后面的内容将以 MySQL 为例做演示。
首先创建一个名为 `yii2basic` 的数据库,应用将从这个数据库中读取数据。
你可以创建 SQLite,MySQL,PostregSQL,MSSQL 或 Oracle 数据库,Yii 内置多种数据库支持。简单起见,后面的内容将以 MySQL 为例做演示。
然后在数据库中创建一个名为 `country` 的表并插入简单的数据。可以执行下面的语句:
@ -51,7 +51,7 @@ INSERT INTO `country` VALUES ('US','United States',278357000);
开始之前,请确保你已经安装了 PHP [PDO](http://www.php.net/manual/en/book.pdo.php)
扩展和你所使用的数据库的 PDO 驱动(例如 MySQL 的 `pdo_mysql`)。
假如你的程序是使用关系型数据库,这是基本要求。
对于使用关系型数据库来讲,这是基本要求。
驱动和扩展安装可用后,打开 `config/db.php` 修改里面的配置参数对应你的数据库配置。
该文件默认包含这些内容:
@ -74,11 +74,11 @@ return [
上面配置的数据库连接可以在应用中通过 `Yii::$app->db` 表达式访问。
> 补充:`config/db.php` 将被包含在应用配置文件 `config/web.php` 中,
> Info: `config/db.php` 将被包含在应用配置文件 `config/web.php` 中,
后者指定了整个[应用](structure-applications.md)如何初始化。
请参考[配置](concept-configurations.md)章节了解更多信息。
如果你需要的不是Yii附带的数据库驱动,查阅以下的驱动:
If you need to work with databases support for which isn't bundled with Yii, check the following extensions:
- [Informix](https://github.com/edgardmessias/yii2-informix)
- [IBM DB2](https://github.com/edgardmessias/yii2-ibm-db2)
@ -106,8 +106,8 @@ class Country extends ActiveRecord
这个 `Country` 类继承自 [[yii\db\ActiveRecord]]。你不用在里面写任何代码。
只需要像现在这样,Yii 就能根据类名去猜测对应的数据表名。
> 注意:如果类名和数据表名不能直接对应,可以覆写 [[yii\db\ActiveRecord::tableName()|tableName()]]
方法去显式指定相关表名。
> Info: 如果类名和数据表名不能直接对应,
可以覆写 [[yii\db\ActiveRecord::tableName()|tableName()]] 方法去显式指定相关表名。
使用 `Country` 类可以很容易地操作 `country` 表数据,就像这段代码:
@ -128,17 +128,17 @@ $country->name = 'U.S.A.';
$country->save();
```
> 补充:活动记录是面向对象、功能强大的访问和操作数据库数据的方式。你可以在[活动记录](db-active-record.md)章节了解更多信息。
除此之外你还可以使用另一种更原生的被称做[数据访问对象](db-dao)的方法操作数据库数据。
> Info: 活动记录是面向对象、功能强大的访问和操作数据库数据的方式。你可以在[活动记录](db-active-record.md)章节了解更多信息。
除此之外你还可以使用另一种更原生的被称做[数据访问对象](db-dao)的方法操作数据库数据。
创建动作 <span id="creating-action"></span>
------------------
为了向最终用户显示国家数据,你需要创建一个动作。
相比之前小节掌握的在 `site` 控制器中创建动作,
为了向最终用户显示国家数据,你需要创建一个操作。相比之前小节掌握的在 `site` 控制器中创建操作,
在这里为所有和国家有关的数据新建一个控制器更加合理。
新控制器名为 `CountryController`,并在其中创建一个 `index` 动作,如下:
新控制器名为 `CountryController`,并在其中创建一个 `index` 操作,
如下:
```php
<?php
@ -175,7 +175,7 @@ class CountryController extends Controller
把上面的代码保存在 `controllers/CountryController.php` 文件中。
`index` 作调用了活动记录 `Country::find()` 方法,去生成查询语句并从 `country` 表中取回所有数据。
`index` 作调用了活动记录 `Country::find()` 方法,去生成查询语句并从 `country` 表中取回所有数据。
为了限定每个请求所返回的国家数量,查询在 [[yii\data\Pagination]] 对象的帮助下进行分页。
`Pagination` 对象的使命主要有两点:
@ -184,16 +184,16 @@ class CountryController extends Controller
* 在视图中显示一个由页码列表组成的分页器,
这点将在后面的段落中解释。
在代码末尾,`index` 作渲染一个名为 `index` 的视图,
在代码末尾,`index` 作渲染一个名为 `index` 的视图,
并传递国家数据和分页信息进去。
创建视图 <span id="creating-view"></span>
---------------
`views` 目录下先创建一个名为 `country` 的子目录。这个目录存储所有由 `country` 控制器渲染的视图。
`views/country` 目录下创建一个名为 `index.php` 的视图文件,
内容如下:
`views` 目录下先创建一个名为 `country` 的子目录。
这个目录存储所有由 `country` 控制器渲染的视图。在 `views/country` 目录下
创建一个名为 `index.php` 的视图文件,内容如下:
```php
<?php
@ -214,7 +214,7 @@ use yii\widgets\LinkPager;
```
这个视图包含两部分用以显示国家数据。第一部分遍历国家数据并以无序 HTML 列表渲染出来。
第二部分使用 [[yii\widgets\LinkPager]] 去渲染从作中传来的分页信息。
第二部分使用 [[yii\widgets\LinkPager]] 去渲染从作中传来的分页信息。
小部件 `LinkPager` 显示一个分页按钮的列表。
点击任何一个按钮都会跳转到对应的分页。
@ -230,8 +230,8 @@ http://hostname/index.php?r=country/index
![国家列表](images/start-country-list.png)
首先你会看到显示着五个国家的列表页面。在国家下面,
你还会看到一个包含四个按钮的分页器。如果你点击按钮 “2”,将会跳转到显示另外五个国家的页面,
首先你会看到显示着五个国家的列表页面。在国家下面,你还会看到一个包含四个按钮的分页器。
如果你点击按钮 “2”,将会跳转到显示另外五个国家的页面,
也就是第二页记录。如果观察仔细点你还会看到浏览器的 URL 变成了:
```
@ -242,13 +242,13 @@ http://hostname/index.php?r=country/index&page=2
* 首先 [[yii\data\Pagination|Pagination]] 把 SELECT 的子查询 `LIMIT 5 OFFSET 0` 数据表示成第一页。
因此开头的五条数据会被取出并显示。
* 然后小部件 [[yii\widgets\LinkPager|LinkPager]] 使用
* 然后小部件 [[yii\widgets\LinkPager|LinkPager]] 使用
[[yii\data\Pagination::createUrl()|Pagination::createUrl()]] 方法生成的 URL 去渲染翻页按钮。
URL 中包含必要的参数 `page` 才能查询不同的页面编号。
* 如果你点击按钮 “2”,将会发起一个路由为 `country/index` 的新请求。
[[yii\data\Pagination|Pagination]] 接收到 URL 中`page` 参数把当前的页码设为 2。
新的数据库请求将会以 `LIMIT 5 OFFSET 5`
查询并显示。
[[yii\data\Pagination|Pagination]] 接收到 URL 中
`page` 参数把当前的页码设为 2。
新的数据库请求将会以 `LIMIT 5 OFFSET 5` 查询并显示。
总结 <span id="summary"></span>

72
docs/guide-zh-CN/start-forms.md

@ -5,7 +5,7 @@
该页将显示一个包含 name 输入框和 email 输入框的表单。
当提交这两部分信息后,页面将会显示用户所输入的信息。
为了实现这个目标,除了创建一个[作](structure-controllers.md)和两个[视图](structure-views)外,
为了实现这个目标,除了创建一个[作](structure-controllers.md)和两个[视图](structure-views)外,
还需要创建一个[模型](structure-models.md)。
通过本教程,你将会学到:
@ -48,8 +48,8 @@ class EntryForm extends Model
该类继承自Yii 提供的一个基类 [[yii\base\Model]],
该基类通常用来表示数据。
> 补充:[[yii\base\Model]] 被用于普通模型类的父类并与数据表**无关**。[[yii\db\ActiveRecord]]
通常是普通模型类的父类但与数据表有关联(译注:[[yii\db\ActiveRecord]] 类其实也是继承自 [[yii\base\Model]],增加了数据库处理)。
> Info: [[yii\base\Model]] 被用于普通模型类的父类并与数据表**无关**。[[yii\db\ActiveRecord]]
通常是普通模型类的父类但与数据表有关联(译注:[[yii\db\ActiveRecord]] 类其实也是继承自 [[yii\base\Model]],增加了数据库处理)。
`EntryForm` 类包含 `name``email` 两个公共成员,
用来储存用户输入的数据。它还包含一个名为 `rules()` 的方法,
@ -59,8 +59,8 @@ class EntryForm extends Model
* `email` 的值必须满足email规则验证
如果你有一个处理用户提交数据的 `EntryForm` 对象,
你可以调用它的 [[yii\base\Model::validate()|validate()]] 方法触发数据验证。如果有数据验证失败,
将把 [[yii\base\Model::hasErrors|hasErrors]] 属性设为 ture,
你可以调用它的 [[yii\base\Model::validate()|validate()]] 方法触发数据验证。
如果有数据验证失败,将把 [[yii\base\Model::hasErrors|hasErrors]] 属性设为 ture,
想要知道具体发生什么错误就调用 [[yii\base\Model::getErrors|getErrors]]。
```php
@ -80,8 +80,8 @@ if ($model->validate()) {
创建动作 <span id="creating-action"></span>
------------------
下面你得在 `site` 控制器中创建一个 `entry` 作用于新建的模型。
作的创建和使用已经在[说一声你好](start-hello.md)小节中解释了。
下面你得在 `site` 控制器中创建一个 `entry` 作用于新建的模型。
作的创建和使用已经在[说一声你好](start-hello.md)小节中解释了。
```php
<?php
@ -114,30 +114,30 @@ class SiteController extends Controller
}
```
该动作首先创建了一个 `EntryForm` 对象。然后尝试从 `$_POST` 搜集用户提交的数据,
由 Yii 的 [[yii\web\Request::post()]] 方法负责搜集。如果模型被成功填充数据(比如:如果用户已经提交了 HTML 表单),
动作将调用 [[yii\base\Model::validate()|validate()]] 去确保用户提交的是有效数据。
该操作首先创建了一个 `EntryForm` 对象。然后尝试从 `$_POST` 搜集用户提交的数据,
由 Yii 的 [[yii\web\Request::post()]] 方法负责搜集。
如果模型被成功填充数据(也就是说用户已经提交了 HTML 表单),
操作将调用 [[yii\base\Model::validate()|validate()]] 去确保用户提交的是有效数据。
> 补充:表达式 `Yii::$app` 代表[应用](structure-applications.md)实例,
它是一个全局可访问的单例。同时它也是一个[服务定位器](concept-service-locator.md),
> Info: 表达式 `Yii::$app` 代表[应用](structure-applications.md)实例,它是一个全局可访问的单例。
同时它也是一个[服务定位器](concept-service-locator.md),
能提供 `request`,`response`,`db` 等等特定功能的组件。
在上面的代码里就是使用 `request` 组件来访问应用实例收到的 `$_POST` 数据。
如果一切都准备好了,用户提交表单后,动作将会渲染一个名为 `entry-confirm` 的视图去确认用户输入的数据。
如果没填表单就提交,或数据包含错误(译者:如 email 格式不对),`entry` 视图将会渲染输出,
连同表单一起输出的还有验证错误的详细信息。
用户提交表单后,操作将会渲染一个名为 `entry-confirm` 的视图去确认用户输入的数据。
如果没填表单就提交,或数据包含错误(译者:如 email 格式不对),
`entry` 视图将会渲染输出,连同表单一起输出的还有验证错误的详细信息。
> 注意:在这个简单例子里我们只是呈现了有效数据的确认页面。
实践中你应该考虑使用 [[yii\web\Controller::refresh()|refresh()]] 或 [[yii\web\Controller::redirect()|redirect()]]
去避免[表单重复提交问题](http://en.wikipedia.org/wiki/Post/Redirect/Get)。
> Note: 在这个简单例子里我们只是呈现了有效数据的确认页面。
实践中你应该考虑使用 [[yii\web\Controller::refresh()|refresh()]]
或 [[yii\web\Controller::redirect()|redirect()]] 去避免[表单重复提交问题](http://en.wikipedia.org/wiki/Post/Redirect/Get)。
创建视图 <span id="creating-views"></span>
--------------
最后创建两个视图文件 `entry-confirm``entry`
他们会被刚才创建的 `entry` 作渲染。
他们会被刚才创建的 `entry` 作渲染。
`entry-confirm` 视图简单地显示提交的 name 和 email 数据。视图文件应该保存在 `views/site/entry-confirm.php`
@ -173,12 +173,12 @@ use yii\widgets\ActiveForm;
<?php ActiveForm::end(); ?>
```
视图使用了一个功能强大的[小部件](structure-widgets.md) [[yii\widgets\ActiveForm|ActiveForm]] 去生成 HTML 表单。
视图使用了一个功能强大的[小部件](structure-widgets.md) [[yii\widgets\ActiveForm|ActiveForm]]
去生成 HTML 表单。
其中的 `begin()``end()` 分别用来渲染表单的开始和关闭标签。
在这两个方法之间使用了 [[yii\widgets\ActiveForm::field()|field()]] 方法去创建输入框。
第一个输入框用于 “name”,第二个输入框用于 “email”。
之后使用 [[yii\helpers\Html::submitButton()]]
方法生成提交按钮。
之后使用 [[yii\helpers\Html::submitButton()]] 方法生成提交按钮。
尝试下 <span id="trying-it-out"></span>
@ -196,7 +196,7 @@ http://hostname/index.php?r=site/entry
![验证错误的表单](images/start-form-validation.png)
输入有效的 name 和 email 信息并提交后,
你将会看到一个显示你所提交数据的新页面。
将会看到一个显示你所提交数据的确认页面。
![输入数据的确认页](images/start-entry-confirmation.png)
@ -204,31 +204,31 @@ http://hostname/index.php?r=site/entry
### 效果说明 <span id="magic-explained"></span>
你可能会好奇 HTML 表单暗地里是如何工作的呢,看起来它可以为每个输入框显示文字标签,
而当你没输入正确的信息时又不需要刷新页面就能给出错误提示
似乎有些神奇。
你可能会好奇 HTML 表单暗地里是如何工作的呢,
看起来它可以为每个输入框显示文字标签
而当你没输入正确的信息时又不需要刷新页面就能给出错误提示,似乎有些神奇。
是的,其实数据首先由客户端 JavaScript 脚本验证,然后才会提交给服务器通过 PHP 验证。
[[yii\widgets\ActiveForm]] 足够智能到把你在 `EntryForm` 模型中声明的验证规则转化成客户端 JavaScript 脚本去执行验证。
[[yii\widgets\ActiveForm]] 足够智能到把你在 `EntryForm`
模型中声明的验证规则转化成客户端 JavaScript 脚本去执行验证。
如果用户浏览器禁用了 JavaScript,
服务器端仍然会像 `actionEntry()` 方法里这样验证一遍数据。
这保证了任何情况下用户提交的数据都是有效的。
服务器端仍然会像 `actionEntry()` 方法里这样验证一遍数据。这保证了任何情况下用户提交的数据都是有效的。
> 警告:客户端验证是提高用户体验的手段。无论它是否正常启用,
服务端验证则都是必须的,请不要忽略它。
> Warning: 客户端验证是提高用户体验的手段。
无论它是否正常启用,服务端验证则都是必须的,请不要忽略它。
输入框的文字标签是 `field()` 方法生成的,内容就是模型中该数据的属性名。
例如模型中的 `name` 属性生成的标签就是 `Name`
你可以按如下方式
在视图中自定义标签
你可以在视图中自定义标签
按如下方法
```php
<?= $form->field($model, 'name')->label('自定义 Name') ?>
<?= $form->field($model, 'email')->label('自定义 Email') ?>
```
> 补充:Yii 提供了相当多类似的小部件去帮你生成复杂且动态的视图。
> Info: Yii 提供了相当多类似的小部件去帮你生成复杂且动态的视图。
在后面你还会了解到自己写小部件是多么简单。
你可能会把自己的很多视图代码转化成小部件以提高重用,加快开发效率。
@ -237,7 +237,7 @@ http://hostname/index.php?r=site/entry
-------
本章节指南中你接触了 MVC 设计模式的每个部分。
你已经学到了如何创建一个模型代表用户数据并验证它的有效性。
学到了如何创建一个模型代表用户数据并验证它的有效性。
你还学到了如何从用户那获取数据并在浏览器上回显给用户。
这本来是开发应用的过程中比较耗时的任务,

18
docs/guide-zh-CN/start-gii.md

@ -15,8 +15,8 @@
开始 Gii <span id="starting-gii"></span>
------------
[Gii](tool-gii.md) 是 Yii 中的一个[模块](structure-modules.md)。可以通过配置应用的 [[yii\base\Application::modules|modules]] 属性开启它。
通常来讲在 `config/web.php` 文件中会有以下配置代码:
[Gii](tool-gii.md) 是 Yii 中的一个[模块](structure-modules.md)。
可以通过配置应用的 [[yii\base\Application::modules|modules]] 属性开启它。通常来讲在 `config/web.php` 文件中会有以下配置代码:
```php
$config = [ ... ];
@ -45,7 +45,7 @@ defined('YII_ENV') or define('YII_ENV', 'dev');
http://hostname/index.php?r=gii
```
> 补充: 如果你通过本机以外的机器访问 Gii,请求会被出于安全原因拒绝。
> Info: 如果你通过本机以外的机器访问 Gii,请求会被出于安全原因拒绝。
> 你可以配置 Gii 为其添加允许访问的 IP 地址:
>
```php
@ -70,9 +70,9 @@ http://hostname/index.php?r=gii
然后点击 “Preview” 按钮。你会看到 `models/Country.php` 被列在将要生成的文件列表中。可以点击文件名预览内容。
如果你已经创建过同样的文件,
使用 Gii 会覆写它,
点击文件名旁边的 `diff` 能查看现有文件与将要生成的文件的内容区别。
如果你已经创建过同样的文件,使用 Gii 会覆写它,
点击文件名旁边的 `diff` 能查看现有文件与将要
生成的文件的内容区别。
![模型生成器预览](images/start-gii-model-preview.png)
@ -110,8 +110,8 @@ CRUD 代表增,查,改,删操作,这是绝大多数 Web 站点常用的
http://hostname/index.php?r=country/index
```
可以看到一个栅格显示着从数据表中读取的国家数据。
支持在列头对数据进行排序,输入筛选条件进行筛选。
可以看到一个栅格显示着从数据表中读取的国家数据。支持在列头对数据进行排序,
输入筛选条件进行筛选。
可以浏览详情,编辑,或删除栅格中的每个国家。
还可以点击栅格上方的 “Create Country” 按钮通过表单创建新国家。
@ -127,7 +127,7 @@ http://hostname/index.php?r=country/index
* 模型:`models/Country.php` 和 `models/CountrySearch.php`
* 视图:`views/country/*.php`
> 注意:Gii 被设计成高度可定制和可扩展的代码生成工具。
> Info: Gii 被设计成高度可定制和可扩展的代码生成工具。
使用它可以大幅提高应用开发速度。
请参考 [Gii](tool-gii.md) 章节了解更多内容。

92
docs/guide-zh-CN/start-hello.md

@ -1,9 +1,9 @@
说声 Hello
============
本章描述了如何在你的应用中创建一个新的 “Hello” 页面。
为了实现这一目标,
将会创建一个[动作](structure-controllers.md#creating-actions)和一个[视图](structure-views.md):
本章描述了如何在你的应用中创建一个新的 “Hello” 页面。为了实现这一目标,
将会创建一个[操作](structure-controllers.md#creating-actions)
和一个[视图](structure-views.md):
* 应用将会分派页面请求给动作
* 动作将会依次渲染视图呈现 “Hello” 给最终用户
@ -18,17 +18,17 @@
创建动作 <span id="creating-action"></span>
------------------
对于“Hello”任务,需要创建一个 `say` [](structure-controllers.md#creating-actions),
从请求中接收 `message` 参数并显示给最终用户。如果请求没有提供 `message` 参数,
作将显示默认参数 “Hello”。
为了 “Hello”,需要创建一个 `say` [](structure-controllers.md#creating-actions),
从请求中接收 `message` 参数并显示给最终用户。
如果请求没有提供 `message` 参数,操作将显示默认参数 “Hello”。
> 注意:[动作](structure-controllers.md#creating-actions)是最终用户可以直接访问并执行的对象。
作被组织在[控制器](structure-controllers.md)中。
一个作的执行结果就是最终用户收到的响应内容。
> Info: [操作](structure-controllers.md#creating-actions)是最终用户可以直接访问并执行的对象。
作被组织在[控制器](structure-controllers.md)中。
一个作的执行结果就是最终用户收到的响应内容。
作必须声明在[控制器](structure-controllers.md)中。为了简单起见,
你可以在现存的 `SiteController` 控制器里声明 `say` 动作。这个控制器定义在 `controllers/SiteController.php` 类文件中
以下是一个动作的声明:
作必须声明在[控制器](structure-controllers.md)中。为了简单起见,
你可以直接`SiteController` 控制器里声明 `say` 操作
这个控制器是由文件 `controllers/SiteController.php` 定义的。以下是一个操作的声明:
```php
<?php
@ -48,25 +48,25 @@ class SiteController extends Controller
}
```
在上述 `SiteController` 代码中,`say` 作被定义为 `actionSay` 方法。
Yii 使用 `action` 前缀区分普通方法和作。
`action` 前缀后面的名称被映射为作的 ID。
在上述 `SiteController` 代码中,`say` 作被定义为 `actionSay` 方法。
Yii 使用 `action` 前缀区分普通方法和作。
`action` 前缀后面的名称被映射为作的 ID。
涉及到给作命名时,你应该理解 Yii 如何处理操作 ID。
作 ID 总是被以小写处理,如果一个操作 ID 由多个单词组成,
单词之间将由破折号连接(如 `create-comment`)。动作 ID 映射为方法名时移除了破折号,
将每个单词首字母大写,并加上 `action` 前缀。
比如:动作 ID `create-comment` 对应方法名 `actionCreateComment`
涉及到给作命名时,你应该理解 Yii 如何处理操作 ID。
作 ID 总是被以小写处理,如果一个操作 ID 由多个单词组成,
单词之间将由连字符连接(如 `create-comment`)。
操作 ID 映射为方法名时移除了连字符,将每个单词首字母大写,并加上 `action` 前缀。
例子:操作 ID `create-comment` 相当于方法名 `actionCreateComment`
上述代码中的作方法接受一个参数 `$message`
上述代码中的作方法接受一个参数 `$message`
它的默认值是 `“Hello”`(就像你设置 PHP 中其它函数或方法的默认值一样)。
当应用接收到请求并确定由 `say` 作来响应请求时,应用将从请求的参数中寻找对应值传入进来。
换句话说,如果请求包含一个 `message` 参数,它的值是 `“Goodybye”`
动作方法中的 `$message` 变量也将赋值`“Goodbye”`
当应用接收到请求并确定由 `say` 作来响应请求时,应用将从请求的参数中寻找对应值传入进来。
换句话说,如果请求包含一个 `message` 参数,
它的值是 `“Goodybye”`, 操作方法中的 `$message` 变量也将被填充`“Goodbye”`
作方法中,[[yii\web\Controller::render()|render()]] 被用来渲染一个名为
`say` 的[视图](structure-views.md)文件。
`message` 参数也被传入视图,这样就可以在里面使用。作方法会返回渲染结果。
作方法中,[[yii\web\Controller::render()|render()]] 被用来渲染一个
名为 `say` 的[视图](structure-views.md)文件。
`message` 参数也被传入视图,这样就可以在里面使用。作方法会返回渲染结果。
结果会被应用接收并显示给最终用户的浏览器(作为整页 HTML 的一部分)。
@ -74,7 +74,7 @@ Yii 使用 `action` 前缀区分普通方法和动作。
---------------
[视图](structure-views.md)是你用来生成响应内容的脚本。为了说 “Hello”,
你需要创建一个 `say` 视图,以便显示从作方法中传来的 `message` 参数。
你需要创建一个 `say` 视图,以便显示从作方法中传来的 `message` 参数。
```php
<?php
@ -83,12 +83,12 @@ use yii\helpers\Html;
<?= Html::encode($message) ?>
```
`say` 视图应该存为 `views/site/say.php` 文件。当一个作中调用了 [[yii\web\Controller::render()|render()]] 方法时,
它将会寻找名为 `views/控制器 ID/视图名.php` 的PHP文件。
`say` 视图应该存为 `views/site/say.php` 文件。当一个作中调用了 [[yii\web\Controller::render()|render()]] 方法时,
它将会`views/控制器 ID/视图名.php` 路径加载 PHP 文件
注意以上代码,`message` 参数在输出之前被 [[yii\helpers\Html::encode()|HTML-encoded]] 方法处理过。
这很有必要,当参数来自于最终用户时,
参数中可能隐含的恶意 JavaScript 代码会导致
注意以上代码,`message` 参数在输出之前被
[[yii\helpers\Html::encode()|HTML-encoded]] 方法处理过。
这很有必要,当参数来自于最终用户时,参数中可能隐含的恶意 JavaScript 代码会导致
[跨站脚本(XSS)攻击](http://en.wikipedia.org/wiki/Cross-site_scripting)。
当然了,你大概会在 `say` 视图里放入更多内容。内容可以由 HTML 标签,纯文本,
@ -112,31 +112,31 @@ http://hostname/index.php?r=site/say&message=Hello+World
如果你省略 URL 中的 `message` 参数,将会看到页面只显示 “Hello”。
这是因为 `message` 被作为一个参数传给 `actionSay()` 方法,当省略它时,参数将使用默认的 `“Hello”` 代替。
> 注意:新页面和其它页面使用同样的头部和尾部是因为 [[yii\web\Controller::render()|render()]] 方法会
自动把 `say` 视图执行的结果嵌入称为[布局](structure-views.md#layouts)的文件中,
位于 `views/layouts/main.php`
> Info: 新页面和其它页面使用同样的头部和尾部是因为 [[yii\web\Controller::render()|render()]]
方法会自动把 `say` 视图执行的结果嵌入称为[布局](structure-views.md#layouts)的文件中,
本例中是 `views/layouts/main.php`
上面 URL 中的参数 `r` 需要更多解释。
它代表[路由](runtime-routing.md),是整个应用级的,
指向特定作的独立 ID。路由格式是 `控制器 ID/操作 ID`。应用接受请求的时候会检查参数,
指向特定作的独立 ID。路由格式是 `控制器 ID/操作 ID`。应用接受请求的时候会检查参数,
使用控制器 ID 去确定哪个控制器应该被用来处理请求。
然后相应控制器将使用作 ID 去确定哪个操作方法将被用来做具体工作。
在本例子中,路由 `site/say` 将被解析至 `SiteController` 控制器和其中的 `say` 作。
然后相应控制器将使用作 ID 去确定哪个操作方法将被用来做具体工作。
上述例子中,路由 `site/say` 将被解析至 `SiteController` 控制器和其中的 `say` 作。
因此 `SiteController::actionSay()` 方法将被调用处理请求。
> 注意:与动作一样,一个应用中控制器同样有唯一的 ID。
控制器 ID 和作 ID 使用同样的命名规则。
控制器的类名源自于控制器 ID,移除了破折号
,每个单词首字母大写,并加上 `Controller` 后缀。
例子:控制器 ID `post-comment` 对应控制器类名 `PostCommentController`
> Info: 与操作一样,一个应用中控制器同样有唯一的 ID。
控制器 ID 和作 ID 使用同样的命名规则。
控制器的类名源自于控制器 ID,
移除了连字符,每个单词首字母大写,并加上 `Controller` 后缀。
例子:控制器 ID `post-comment` 相当于控制器类名 `PostCommentController`
总结 <span id="summary"></span>
-------
通过本章节你接触了 MVC 设计模式中的控制器和视图部分。
创建了一个作作为控制器的一部分去处理特定请求。然后又创建了一个视图去构造响应内容
在这个小例子中,没有模型调用,唯一涉及到数据的地方是 `message` 参数。
创建了一个作作为控制器的一部分去处理特定请求。
然后又创建了一个视图去构造响应内容。在这个小例子中,没有模型调用,唯一涉及到数据的地方是 `message` 参数。
你同样学习了 Yii 路由的相关内容,它是用户请求与控制器动作之间的桥梁。

8
docs/guide-zh-CN/start-installation.md

@ -21,8 +21,10 @@ Yii当然也提供了其它模板叫
通过 Composer 安装 <span id="installing-via-composer"></span>
-----------------------
### Installing Composer
如果还没有安装 Composer,你可以按 [getcomposer.org](https://getcomposer.org/download/) 中的方法安装。
在 Linux 和 Mac OS X 中,你可以运行如下命令:
在 Linux 和 Mac OS X 中可以运行如下命令:
```bash
curl -sS https://getcomposer.org/installer | php
@ -31,8 +33,8 @@ mv composer.phar /usr/local/bin/composer
在 Windows 中,你需要下载并运行 [Composer-Setup.exe](https://getcomposer.org/Composer-Setup.exe)。
如果遇到任何问题或者想更深入地学习 Composer,
请参考 [Composer 文档(英文)](https://getcomposer.org/doc/),[Composer 中文](https://github.com/5-say/composer-doc-cn)。
如果遇到任何问题或者想更深入地学习 Composer,请参考 [Composer 文档(英文)](https://getcomposer.org/doc/),
[Composer 中文](https://github.com/5-say/composer-doc-cn)。
如果你已经安装有 Composer 请确保使用的是最新版本,
你可以用 `composer self-update` 命令更新 Composer 为最新版本。

28
docs/guide-zh-CN/start-looking-ahead.md

@ -1,29 +1,29 @@
更上一层楼
=============
假如你已经阅读完整个“入门”部分,你就完成了一个完整 Yii 应用的创建。
在此过程中你学到了如何实现一些常用功能,例如通过 HTML 表单从用户那获取数据,
从数据库中获取数据并以分页形式显示。你还学到了如何通过 [Gii](tool-gii.md) 去自动生成代码。
通篇阅读完整个“入门”部分,你就完成了一个完整 Yii 应用的创建。在此过程中你学到了如何实现一些常用功能,
例如通过 HTML 表单从用户那获取数据,从数据库中获取数据并以分页形式显示。
你还学到了如何通过 [Gii](tool-gii.md) 去自动生成代码。
使用 Gii 生成代码把 Web 开发中多数繁杂的过程转化为仅仅填写几个表单就行。
本章将介绍一些有助于更好使用 Yii 的资源:
* 文档
- 权威指南:顾名思义,
指南详细描述了 Yii 的工作原理并提供了如何使用它的常规引导。
- 权威指南:顾名思义,指南详细描述了 Yii 的工作原理
并提供了如何使用它的常规引导。
这是最重要的 Yii 辅助资料,
强烈建议在开始写 Yii 代码之前阅读。
- 类参考手册:描述了 Yii 中每个类的用法。在编码过程中这极为有用,
能够帮你理清某个特定类,方法,和属性的用法。
类参考手册最好在整个框架的语境下去理解。
- [Wiki 文章](http://www.yiiframework.com/wiki/?tag=yii2):Wiki 文章是 Yii 用户在其自身经验基础上分享出来的。
- 类参考手册:描述了 Yii 中每个类的用法。
在编码过程中这极为有用,能够帮你理清某个特定类,
方法,和属性的用法。类参考手册最好在整个框架的语境下去理解。
- Wiki 文章:Wiki 文章是 Yii 用户在其自身经验基础上分享出来的。
大多数是使用教程或如何使用 Yii 解决特定问题。
虽然这些文章质量可能并不如权威指南,
但它们往往覆盖了更广泛的话题,
并常常提供解决方案,所以它们也很有用。
- [书籍](http://www.yiiframework.com/doc/)
* [扩展](http://www.yiiframework.com/extensions/):Yii 拥有数以千计用户提供的扩展,
这些扩展能非常方便的插入到应用中,使你的应用开发过程更加方便快捷。
但它们往往覆盖了更广泛的话题,并常常提供解决方案,
所以它们也很有用。
- 书籍
* [扩展](http://www.yiiframework.com/extensions/):Yii 拥有数以千计用户提供的扩展,这些扩展能非常方便的插入到应用中,
使你的应用开发过程更加方便快捷。
* 社区
- 官方论坛:<http://www.yiiframework.com/forum/>
- IRC 聊天室:Freenode 网络上的 #yii 频道 (<irc://irc.freenode.net/yii>)

20
docs/guide-zh-CN/start-workflow.md

@ -32,7 +32,7 @@
在浏览器底部可以看到一个工具栏。这是 Yii 提供的很有用的[调试工具](tool-debugger.md),
可以记录并显示大量的调试信息,例如日志信息,响应状态,数据库查询等等。
除了web应用程序,还有一个控制台脚步`yii` ,它位于应用程序根目录。
除了 web 应用程序,还有一个控制台脚本`yii` ,它位于应用程序根目录。
它可以用于程序的后台运行和维护任务,在[控制台应用程序章节](tutorial-console.md)
中描述。
@ -72,11 +72,11 @@ Yii 实现了[模型-视图-控制器 (MVC)](http://wikipedia.org/wiki/Model-vie
![应用静态结构](images/application-structure.png)
每个应用都有一个入口脚本 `web/index.php`
这是整个应用中唯一可以访问的 PHP 脚本。
入口脚本接受一个 Web 请求并创建[应用](structure-application.md)实例去处理它。
[应用](structure-applications.md)在它的[组件](concept-components.md)辅助下解析请求,
并分派请求至 MVC 元素。[视图](structure-views.md)使用[小部件](structure-widgets.md)去创建复杂和动态的用户界面。
每个应用都有一个入口脚本 `web/index.php`这是整个应用中唯一可以访问的 PHP 脚本。
入口脚本接受一个 Web 请求并创建[应用](structure-application.md)实例去处理它。
[应用](structure-applications.md)在它的[组建](concept-components.md)辅助下解析请求,
并分派请求至 MVC 元素。[视图](structure-views.md)使用[小部件](structure-widgets.md)
去创建复杂和动态的用户界面。
请求生命周期 <span id="request-lifecycle"></span>
@ -87,10 +87,10 @@ Yii 实现了[模型-视图-控制器 (MVC)](http://wikipedia.org/wiki/Model-vie
![请求生命周期](images/request-lifecycle.png)
1. 用户向[入口脚本](structure-entry-scripts.md) `web/index.php` 发起请求。
2. 入口脚本加载应用[配置](concept-configurations.md)
并创建一个[应用](structure-applications.md)实例去处理请求。
3. 应用通过[请求](runtime-request.md)组件
解析请求的[路由](runtime-routing.md)。
2. 入口脚本加载应用[配置](concept-configurations.md)并创建一个[应用](structure-applications.md)
实例去处理请求。
3. 应用通过[请求](runtime-request.md)组件解析请求的
[路由](runtime-routing.md)。
4. 应用创建一个[控制器](structure-controllers.md)实例去处理请求。
5. 控制器创建一个[动作](structure-controllers.md)实例并针对操作执行过滤器。
6. 如果任何一个过滤器返回失败,则动作取消。

34
docs/guide-zh-CN/structure-application-components.md

@ -19,8 +19,8 @@
第一次使用以上表达式时候会创建应用组件实例,
后续再访问会返回此实例,无需再次创建。
应用组件可以是任意对象,可以在
[应用主体配置](structure-applications.md#application-configurations)配置 [[yii\base\Application::components]] 属性 .
应用组件可以是任意对象,可以在 [应用主体配置](structure-applications.md#application-configurations)配置
[[yii\base\Application::components]] 属性 .
例如:
```php
@ -45,7 +45,7 @@
]
```
> 补充:请谨慎注册太多应用组件,
> Info: 请谨慎注册太多应用组件,
应用组件就像全局变量,
使用太多可能加大测试和维护的难度。
一般情况下可以在需要时再创建本地组件。
@ -58,17 +58,26 @@
有时你想在每个请求处理过程都实例化某个组件即便它不会被访问,
可以将该组件ID加入到应用主体的 [[yii\base\Application::bootstrap|bootstrap]] 属性中。
You can also use Closures to bootstrap customized components. Returning a instantiated component is not
required. A Closure can also be used simply for running code after [[yii\base\Application]] instantiation.
例如, 如下的应用主体配置保证了 `log` 组件一直被加载。
```php
[
'bootstrap' => [
// 将 log 组件 ID 加入引导让它始终载入
'log',
function($app){
return new ComponentX();
},
function($app){
// some code
return;
}
],
'components' => [
'log' => [
// "log" 组件的配置
// configuration for "log" component
],
],
]
@ -77,14 +86,15 @@
## 核心应用组件 <span id="core-application-components"></span>
Yii 定义了一组固定ID和默认配置的 *核心* 组件,例如 [[yii\web\Application::request|request]] 组件
Yii 定义了一组固定ID和默认配置的 *核心* 组件,
例如 [[yii\web\Application::request|request]] 组件
用来收集用户请求并解析 [路由](runtime-routing.md);
[[yii\base\Application::db|db]] 代表一个可以执行数据库操作的数据库连接。
通过这些组件,Yii应用主体能处理用户请求。
下面是预定义的核心应用组件列表,可以和普通应用组件一样配置和自定义它们。
当你配置一个核心组件,
不指定它的类名的话就会使用Yii默认指定的类。
下面是预定义的核心应用组件列表,
可以和普通应用组件一样配置和自定义它们。
当你配置一个核心组件,不指定它的类名的话就会使用Yii默认指定的类。
* [[yii\web\AssetManager|assetManager]]: 管理资源包和资源发布,
详情请参考 [管理资源](output-assets.md) 一节。
@ -94,9 +104,9 @@ Yii 定义了一组固定ID和默认配置的 *核心* 组件,例如 [[yii\web
详情请参考 [数据访问对象](db-dao.md) 一节。
* [[yii\base\Application::errorHandler|errorHandler]]: 处理 PHP 错误和异常,
详情请参考 [错误处理](tutorial-handling-errors.md) 一节。
* [[yii\i18n\Formatter|formatter]]: 格式化输出显示给终端用户的数据,
例如数字可能要带分隔符,
日期使用长格式。详情请参考 [格式化输出数据](output-formatting.md) 一节。
* [[yii\i18n\Formatter|formatter]]: 格式化输出显示给终端用户的数据,例如数字可能要带分隔符,
日期使用长格式。
详情请参考 [格式化输出数据](output-formatting.md) 一节。
* [[yii\i18n\I18N|i18n]]: 支持信息翻译和格式化。
详情请参考 [国际化](tutorial-i18n.md) 一节。
* [[yii\log\Dispatcher|log]]: 管理日志对象。

112
docs/guide-zh-CN/structure-applications.md

@ -2,8 +2,8 @@
============
应用主体是管理 Yii 应用系统整体结构和生命周期的对象。
每个Yii应用系统只能包含一个应用主体,
应用主体在 [入口脚本](structure-entry-scripts.md) 中创建并能通过表达式 `\Yii::$app` 全局范围内访问。
每个Yii应用系统只能包含一个应用主体,应用主体在
[入口脚本](structure-entry-scripts.md) 中创建并能通过表达式 `\Yii::$app` 全局范围内访问。
> Info: 当我们说"一个应用",它可能是一个应用主体对象,也可能是一个应用系统,
是根据上下文来决定[译:中文为避免歧义,Application翻译为应用主体]。
@ -29,30 +29,30 @@ $config = require(__DIR__ . '/../config/web.php');
(new yii\web\Application($config))->run();
```
类似其他 [配置](concept-configurations.md) 文件,
类似其他 [配置](concept-configurations.md) 文件,
应用主体配置文件标明如何设置应用对象初始属性。
由于应用主体配置比较复杂,
一般保存在多个类似如上web.php的 [配置文件](concept-configurations.md#configuration-files) 当中。
由于应用主体配置比较复杂,一般保存在多个类似如上web.php的
[配置文件](concept-configurations.md#configuration-files) 当中。
## 应用主体属性 <span id="application-properties"></span>
应用主体配置文件中有许多重要的属性要配置,
这些属性指定应用主体的运行环境。
应用主体配置文件中有许多重要的属性要配置,这些属性指定应用主体的运行环境。
比如,应用主体需要知道如何加载 [控制器](structure-controllers.md) ,
临时文件保存到哪儿等等。以下我们简述这些属性。
临时文件保存到哪儿等等。
以下我们简述这些属性。
### 必要属性 <span id="required-properties"></span>
在一个应用中,至少要配置2个属性:
在一个应用中,至少要配置2个属性:
[[yii\base\Application::id|id]] 和 [[yii\base\Application::basePath|basePath]]。
#### [[yii\base\Application::id|id]] <span id="id"></span>
[[yii\base\Application::id|id]] 属性用来区分其他应用的唯一标识ID。
主要给程序使用。为了方便协作,最好使用数字作为应用主体ID,
[[yii\base\Application::id|id]] 属性用来区分其他应用的唯一标识ID。主要给程序使用。
为了方便协作,最好使用数字作为应用主体ID,
但不强制要求为数字。
@ -60,7 +60,7 @@ $config = require(__DIR__ . '/../config/web.php');
[[yii\base\Application::basePath|basePath]] 指定该应用的根目录。
根目录包含应用系统所有受保护的源代码。
在根目录下可以看到对应MVC设计模式的`models`,
在根目录下可以看到对应MVC设计模式的`models`,
`views`, `controllers`等子目录。
可以使用路径或 [路径别名](concept-aliases.md) 来在配置 [[yii\base\Application::basePath|basePath]] 属性。
@ -99,9 +99,9 @@ $config = require(__DIR__ . '/../config/web.php');
#### [[yii\base\Application::bootstrap|bootstrap]] <span id="bootstrap"></span>
这个属性很实用,它允许你用数组指定启动阶段
[[yii\base\Application::bootstrap()|bootstrapping process]]需要运行的组件。
比如,如果你希望一个 [模块](structure-modules.md) 自定义 [URL 规则](runtime-url-handling.md),
这个属性很实用,它允许你用数组指定启动阶段[[yii\base\Application::bootstrap()|bootstrapping process]]需要运行的组件。
比如,如果你希望一个 [模块](structure-modules.md)
自定义 [URL 规则](runtime-url-handling.md),
你可以将模块ID加入到bootstrap数组中。
属性中的每个组件需要指定以下一项:
@ -137,8 +137,8 @@ $config = require(__DIR__ . '/../config/web.php');
]
```
> Info: 如果模块ID和应用组件ID同名,
> 优先使用应用组件ID,如果你想用模块ID,
> Info: 如果模块ID和应用组件ID同名,优先使用应用组件ID,
> 如果你想用模块ID,
> 可以使用如下无名称函数返回模块ID。
>
> ```php
@ -150,12 +150,12 @@ $config = require(__DIR__ . '/../config/web.php');
```
在启动阶段,每个组件都会实例化。
如果组件类实现接口 [[yii\base\BootstrapInterface]],
也会调用 [[yii\base\BootstrapInterface::bootstrap()|bootstrap()]] 方法。
在启动阶段,每个组件都会实例化。如果组件类实现接口
[[yii\base\BootstrapInterface]],也会调用
[[yii\base\BootstrapInterface::bootstrap()|bootstrap()]] 方法。
举一个实际的例子,
[Basic Application Template](start-installation.md) 应用主体配置中,
举一个实际的例子,[Basic Application Template](start-installation.md)
应用主体配置中,
开发环境下会在启动阶段运行 `debug``gii` 模块。
```php
@ -169,8 +169,8 @@ if (YII_ENV_DEV) {
}
```
> 注: 启动太多的组件会降低系统性能,
因为每次请求都需要重新运行启动组件,因此谨慎配置启动组件。
> 注: 启动太多的组件会降低系统性能,因为每次请求都需要重新运行启动组件,
> 因此谨慎配置启动组件。
#### [[yii\web\Application::catchAll|catchAll]] <span id="catchAll"></span>
@ -179,8 +179,8 @@ if (YII_ENV_DEV) {
它指定一个要处理所有用户请求的 [控制器方法](structure-controllers.md),
通常在维护模式下使用,同一个方法处理所有用户请求。
该配置为一个数组,第一项指定动作的路由,
剩下的数组项(key-value 成对)指定传递给动作的参数,例如:
该配置为一个数组,第一项指定动作的路由,剩下的数组项(key-value 成对)指定传递给动作的参数,
例如:
```php
[
@ -192,11 +192,11 @@ if (YII_ENV_DEV) {
]
```
> Info: Debug panel on development environment will not work when this property is enabled
> Info: Debug panel on development environment will not work when this property is enabled.
#### [[yii\base\Application::components|components]] <span id="components"></span>
这是最重要的属性,它允许你注册多个在其他地方使用的[应用组件](#structure-application-components.md)
这是最重要的属性,它允许你注册多个在其他地方使用的[应用组件](#structure-application-components.md).
例如
```php
@ -216,8 +216,8 @@ if (YII_ENV_DEV) {
每一个应用组件指定一个key-value对的数组,key代表组件ID,
value代表组件类名或 [配置](concept-configurations.md)。
在应用中可以任意注册组件,
并可以通过表达式 `\Yii::$app->ComponentID` 全局访问。
在应用中可以任意注册组件,并可以通过表达式
`\Yii::$app->ComponentID` 全局访问。
详情请阅读 [应用组件](structure-application-components.md) 一节.
@ -253,11 +253,11 @@ Yii遵循一个默认的 [规则](#controllerNamespace)指定控制器ID到任
类全名为 `app\controllers\PostController`
控制器类文件可能放在这个命名空间对应目录的子目录下,
例如,控制器ID `admin/post` 对应的控制器类全名为
例如,控制器ID `admin/post` 对应的控制器类全名为
`app\controllers\admin\PostController`
控制器类全面能被 [自动加载](concept-autoloading.md),这点是非常重要的,
控制器类的实际命名空间对应这个属性,
控制器类全面能被 [自动加载](concept-autoloading.md),
这点是非常重要的,控制器类的实际命名空间对应这个属性,
否则,访问时你会收到"Page Not Found"[译:页面找不到]。
如果你想打破上述的规则,
@ -272,11 +272,11 @@ Yii遵循一个默认的 [规则](#controllerNamespace)指定控制器ID到任
该属性影响各种 [国际化](tutorial-i18n.md) ,
包括信息翻译、日期格式、数字格式等。
例如 [[yii\jui\DatePicker]] 小部件会
根据该属性展示对应语言的日历以及日期格式。
例如 [[yii\jui\DatePicker]] 小部件会根据该属性
展示对应语言的日历以及日期格式。
推荐遵循 [IETF language tag](http://en.wikipedia.org/wiki/IETF_language_tag) 来设置语言,
例如 `en` 代表英文, `en-US` 代表英文(美国)
例如 `en` 代表英文, `en-US` 代表英文(美国).
该属性的更多信息可参考 [国际化](tutorial-i18n.md) 一节.
@ -285,8 +285,8 @@ Yii遵循一个默认的 [规则](#controllerNamespace)指定控制器ID到任
该属性指定应用所包含的 [模块](structure-modules.md)。
该属性使用数组包含多个模块类 [配置](concept-configurations.md),
数组的键为模块ID,例:
该属性使用数组包含多个模块类 [配置](concept-configurations.md),数组的键为模块ID,
例:
```php
[
@ -346,8 +346,8 @@ $width = \Yii::$app->params['thumbnail.size'][0];
该属性指定应用代码的语言,默认为 `'en-US'` 标识英文(美国),
如果应用不是英文请修改该属性。
和 [语言](#language) 属性类似,
配置该属性需遵循 [IETF language tag](http://en.wikipedia.org/wiki/IETF_language_tag).
和 [语言](#language) 属性类似,配置该属性需遵循
[IETF language tag](http://en.wikipedia.org/wiki/IETF_language_tag).
例如 `en` 代表英文, `en-US` 代表英文(美国)。
该属性的更多信息可参考 [国际化](tutorial-i18n.md) 一节.
@ -404,7 +404,7 @@ $width = \Yii::$app->params['thumbnail.size'][0];
该属性用数组列表指定应用安装和使用的 [扩展](structure-extensions.md),
默认使用`@vendor/yiisoft/extensions.php`文件返回的数组。
当你使用 [Composer](http://getcomposer.org) 安装扩展,`extensions.php` 会被自动生成和维护更新。
当你使用 [Composer](https://getcomposer.org) 安装扩展,`extensions.php` 会被自动生成和维护更新。
所以大多数情况下,不需要配置该属性。
特殊情况下你想自己手动维护扩展,可以参照如下配置该属性:
@ -446,9 +446,9 @@ $width = \Yii::$app->params['thumbnail.size'][0];
#### [[yii\base\Application::layoutPath|layoutPath]] <span id="layoutPath"></span>
该属性指定查找布局文件的路径,
默认值为 [视图路径](#viewPath) 下的 `layouts` 子目录。
如果 [视图路径](#viewPath) 使用默认值,默认的布局路径别名为`@app/views/layouts`。
该属性指定查找布局文件的路径,默认值为 [视图路径](#viewPath) 下的 `layouts` 子目录。
如果 [视图路径](#viewPath) 使用默认值,
默认的布局路径别名为`@app/views/layouts`。
该属性需要配置成一个目录或 路径 [别名](concept-aliases.md)。
@ -473,12 +473,12 @@ $width = \Yii::$app->params['thumbnail.size'][0];
#### [[yii\base\Application::vendorPath|vendorPath]] <span id="vendorPath"></span>
该属性指定 [Composer](http://getcomposer.org) 管理的供应商路径,
该路径包含应用使用的包括 Yii 框架在内的所有第三方库。
该属性指定 [Composer](https://getcomposer.org) 管理的供应商路径,
该路径包含应用使用的包括Yii框架在内的所有第三方库。
默认值为带别名的 `@app/vendor`
可以配置它为一个目录或者路径 [别名](concept-aliases.md),当你修改时,
务必修改对应的 Composer 配置。
可以配置它为一个目录或者路径 [别名](concept-aliases.md),
当你修改时,务必修改对应的 Composer 配置。
为了简化访问该路径,Yii预定义别名 `@vendor` 代表该路径。
@ -491,8 +491,8 @@ $width = \Yii::$app->params['thumbnail.size'][0];
## 应用事件 <span id="application-events"></span>
应用在处理请求过程中会触发事件,
可以在配置文件配置事件处理代码,如下所示:
应用在处理请求过程中会触发事件,可以在配置文件配置事件处理代码,
如下所示:
```php
[
@ -581,10 +581,10 @@ $width = \Yii::$app->params['thumbnail.size'][0];
]
```
注意 [模块](structure-modules.md) 和 [控制器](structure-controllers.md)
都会触发 `afterAction` 事件。
这些对象的触发顺序和 `beforeAction` 相反,也就是说,控制器最先触发,
然后是模块(如果有模块),最后为应用主体。
注意 [模块](structure-modules.md) 和
[控制器](structure-controllers.md) 都会触发 `afterAction` 事件。
这些对象的触发顺序和 `beforeAction` 相反,也就是说,
控制器最先触发,然后是模块(如果有模块),最后为应用主体。
## 应用主体生命周期 <span id="application-lifecycle"></span>
@ -600,8 +600,8 @@ $width = \Yii::$app->params['thumbnail.size'][0];
比如[[yii\base\Application::basePath|basePath]]。
* 注册 [[yii\base\Application::errorHandler|error handler]] 错误处理方法.
* 配置应用主体属性.
* 调用 [[yii\base\Application::init()|init()]] 初始化,
该函数会调用 [[yii\base\Application::bootstrap()|bootstrap()]] 运行引导启动组件.
* 调用 [[yii\base\Application::init()|init()]] 初始化,该函数会调用 [[yii\base\Application::bootstrap()|bootstrap()]]
运行引导启动组件.
3. 入口脚本调用 [[yii\base\Application::run()]] 运行应用主体:
* 触发 [[yii\base\Application::EVENT_BEFORE_REQUEST|EVENT_BEFORE_REQUEST]] 事件。
* 处理请求:解析请求 [路由](runtime-routing.md) 和相关参数;

56
docs/guide-zh-CN/structure-assets.md

@ -4,9 +4,9 @@
Yii中的资源是和Web页面相关的文件,可为CSS文件,JavaScript文件,图片或视频等,
资源放在Web可访问的目录下,直接被Web服务器调用。
通过程序自动管理资源更好一点,例如,
当你在页面中使用 [[yii\jui\DatePicker]] 小部件时
它会自动包含需要的CSS和JavaScript文件,而不是要求你手工去找到这些文件并包含,
通过程序自动管理资源更好一点,例如,当你在页面中使用 [[yii\jui\DatePicker]] 小部件时,
它会自动包含需要的CSS和JavaScript文件
而不是要求你手工去找到这些文件并包含,
当你升级小部件时,它会自动使用新版本的资源文件,
在本教程中,我们会详述Yii提供的强大的资源管理功能。
@ -65,50 +65,50 @@ class AppAsset extends AssetBundle
如果你的资源文件在一个Web可访问目录下,应设置该属性,这样就不用再发布了。
[路径别名](concept-aliases.md) 可在此处使用。
* [[yii\web\AssetBundle::baseUrl|baseUrl]]: 指定对应到[[yii\web\AssetBundle::basePath|basePath]]目录的URL,
和 [[yii\web\AssetBundle::basePath|basePath]] 类似,如果你指定 [[yii\web\AssetBundle::sourcePath|sourcePath]] 属性,
[资源管理器](#asset-manager) 会发布这些资源并覆盖该属性,
[路径别名](concept-aliases.md) 可在此处使用。
和 [[yii\web\AssetBundle::basePath|basePath]] 类似,
如果你指定 [[yii\web\AssetBundle::sourcePath|sourcePath]] 属性,
[资源管理器](#asset-manager) 会发布这些资源并覆盖该属性,[路径别名](concept-aliases.md) 可在此处使用。
* [[yii\web\AssetBundle::js|js]]: 一个包含该资源包JavaScript文件的数组,
注意正斜杠"/"应作为目录分隔符,
每个JavaScript文件可指定为以下两种格式之一:
- 相对路径表示为本地JavaScript文件 (如 `js/main.js`),
文件实际的路径在该相对路径前加上
[[yii\web\AssetManager::basePath]],文件实际的URL在该路径前加上[[yii\web\AssetManager::baseUrl]]。
- 相对路径表示为本地JavaScript文件 (如 `js/main.js`),文件实际的路径在该相对路径前加上
[[yii\web\AssetManager::basePath]],文件实际的URL
在该路径前加上[[yii\web\AssetManager::baseUrl]]。
- 绝对URL地址表示为外部JavaScript文件,如
`http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js`
`//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js`.
* [[yii\web\AssetBundle::css|css]]: 一个包含该资源包CSS文件的数组,
该数组格式和 [[yii\web\AssetBundle::js|js]] 相同。
* [[yii\web\AssetBundle::depends|depends]]: 一个列出该资源包
依赖的其他资源包(后两节有详细介绍)。
* [[yii\web\AssetBundle::depends|depends]]: 一个列出该资源包依赖的
其他资源包(后两节有详细介绍)。
* [[yii\web\AssetBundle::jsOptions|jsOptions]]: 当调用[[yii\web\View::registerJsFile()]]注册该包 *每个* JavaScript文件时,
指定传递到该方法的选项。
* [[yii\web\AssetBundle::cssOptions|cssOptions]]: 当调用[[yii\web\View::registerCssFile()]]注册该包 *每个* css文件时,
指定传递到该方法的选项。
* [[yii\web\AssetBundle::publishOptions|publishOptions]]: 当调用[[yii\web\AssetManager::publish()]]发布该包资源文件到Web目录时
指定传递到该方法的选项,
仅在指定了[[yii\web\AssetBundle::sourcePath|sourcePath]]属性时使用。
指定传递到该方法的选项,仅在指定了
[[yii\web\AssetBundle::sourcePath|sourcePath]]属性时使用。
### 资源位置 <span id="asset-locations"></span>
资源根据它们的位置可以分为:
* 源资源: 资源文件和PHP源代码放在一起,不能被Web直接访问,
为了使用这些源资源,它们要拷贝到一个可Web访问的Web目录中
* 源资源: 资源文件和PHP源代码放在一起,不能被Web直接访问,为了使用这些源资源,
它们要拷贝到一个可Web访问的Web目录中
成为发布的资源,这个过程称为*发布资源*,随后会详细介绍。
* 发布资源: 资源文件放在可通过Web直接访问的Web目录中;
* 外部资源: 资源文件放在与你的Web应用不同
Web服务器上;
* 外部资源: 资源文件放在与你的Web应用不同
Web服务器上;
当定义资源包类时候,如果你指定了[[yii\web\AssetBundle::sourcePath|sourcePath]] 属性,
就表示任何使用相对路径的资源会被当作源资源;如果没有指定该属性,
就表示这些资源为发布资源(因此应指定[[yii\web\AssetBundle::basePath|basePath]] 和
就表示任何使用相对路径的资源会被当作源资源;
如果没有指定该属性,就表示这些资源为发布资源(因此应指定[[yii\web\AssetBundle::basePath|basePath]] 和
[[yii\web\AssetBundle::baseUrl|baseUrl]] 让Yii知道它们的位置)。
推荐将资源文件放到Web目录以避免不必要的发布资源过程,
这就是之前的例子:指定
[[yii\web\AssetBundle::basePath|basePath]] 而不是 [[yii\web\AssetBundle::sourcePath|sourcePath]].
推荐将资源文件放到Web目录以避免不必要的发布资源过程,这就是之前的例子:指定
[[yii\web\AssetBundle::basePath|basePath]]
而不是 [[yii\web\AssetBundle::sourcePath|sourcePath]].
对于 [扩展](structure-extensions.md)来说,
由于它们的资源和源代码都在不能Web访问的目录下,
@ -128,7 +128,7 @@ class AppAsset extends AssetBundle
我们称这种资源先后次序称为资源依赖。
资源依赖主要通过[[yii\web\AssetBundle::depends]] 属性来指定,
在`AppAsset` 示例中,资源包依赖其他两个资源包:
在`AppAsset` 示例中,资源包依赖其他两个资源包:
[[yii\web\YiiAsset]] 和 [[yii\bootstrap\BootstrapAsset]]
也就是该资源包的CSS和JavaScript文件要在这两个依赖包的文件包含 *之后* 才包含。
@ -166,8 +166,8 @@ public $cssOptions = ['condition' => 'lte IE9'];
public $cssOptions = ['noscript' => true];
```
为使JavaScript文件包含在页面head区域
(JavaScript文件默认包含在body的结束处)使用以下选项:
为使JavaScript文件包含在页面head区域(JavaScript文件默认包含在body的结束处)
使用以下选项:
```php
public $jsOptions = ['position' => \yii\web\View::POS_HEAD];
@ -205,9 +205,9 @@ the `only` publishing option, only the `fonts` and `css` subdirectories will be
### Bower 和 NPM 资源 <span id="bower-npm-assets"></span>
大多数 JavaScript/CSS 包通过[Bower](http://bower.io/) 和/或 [NPM](https://www.npmjs.org/)管理,
如果你的应用或扩展使用这些包
推荐你遵循以下步骤来管理库中的资源:
大多数 JavaScript/CSS 包通过[Bower](http://bower.io/) 和/或
[NPM](https://www.npmjs.org/)管理
如果你的应用或扩展使用这些包,推荐你遵循以下步骤来管理库中的资源:
1. 修改应用或扩展的 `composer.json` 文件将包列入`require` 中,
应使用`bower-asset/PackageName` (Bower包)

158
docs/guide-zh-CN/structure-controllers.md

@ -3,15 +3,15 @@
控制器是 [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),
最后生成输出响应信息。
具体来说,控制器从[应用主体](structure-applications.md)
接管控制后会分析请求数据并传送到[模型](structure-models.md),
传送模型结果到[视图](structure-views.md),最后生成输出响应信息。
## 动作 <span id="actions"></span>
控制器由 *作* 组成,它是执行终端用户请求的最基础的单元,
一个控制器可有一个或多个作。
控制器由 *作* 组成,它是执行终端用户请求的最基础的单元,
一个控制器可有一个或多个作。
如下示例显示包含两个动作`view` and `create` 的控制器`post`:
@ -52,13 +52,13 @@ class PostController extends Controller
}
```
`view` (定义为 `actionView()` 方法)中,
`view` (定义为 `actionView()` 方法)中,
代码首先根据请求模型ID加载 [模型](structure-models.md),
如果加载成功,会渲染名称为`view`的[视图](structure-views.md)并显示,否则会抛出一个异常。
`create` (定义为 `actionCreate()` 方法)中, 代码相似
`create` (定义为 `actionCreate()` 方法)中, 代码相似.
先将请求数据填入[模型](structure-models.md),
然后保存模型,如果两者都成功,会跳转到ID为新创建的模型的`view`作,
然后保存模型,如果两者都成功,会跳转到ID为新创建的模型的`view`作,
否则显示提供用户输入的`create`视图。
@ -66,10 +66,10 @@ class PostController extends Controller
终端用户通过所谓的*路由*寻找到动作,路由是包含以下部分的字符串:
* 模ID: 仅存在于控制器属于非应用的[模块](structure-modules.md);
* 模ID: 仅存在于控制器属于非应用的[模块](structure-modules.md);
* 控制器ID: 同应用(或同模块如果为模块下的控制器)
下唯一标识控制器的字符串;
* 作ID: 同控制器下唯一标识操作的字符串。
* 作ID: 同控制器下唯一标识操作的字符串。
路由使用如下格式:
@ -83,8 +83,8 @@ ControllerID/ActionID
ModuleID/ControllerID/ActionID
```
如果用户的请求地址为 `http://hostname/index.php?r=site/index`,
会执行`site` 控制器的`index` 作。
如果用户的请求地址为 `http://hostname/index.php?r=site/index`,
会执行`site` 控制器的`index` 作。
更多关于处理路由的详情请参阅 [路由](runtime-routing.md) 一节。
@ -112,13 +112,13 @@ class SiteController extends Controller
例如使用`article`作为处理文章的控制器ID。
控制器ID应仅包含英文小写字母、数字、下划线、中横杠和正斜杠,
例如 `article``post-comment` 是真实的控制器
ID,`article?`, `PostComment`, `admin\post`不是控制器ID。
例如 `article``post-comment` 是真是的控制器ID,
`article?`, `PostComment`, `admin\post`不是控制器ID。
控制器Id可包含子目录前缀,例如 `admin/article` 代表
[[yii\base\Application::controllerNamespace|controller namespace]]控制器命名空间下 `admin`子目录中 `article` 控制器。
子目录前缀可为英文大小写字母、数字、下划线、正斜杠,
其中正斜杠用来区分多级子目录(如 `panels/admin`)。
[[yii\base\Application::controllerNamespace|controller namespace]]
控制器命名空间下 `admin`子目录中 `article` 控制器。
子目录前缀可为英文大小写字母、数字、下划线、正斜杠,其中正斜杠用来区分多级子目录(如 `panels/admin`)。
### 控制器类命名 <span id="controller-class-naming"></span>
@ -176,10 +176,10 @@ ID,`article?`, `PostComment`, `admin\post`不是控制器ID。
### 默认控制器 <span id="default-controller"></span>
每个应用有一个由[[yii\base\Application::defaultRoute]]属性指定的默认控制器;当请求没有指定 [路由](#ids-routes),该属性值作为路由使用。
对于[[yii\web\Application|Web applications]]网页应用,它的值为 `'site'`
对于 [[yii\console\Application|console applications]]控制台应用,它的值为 `help`
所以URL为 `http://hostname/index.php` 表示由 `site` 控制器来处理。
每个应用有一个由[[yii\base\Application::defaultRoute]]属性指定的默认控制器;
当请求没有指定 [路由](#ids-routes),该属性值作为路由使用。
对于[[yii\web\Application|Web applications]]网页应用,它的值为 `'site'`,对于 [[yii\console\Application|console applications]]
控制台应用,它的值为 `help`所以URL为 `http://hostname/index.php` 表示由 `site` 控制器来处理。
可以在 [应用配置](structure-applications.md#application-configurations) 中修改默认控制器,如下所示:
@ -192,9 +192,9 @@ ID,`article?`, `PostComment`, `admin\post`不是控制器ID。
## 创建动作 <span id="creating-actions"></span>
创建作可简单地在控制器类中定义所谓的 *操作方法* 来完成,操作方法必须是以`action`开头的公有方法。
作方法的返回值会作为响应数据发送给终端用户,
如下代码定义了两个`index``hello-world`:
创建作可简单地在控制器类中定义所谓的 *操作方法* 来完成,操作方法必须是以`action`开头的公有方法。
作方法的返回值会作为响应数据发送给终端用户,
如下代码定义了两个`index``hello-world`:
```php
namespace app\controllers;
@ -218,17 +218,17 @@ class SiteController extends Controller
### 动作ID <span id="action-ids"></span>
作通常是用来执行资源的特定操作,因此,
作ID通常为动词,如`view`, `update`等。
作通常是用来执行资源的特定操作,因此,
作ID通常为动词,如`view`, `update`等。
作ID应仅包含英文小写字母、数字、下划线和中横杠,操作ID中的中横杠用来分隔单词。
例如`view`, `update2`, `comment-post`是真实的动作
ID,`view?`, `Update`不是动作ID.
作ID应仅包含英文小写字母、数字、下划线和中横杠,操作ID中的中横杠用来分隔单词。
例如`view`, `update2`, `comment-post`是真实的操作ID,
`view?`, `Update`不是操作ID.
可通过两种方式创建动作ID,内联动作和独立动作. An inline action is
内联动作在控制器类中定义为方法;独立动作是继承[[yii\base\Action]]或它的子类的类。
内联作容易创建,在无需重用的情况下优先使用;
独立作相反,主要用于多个控制器重用,
可通过两种方式创建操作ID,内联操作和独立操作. An inline action is
内联操作在控制器类中定义为方法;独立操作是继承[[yii\base\Action]]或它的子类的类。
内联作容易创建,在无需重用的情况下优先使用;
独立作相反,主要用于多个控制器重用,
或重构为[扩展](structure-extensions.md)。
@ -238,30 +238,30 @@ ID,`view?`, `Update`不是动作ID.
动作方法的名字是根据操作ID遵循如下规则衍生:
* 将每个单词的第一个字母转为大写;
* 去掉中横杠;
* 增加`action`前缀.
1. 将每个单词的第一个字母转为大写;
2. 去掉中横杠;
3. 增加`action`前缀.
例如`index` 转成 `actionIndex`, `hello-world` 转成 `actionHelloWorld`
> Note: 作方法的名字*大小写敏感*,如果方法名称为`ActionIndex`不会认为是操作方法,
所以请求`index`作会返回一个异常,
也要注意作方法必须是公有的,
私有或者受保护的方法不能定义成内联作。
> Note: 作方法的名字*大小写敏感*,如果方法名称为`ActionIndex`不会认为是操作方法,
所以请求`index`作会返回一个异常,
也要注意作方法必须是公有的,
私有或者受保护的方法不能定义成内联作。
因为容易创建,内联作是最常用的操作,
但是如果你计划在不同地方重用相同的作,
或者你想重新分配一个动作,需要考虑定义它为*独立动作*。
因为容易创建,内联作是最常用的操作,
但是如果你计划在不同地方重用相同的作,
或者你想重新分配一个操作,需要考虑定义它为*独立操作*。
### 独立动作 <span id="standalone-actions"></span>
独立作通过继承[[yii\base\Action]]或它的子类来定义。
例如Yii发布的[[yii\web\ViewAction]]和[[yii\web\ErrorAction]]
都是独立动作。
独立作通过继承[[yii\base\Action]]或它的子类来定义。
例如Yii发布的[[yii\web\ViewAction]]
和[[yii\web\ErrorAction]]都是独立操作。
要使用独立作,需要通过控制器中覆盖[[yii\base\Controller::actions()]]方法在*action map*中申明,
要使用独立作,需要通过控制器中覆盖[[yii\base\Controller::actions()]]方法在*action map*中申明,
如下例所示:
```php
@ -280,12 +280,12 @@ public function actions()
}
```
如上所示, `actions()` 方法返回键为动作ID、值为对应操作类名或数组[configurations](concept-configurations.md) 的数组。
和内联动作不同,独立动作ID可包含任意字符,
只要在`actions()` 方法中申明.
如上所示, `actions()` 方法返回键为操作ID、值为对应操作类名
或数组[configurations](concept-configurations.md) 的数组。
和内联操作不同,独立操作ID可包含任意字符,只要在`actions()` 方法中申明.
为创建一个独立作类,需要继承[[yii\base\Action]] 或它的子类,并实现公有的名称为`run()`的方法,
`run()` 方法的角色和作方法类似,例如:
为创建一个独立作类,需要继承[[yii\base\Action]] 或它的子类,并实现公有的名称为`run()`的方法,
`run()` 方法的角色和作方法类似,例如:
```php
<?php
@ -305,8 +305,8 @@ class HelloWorldAction extends Action
### 动作结果 <span id="action-results"></span>
作方法或独立操作的`run()`方法的返回值非常重要,
它表示对应作结果。
作方法或独立操作的`run()`方法的返回值非常重要,
它表示对应作结果。
返回值可为 [响应](runtime-responses.md) 对象,作为响应发送给终端用户。
@ -315,8 +315,8 @@ class HelloWorldAction extends Action
* 对于[[yii\console\Application|console applications]]控制台应用,返回值可为整数,
表示命令行下执行的 [[yii\console\Response::exitStatus|exit status]] 退出状态。
在上面的例子中,作结果都为字符串,作为响应数据发送给终端用户,
下例显示一个作通过
在上面的例子中,作结果都为字符串,作为响应数据发送给终端用户,
下例显示一个作通过
返回响应对象(因为[[yii\web\Controller::redirect()|redirect()]]方法返回一个响应对象)
可将用户浏览器跳转到新的URL。
@ -356,8 +356,8 @@ class PostController extends Controller
* `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&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]] 异常
@ -376,18 +376,18 @@ public function actionView(array $id, $version = null)
如果请求为 `http://hostname/index.php?r=post/view&id=123`
参数 `$id` 会获取相同数组值,因为无类型的`'123'`会自动转成数组。
上述例子主要描述网页应用的作参数,对于控制台应用,
上述例子主要描述网页应用的作参数,对于控制台应用,
更多详情请参阅[控制台命令](tutorial-console.md)。
### 默认动作 <span id="default-action"></span>
每个控制器都有一个由 [[yii\base\Controller::defaultAction]] 属性指定的默认作,
每个控制器都有一个由 [[yii\base\Controller::defaultAction]] 属性指定的默认作,
当[路由](#ids-routes) 只包含控制器ID,
会使用所请求的控制器的默认作。
会使用所请求的控制器的默认作。
默认动作默认为 `index`,如果想修改默认动作
只需简单地在控制器类中覆盖这个属性,如下所示:
默认操作默认为 `index`,如果想修改默认操作,只需简单地在控制器类中覆盖这个属性
如下所示:
```php
namespace app\controllers;
@ -408,33 +408,33 @@ class SiteController extends Controller
## 控制器生命周期 <span id="controller-lifecycle"></span>
处理一个请求时,
[应用主体](structure-applications.md) 会根据请求[路由](#routes)创建一个控制器,
处理一个请求时,[应用主体](structure-applications.md) 会根据请求
[路由](#routes)创建一个控制器,
控制器经过以下生命周期来完成请求:
1. 在控制器创建和配置后,[[yii\base\Controller::init()]] 方法会被调用。
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]]异常。
3. 控制器按顺序调用应用主体、模块(如果控制器属于模块)、
控制器的 `beforeAction()` 方法;
* 如果任意一个调用返回false,后面未调用的`beforeAction()`会跳过并且作执行会被取消;
* 如果任意一个调用返回false,后面未调用的`beforeAction()`会跳过并且作执行会被取消;
action execution will be cancelled.
* 默认情况下每个 `beforeAction()` 方法会触发一个 `beforeAction` 事件,在事件中你可以追加事件处理作;
4. 控制器执行作:
* 请求数据解析和填入到作参数;
5. 控制器按顺序调用控制器、模块(如果控制器属于模块)、
应用主体的 `afterAction()` 方法;
* 默认情况下每个 `afterAction()` 方法会触发一个 `afterAction` 事件,在事件中你可以追加事件处理动作;
6. 应用主体获取作结果并赋值给[响应](runtime-responses.md).
* 默认情况下每个 `beforeAction()` 方法会触发一个 `beforeAction` 事件,在事件中你可以追加事件处理作;
4. 控制器执行作:
* 请求数据解析和填入到作参数;
5. 控制器按顺序调用控制器、模块(如果控制器属于模块)、应用主体的 `afterAction()` 方法;
* 默认情况下每个 `afterAction()` 方法会触发一个 `afterAction` 事件,
在事件中你可以追加事件处理操作;
6. 应用主体获取作结果并赋值给[响应](runtime-responses.md).
## 最佳实践 <span id="best-practices"></span>
在设计良好的应用中,控制器很精练,包含的作代码简短;
在设计良好的应用中,控制器很精练,包含的作代码简短;
如果你的控制器很复杂,通常意味着需要重构,
转移一些代码到其他类中。

9
docs/guide-zh-CN/structure-entry-scripts.md

@ -63,6 +63,7 @@ $config = require(__DIR__ . '/../config/web.php');
*/
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
// 注册 Composer 自动加载器
require(__DIR__ . '/vendor/autoload.php');
@ -83,11 +84,11 @@ exit($exitCode);
入口脚本是定义全局常量的最好地方,Yii 支持以下三个常量:
* `YII_DEBUG`:标识应用是否运行在调试模式。当在调试模式下,
应用会保留更多日志信息,如果抛出异常,会显示详细的错误调用堆栈。
* `YII_DEBUG`:标识应用是否运行在调试模式。当在调试模式下,应用会保留更多日志信息,
如果抛出异常,会显示详细的错误调用堆栈。
因此,调试模式主要适合在开发阶段使用,`YII_DEBUG` 默认值为 false。
* `YII_ENV`:标识应用运行的环境,
详情请查阅[配置](concept-configurations.md#environment-constants)章节。
* `YII_ENV`:标识应用运行的环境,详情请查阅
[配置](concept-configurations.md#environment-constants)章节。
`YII_ENV` 默认值为 `'prod'`,表示应用运行在线上产品环境。
* `YII_ENABLE_ERROR_HANDLER`:标识是否启用 Yii 提供的错误处理,
默认为 true。

44
docs/guide-zh-CN/structure-filters.md

@ -11,9 +11,9 @@
## 使用过滤器 <span id="using-filters"></span>
过滤器本质上是一类特殊的 [行为](concept-behaviors.md),所以使用过滤器和 [使用 行为](concept-behaviors.md#attaching-behaviors)一样。
可以在控制器类中覆盖它的 [[yii\base\Controller::behaviors()|behaviors()]] 方法来申明过滤器,
如下所示:
过滤器本质上是一类特殊的 [行为](concept-behaviors.md),
所以使用过滤器和 [使用 行为](concept-behaviors.md#attaching-behaviors)一样。
可以在控制器类中覆盖它的 [[yii\base\Controller::behaviors()|behaviors()]] 方法来申明过滤器,如下所示:
```php
public function behaviors()
@ -33,9 +33,9 @@ public function behaviors()
控制器类的过滤器默认应用到该类的 *所有* 动作,
你可以配置[[yii\base\ActionFilter::only|only]]属性明确指定控制器应用到哪些动作。
在上述例子中,
`HttpCache` 过滤器只应用到`index`和`view`动作。
也可以配置[[yii\base\ActionFilter::except|except]]属性使一些动作不执行过滤器。
在上述例子中,`HttpCache` 过滤器只应用到`index`和`view`动作。
也可以配置[[yii\base\ActionFilter::except|except]]属性
使一些动作不执行过滤器。
除了控制器外,可在 [模块](structure-modules.md)或[应用主体](structure-applications.md) 中申明过滤器。
申明之后,过滤器会应用到所属该模块或应用主体的 *所有* 控制器动作,
@ -106,8 +106,8 @@ Yii提供了一组常用过滤器,在`yii\filters`命名空间下,
### [[yii\filters\AccessControl|AccessControl]] <span id="access-control"></span>
AccessControl提供基于[[yii\filters\AccessControl::rules|rules]]规则的访问控制。
特别是在动作执行之前,
访问控制会检测所有规则并找到第一个符合上下文的变量(比如用户IP地址、登录状态等等)的规则,
特别是在动作执行之前,访问控制会检测所有规则
并找到第一个符合上下文的变量(比如用户IP地址、登录状态等等)的规则,
来决定允许还是拒绝请求动作的执行,
如果没有规则符合,访问就会被拒绝。
@ -141,9 +141,9 @@ public function behaviors()
### 认证方法过滤器 <span id="auth-method-filters"></span>
认证方法过滤器通过[HTTP Basic Auth](http://en.wikipedia.org/wiki/Basic_access_authentication)或[OAuth 2](http://oauth.net/2/)
来认证一个用户,
认证方法过滤器类在 `yii\filters\auth` 命名空间下。
认证方法过滤器通过[HTTP Basic Auth](http://en.wikipedia.org/wiki/Basic_access_authentication)
或[OAuth 2](http://oauth.net/2/)
来认证一个用户,认证方法过滤器类在 `yii\filters\auth` 命名空间下。
如下示例表示可使用[[yii\filters\auth\HttpBasicAuth]]来认证一个用户,
它使用基于HTTP基础认证方法的令牌。
@ -172,8 +172,8 @@ public function behaviors()
ContentNegotiator支持响应内容格式处理和语言处理。
通过检查 `GET` 参数和 `Accept` HTTP头部来决定响应内容格式和语言。
如下示例,配置ContentNegotiator支持JSON和XML响应格式
和英语(美国)和德语。
如下示例,配置ContentNegotiator支持JSON和XML
响应格式和英语(美国)和德语。
```php
use yii\filters\ContentNegotiator;
@ -224,7 +224,7 @@ use yii\web\Response;
];
```
> 补充: 如果请求中没有检测到内容格式和语言,
> Info: 如果请求中没有检测到内容格式和语言,
使用[[formats]]和[[languages]]第一个配置项。
@ -290,8 +290,8 @@ public function behaviors()
### [[yii\filters\RateLimiter|RateLimiter]] <span id="rate-limiter"></span>
RateLimiter 根据 [漏桶算法](http://en.wikipedia.org/wiki/Leaky_bucket) 来实现速率限制。
主要用在实现RESTful APIs,
更多关于该过滤器详情请参阅 [Rate Limiting](rest-rate-limiting.md) 一节。
主要用在实现RESTful APIs,更多关于该过滤器详情请参阅
[Rate Limiting](rest-rate-limiting.md) 一节。
### [[yii\filters\VerbFilter|VerbFilter]] <span id="verb-filter"></span>
@ -322,7 +322,8 @@ public function behaviors()
### [[yii\filters\Cors|Cors]] <span id="cors"></span>
跨域资源共享 [CORS](https://developer.mozilla.org/fr/docs/HTTP/Access_control_CORS) 机制允许一个网页的许多资源(例如字体、JavaScript等)
跨域资源共享 [CORS](https://developer.mozilla.org/fr/docs/HTTP/Access_control_CORS)
机制允许一个网页的许多资源(例如字体、JavaScript等)
这些资源可以通过其他域名访问获取。
特别是JavaScript's AJAX 调用可使用 XMLHttpRequest 机制,
由于同源安全策略该跨域请求会被网页浏览器禁止.
@ -345,7 +346,10 @@ public function behaviors()
}
```
Cors 可转为使用 `cors` 属性。
Also check the section on [REST Controllers](rest-controllers.md#cors) if you want to add the CORS filter to an
[[yii\rest\ActiveController]] class in your API.
The Cors filtering could be tuned using the [[yii\filters\Cors::$cors|$cors]] property.
* `cors['Origin']`: 定义允许来源的数组,可为`['*']` (任何用户) 或 `['http://www.myserver.net', 'http://www.myotherserver.com']`. 默认为 `['*']`.
* `cors['Access-Control-Request-Method']`: 允许动作数组如 `['GET', 'OPTIONS', 'HEAD']`. 默认为 `['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']`.
@ -373,8 +377,8 @@ public function behaviors()
}
```
可以覆盖默认参数为每个动作调整CORS 头部。例如,
为`login`动作增加`Access-Control-Allow-Credentials`参数如下所示:
可以覆盖默认参数为每个动作调整CORS 头部。例如,为`login`动作
增加`Access-Control-Allow-Credentials`参数如下所示:
```php
use yii\filters\Cors;

81
docs/guide-zh-CN/structure-models.md

@ -36,8 +36,8 @@ $model->name = 'example';
echo $model->name;
```
也可像访问数组单元项一样访问属性,这要感谢 [[yii\base\Model]]
支持 [ArrayAccess 数组访问](http://php.net/manual/en/class.arrayaccess.php)
也可像访问数组单元项一样访问属性,这要感谢[[yii\base\Model]]支持
[ArrayAccess 数组访问](http://php.net/manual/en/class.arrayaccess.php)
和 [ArrayIterator 数组迭代器](http://php.net/manual/en/class.arrayiterator.php):
```php
@ -75,18 +75,18 @@ class ContactForm extends Model
```
另一种方式是可覆盖 [[yii\base\Model::attributes()]] 来定义属性,
该方法返回模型的属性名。
另一种方式是可覆盖 [[yii\base\Model::attributes()]]
来定义属性,该方法返回模型的属性名。
例如 [[yii\db\ActiveRecord]] 返回对应数据表列名作为它的属性名,
注意可能需要覆盖魔术方法如`__get()`,
注意可能需要覆盖魔术方法如`__get()`,
`__set()`使属性像普通对象属性被访问。
### 属性标签 <span id="attribute-labels"></span>
当属性显示或获取输入时,经常要显示属性相关标签,例如假定一个属性名为`firstName`,
在某些地方如表单输入或错误信息处
你可能想显示对终端用户来说更友好的 `First Name` 标签。
当属性显示或获取输入时,经常要显示属性相关标签,
例如假定一个属性名为`firstName`
在某些地方如表单输入或错误信息处,你可能想显示对终端用户来说更友好的 `First Name` 标签。
可以调用 [[yii\base\Model::getAttributeLabel()]] 获取属性的标签,例如:
@ -102,8 +102,8 @@ echo $model->getAttributeLabel('name');
例如 `username` 转换为 `Username`
`firstName` 转换为 `First Name`
如果你不想用自动生成的标签,
可以覆盖 [[yii\base\Model::attributeLabels()]] 方法明确指定属性标签,例如:
如果你不想用自动生成的标签,可以覆盖 [[yii\base\Model::attributeLabels()]] 方法明确指定属性标签,
例如:
```php
namespace app\models;
@ -147,8 +147,8 @@ public function attributeLabels()
甚至可以根据条件定义标签,例如通过使用模型的 [scenario场景](#scenarios),
可对相同的属性返回不同的标签。
> 注意:属性标签是 [视图](structure-views.md)一部分,但是在模型中申明标签通常非常方便
并可行程非常简洁可重用代码。
> Info: 属性标签是 [视图](structure-views.md)一部分,
但是在模型中申明标签通常非常方便,并可行程非常简洁可重用代码。
## 场景 <span id="scenarios"></span>
@ -234,9 +234,9 @@ class User extends ActiveRecord
## 验证规则 <span id="validation-rules"></span>
当模型接收到终端用户输入的数据,数据应当满足某种规则(称为 *验证规则*, 也称为 *业务规则*)。
例如假定`ContactForm`模型,
你可能想确保所有属性不为空且 `email` 属性包含一个有效的邮箱地址,
当模型接收到终端用户输入的数据,
数据应当满足某种规则(称为 *验证规则*, 也称为 *业务规则*)。
例如假定`ContactForm`模型,你可能想确保所有属性不为空且 `email` 属性包含一个有效的邮箱地址,
如果某个属性的值不满足对应的业务规则,
相应的错误信息应显示,以帮助用户修正错误。
@ -260,8 +260,8 @@ if ($model->validate()) {
```
通过覆盖 [[yii\base\Model::rules()]] 方法指定
模型属性应该满足的规则来申明模型相关验证规则。
通过覆盖 [[yii\base\Model::rules()]] 方法指定模型
属性应该满足的规则来申明模型相关验证规则。
下述例子显示`ContactForm`模型申明的验证规则:
```php
@ -278,11 +278,11 @@ public function rules()
```
一条规则可用来验证一个或多个属性,一个属性可对应一条或多条规则。
更多关于如何申明验证规则的详情请参考
[验证输入](input-validation.md) 一节
更多关于如何申明验证规则的详情请参考
[验证输入](input-validation.md) 一节.
有时你想一条规则只在某个 [场景](#scenarios) 下应用,
为此你可以指定规则的 `on` 属性,如下所示:
有时你想一条规则只在某个 [场景](#scenarios) 下应用,为此你可以指定规则的 `on` 属性,
如下所示:
```php
public function rules()
@ -350,12 +350,12 @@ public function scenarios()
例如,如果 `User` 模型有一个`permission`属性对应用户的权限,
你可能只想让这个属性在后台界面被管理员修改。
由于默认[[yii\base\Model::scenarios()]]的实现
会返回[[yii\base\Model::rules()]]所有属性和数据,
由于默认[[yii\base\Model::scenarios()]]的实现会返回
[[yii\base\Model::rules()]]所有属性和数据,
如果不覆盖这个方法,表示所有只要出现在活动验证规则中的属性都是安全的。
为此,提供一个特别的别名为 `safe` 的验证器来
申明哪些属性是安全的不需要被验证,
为此,提供一个特别的别名为 `safe` 的验证器来申明
哪些属性是安全的不需要被验证,
如下示例的规则申明 `title``description` 都为安全属性。
```php
@ -409,8 +409,11 @@ In this case attributes `username`, `password` and `secret` are required, but `s
## 数据导出 <span id="data-exporting"></span>
模型通常要导出成不同格式,例如,你可能想将模型的一个集合转成JSON或Excel格式,
导出过程可分解为两个步骤,
第一步,模型转换成数组;第二步,数组转换成所需要的格式。
导出过程可分解为两个步骤:
- 模型转换成数组;
- 数组转换成所需要的格式。
你只需要关注第一步,因为第二步可被通用的
数据转换器如[[yii\web\JsonResponseFormatter]]来完成。
@ -438,12 +441,12 @@ $array = $post->attributes;
生成的数组的单元名。
默认情况下,字段名对应属性名,但是你可以通过覆盖
[[yii\base\Model::fields()|fields()]] 和/或 [[yii\base\Model::extraFields()|extraFields()]] 方法来改变这种行为,
[[yii\base\Model::fields()|fields()]] 和/或
[[yii\base\Model::extraFields()|extraFields()]] 方法来改变这种行为,
两个方法都返回一个字段定义列表,`fields()` 方法定义的字段是默认字段,
表示`toArray()`方法默认会返回这些字段。
`extraFields()`方法定义额外可用字段,通过`toArray()`方法指定`$expand`参数来返回这些额外可用字段。
例如如下代码会返回`fields()`方法定义的所有字段
和`extraFields()`方法定义的`prettyName` and `fullAddress`字段。
表示`toArray()`方法默认会返回这些字段。 `extraFields()`方法定义额外可用字段,
通过`toArray()`方法指定`$expand`参数来返回这些额外可用字段。
例如如下代码会返回`fields()`方法定义的所有字段和`extraFields()`方法定义的`prettyName` and `fullAddress`字段。
```php
$array = $model->toArray([], ['prettyName', 'fullAddress']);
@ -474,8 +477,8 @@ public function fields()
];
}
// 过滤掉一些字段,特别用于你想
// 继承父类实现并不想用一些敏感字段
// 过滤掉一些字段,特别用于
// 你想继承父类实现并不想用一些敏感字段
public function fields()
{
$fields = parent::fields();
@ -496,8 +499,8 @@ public function fields()
## 最佳实践 <span id="best-practices"></span>
模型是代表业务数据、规则和逻辑的中心地方,通常在很多地方重用,
在一个设计良好的应用中,
模型通常比[控制器](structure-controllers.md)代码多。
在一个设计良好的应用中,模型通常比
[控制器](structure-controllers.md)代码多。
归纳起来,模型
@ -515,7 +518,7 @@ public function fields()
因为一个简单修改会影响好多地方,
为确保模型好维护,最好使用以下策略:
* 定义可被多个 [应用主体](structure-applications.md)
* 定义可被多个 [应用主体](structure-applications.md)
或 [模块](structure-modules.md) 共享的模型基类集合。
这些模型类应包含通用的最小规则集合和逻辑。
* 在每个使用模型的 [应用主体](structure-applications.md) 或 [模块](structure-modules.md)中,
@ -526,5 +529,5 @@ public function fields()
你可以定义一个模型基类`common\models\Post`,
然后在前台应用中,定义并使用一个继承`common\models\Post`的具体模型类`frontend\models\Post`,
在后台应用中可以类似地定义`backend\models\Post`。
通过这种策略,你清楚`frontend\models\Post`只对应前台应用,
如果你修改它,就无需担忧修改会影响后台应用。
通过这种策略,你清楚`frontend\models\Post`只对应前台应用,如果你修改它,
就无需担忧修改会影响后台应用。

45
docs/guide-zh-CN/structure-modules.md

@ -31,8 +31,8 @@ forum/
每个模块都有一个继承[[yii\base\Module]]的模块类,
该类文件直接放在模块的[[yii\base\Module::basePath|base path]]目录下,
并且能被 [自动加载](concept-autoloading.md)。
当一个模块被访问,和 [应用主体实例](structure-applications.md)
并且能被 [自动加载](concept-autoloading.md)。当一个模块被访问,
和 [应用主体实例](structure-applications.md)
类似会创建该模块类唯一实例,模块实例用来帮模块内代码共享数据和组件。
以下示例一个模块类大致定义:
@ -64,8 +64,8 @@ public function init()
}
```
`config.php`配置文件可能包含以下内容,
类似[应用主体配置](structure-applications.md#application-configurations).
`config.php`配置文件可能包含以下内容,类似
[应用主体配置](structure-applications.md#application-configurations).
```php
<?php
@ -122,10 +122,10 @@ class PostController extends Controller
您的模块也可以声明命令,这将通过 [控制台](tutorial-console.md) 模式可用。
当 Yii 在控制台模式下执行,并指向你的命令的命名空间,为了让命令行实用程序看到您的命令,您需要更改 [[yii\base\Module::controllerNamespace]]
属性。
In order for the command line utility to see your commands, you will need to change the [[yii\base\Module::controllerNamespace]]
property, when Yii is executed in the console mode, and point it to your commands namespace.
一种实现方法是在模块的 `init` 方法中测试Yii应用程序的实例类型:
一种实现方法是在模块的 `init()` 方法中测试Yii应用程序的实例类型
```php
public function init()
@ -137,7 +137,7 @@ public function init()
}
```
然后可以使用以下路由从命令行使用您的命令
然后您的命令将从命令行使用以下路由
```
yii <module_id>/<command>/<sub_command>
@ -169,11 +169,11 @@ yii <module_id>/<command>/<sub_command>
和访问应用的控制器类似,[路由](structure-controllers.md#routes)
也用在模块中控制器的寻址,
模块中控制器的路由必须以模块ID开始,接下来为控制器ID和作ID。
模块中控制器的路由必须以模块ID开始,接下来为控制器ID和作ID。
例如,假定应用使用一个名为 `forum` 模块,
路由`forum/post/index` 代表模块中 `post` 控制器的 `index` 作,
如果路由只包含模块ID,默认为 `default`
[[yii\base\Module::defaultRoute]] 属性来决定使用哪个控制器/作,
路由`forum/post/index` 代表模块中 `post` 控制器的 `index` 作,
如果路由只包含模块ID,默认为 `default`
[[yii\base\Module::defaultRoute]] 属性来决定使用哪个控制器/作,
也就是说路由 `forum` 可能代表 `forum` 模块的 `default` 控制器。
@ -191,7 +191,7 @@ $module = MyModuleClass::getInstance();
如果模块没有被请求,该方法会返回空,注意不需要手动创建一个模块类,
因为手动创建的和Yii处理请求时自动创建的不同。
> 补充: 当开发模块时,你不能假定模块使用固定的ID,
> Info: 当开发模块时,你不能假定模块使用固定的ID,
因为在应用或其他没模块中,模块可能会对应到任意的ID,
为了获取模块ID,应使用上述代码获取模块实例,
然后通过`$module->id`获取模块ID。
@ -238,9 +238,9 @@ $maxPostCount = $module->params['maxPostCount'];
## 模块嵌套 <span id="nested-modules"></span>
模块可无限级嵌套,也就是说,模块可以包含另一个包含模块的模块,
我们称前者为*父模块*,后者为*子模块*
子模块必须在父模块的[[yii\base\Module::modules|modules]]属性中申明,例如:
模块可无限级嵌套,也就是说,模块可以包含另一个包含模块的模块,我们称前者为*父模块*,后者为*子模块*,
子模块必须在父模块的[[yii\base\Module::modules|modules]]属性中申明
例如:
```php
namespace app\modules\forum;
@ -263,11 +263,11 @@ class Module extends \yii\base\Module
在嵌套模块中的控制器,它的路由应包含它所有祖先模块的ID,
例如`forum/admin/dashboard/index` 代表
在模块`forum`中子模块`admin`中`dashboard`控制器的`index`作。
在模块`forum`中子模块`admin`中`dashboard`控制器的`index`作。
> 注意:[[yii\base\Module::getModule()|getModule()]] 方法只返回属直接归属于其父级的子模块。
[[yii\base\Application::loadedModules]] 属性保存加载模块的列表,
通过它们的类名索引,包含直接的子节点和嵌套节点。
> Info: The [[yii\base\Module::getModule()|getModule()]] method only returns the child module directly belonging
to its parent. The [[yii\base\Application::loadedModules]] property keeps a list of loaded modules, including both
direct children and nested ones, indexed by their class names.
## 最佳实践 <span id="best-practices"></span>
@ -276,6 +276,7 @@ class Module extends \yii\base\Module
每个组包含一些强相关的特性,
每个特性组可以做成一个模块由特定的开发人员和开发组来开发和维护。
在特性组上,使用模块也是重用代码的好方式,一些常用特性,
如用户管理,评论管理,可以开发成模块,
在特性组上,使用模块也是重用代码的好方式,
一些常用特性,如用户管理,评论管理,可以开发成模块,
这样在相关项目中非常容易被重用。

84
docs/guide-zh-CN/structure-views.md

@ -5,8 +5,8 @@
它是展示数据到终端用户的代码,在网页应用中,
根据*视图模板*来创建视图,视图模板为PHP脚本文件,
主要包含HTML代码和展示类PHP代码,通过[[yii\web\View|view]]应用组件来管理,
该组件主要提供通用方法帮助视图构造和渲染,简单起见,
我们称视图模板或视图模板文件为视图。
该组件主要提供通用方法帮助视图构造和渲染,
简单起见,我们称视图模板或视图模板文件为视图。
## 创建视图 <span id="creating-views"></span>
@ -41,18 +41,18 @@ $this->title = 'Login';
来管理和渲染这个视图文件。
除了 `$this`之外,上述示例中的视图有其他预定义变量如 `$model`
这些变量代表从[控制器](structure-controllers.md)
其他触发[视图渲染](#rendering-views)的对象 *传入* 到视图的数据。
这些变量代表从[控制器](structure-controllers.md)
其他触发[视图渲染](#rendering-views)的对象 *传入* 到视图的数据。
> 技巧: 将预定义变量列到视图文件头部注释处,这样可被IDE编辑器识别
也是生成视图文档的好方法。
> Tip: 将预定义变量列到视图文件头部注释处,
这样可被IDE编辑器识别,也是生成视图文档的好方法。
### 安全 <span id="security"></span>
当创建生成HTML页面的视图时,
在显示之前将用户输入数据进行转码和过滤非常重要,
否则,你的应用可能会被[跨站脚本](http://en.wikipedia.org/wiki/Cross-site_scripting) 攻击。
当创建生成HTML页面的视图时,在显示之前将用户输入数据进行转码和过滤非常重要,
否则,你的应用可能会被
[跨站脚本](http://en.wikipedia.org/wiki/Cross-site_scripting) 攻击。
要显示纯文本,先调用 [[yii\helpers\Html::encode()]] 进行转码,
例如如下代码将用户名在显示前先转码:
@ -230,9 +230,9 @@ echo \Yii::$app->view->renderFile('@app/views/site/license.php');
* 视图名以双斜杠 `//` 开头,对应的视图文件路径为 `@app/views/ViewName`
也就是说视图文件在 [[yii\base\Application::viewPath|application's view path]] 路径下找,
例如 `//site/about` 对应到 `@app/views/site/about.php`
* 视图名以单斜杠`/`开始,视图文件路径以当前使用[模块](structure-modules.md) 的[[yii\base\Module::viewPath|view path]]开始,
如果不存在模块,使用`@app/views/ViewName`开始,
例如,如果当前模块为`user`, `/user/create` 对应成
* 视图名以单斜杠`/`开始,视图文件路径以当前使用[模块](structure-modules.md)
的[[yii\base\Module::viewPath|view path]]开始,
如果不存在模块,使用`@app/views/ViewName`开始,例如,如果当前模块为`user`, `/user/create` 对应成
`@app/modules/user/views/user/create.php`,
如果不在模块中,`/user/create`对应`@app/views/user/create.php`。
* 如果 [[yii\base\View::context|context]] 渲染视图 并且上下文实现了 [[yii\base\ViewContextInterface]],
@ -240,8 +240,8 @@ echo \Yii::$app->view->renderFile('@app/views/site/license.php');
这种主要用在控制器和小部件中渲染视图,例如
如果上下文为控制器`SiteController`,`site/about` 对应到 `@app/views/site/about.php`
* 如果视图渲染另一个视图,包含另一个视图文件的目录以当前视图的文件路径开始,
例如被视图`@app/views/post/index.php`
渲染的 `item` 对应到 `@app/views/post/item`
例如被视图`@app/views/post/index.php` 渲染的
`item` 对应到 `@app/views/post/item`
根据以上规则,在控制器中 `app\controllers\PostController` 调用 `$this->render('view')`
实际上渲染 `@app/views/post/view.php` 视图文件,当在该视图文件中调用 `$this->render('_overview')`
@ -255,7 +255,7 @@ echo \Yii::$app->view->renderFile('@app/views/site/license.php');
推送方式是通过视图渲染方法的第二个参数传递数据,
数据格式应为名称-值的数组,
视图渲染时,调用PHP `extract()` 方法将该数组转换为视图可访问的变量。
例如,如下控制器的渲染视图代码推送2个变量到
例如,如下控制器的渲染视图代码推送2个变量到
`report` 视图:`$foo = 1` 和 `$bar = 2`
```php
@ -281,11 +281,11 @@ The controller ID is: <?= $this->context->id ?>
### 视图间共享数据 <span id="sharing-data-among-views"></span>
[[yii\base\View|view component]]视图组件提供[[yii\base\View::params|params]]参数
属性来让不同视图共享数据。
[[yii\base\View|view component]]视图组件提供[[yii\base\View::params|params]]
参数属性来让不同视图共享数据。
例如在`about`视图中,可使用如下代码指定当前
breadcrumbs的当前部分。
例如在`about`视图中,
可使用如下代码指定当前breadcrumbs的当前部分。
```php
$this->params['breadcrumbs'][] = 'About Us';
@ -314,8 +314,8 @@ $this->params['breadcrumbs'][] = 'About Us';
由于布局也是视图,它可像普通视图一样创建,布局默认存储在`@app/views/layouts`路径下,
[模块](structure-modules.md)中使用的布局应存储在
[[yii\base\Module::basePath|module directory]]模块目录
下的`views/layouts`路径下,可配置[[yii\base\Module::layoutPath]]
来自定义应用或模块的布局默认路径。
下的`views/layouts`路径下,
可配置[[yii\base\Module::layoutPath]]来自定义应用或模块的布局默认路径。
如下示例为一个布局大致内容,注意作为示例,简化了很多代码,
在实际中,你可能想添加更多内容,如头部标签,主菜单等。
@ -383,9 +383,9 @@ use yii\helpers\Html;
### 使用布局 <span id="using-layouts"></span>
如[控制器中渲染](#rendering-in-controllers)一节描述,当控制器调用[[yii\base\Controller::render()|render()]]
方法渲染视图时,会同时使用布局到渲染结果中,
默认会使用`@app/views/layouts/main.php`布局文件。
如[控制器中渲染](#rendering-in-controllers)一节描述,
当控制器调用[[yii\base\Controller::render()|render()]]
方法渲染视图时,会同时使用布局到渲染结果中,默认会使用`@app/views/layouts/main.php`布局文件。
可配置[[yii\base\Application::layout]] 或 [[yii\base\Controller::layout]] 使用其他布局文件,
前者管理所有控制器的布局,后者覆盖前者来控制单个控制器布局。
@ -425,12 +425,12 @@ class PostController extends Controller
布局的值可为:
- 路径别名 (如 `@app/views/layouts/main`).
- 绝对路径 (如 `/main`): 布局的值以斜杠开始,在应用的[[yii\base\Application::layoutPath|layout path] 布局路径
中查找实际的布局文件,
布局路径默认为 `@app/views/layouts`
- 相对路径 (如 `main`): 在上下文模块的[[yii\base\Module::layoutPath|layout path]]
布局路径中查找实际的布局文件,
布局路径默认为[[yii\base\Module::basePath|module directory]]模块目录下的`views/layouts` 目录。
- 绝对路径 (如 `/main`): 布局的值以斜杠开始,
在应用的[[yii\base\Application::layoutPath|layout path]] 布局路径
中查找实际的布局文件,布局路径默认为 `@app/views/layouts`
- 相对路径 (如 `main`): 在上下文模块的[[yii\base\Module::layoutPath|layout path]]布局路径中查找实际的布局文件,
布局路径默认为[[yii\base\Module::basePath|module directory]]
模块目录下的`views/layouts` 目录。
- 布尔值 `false`: 不使用布局。
布局的值没有包含文件扩展名,默认使用 `.php`作为扩展名。
@ -522,9 +522,9 @@ class PostController extends Controller
## 使用视图组件 <span id="using-view-components"></span>
[[yii\base\View|View components]]视图组件提供许多视图相关特性,
可创建[[yii\base\View]]或它的子类实例来获取视图组件,
大多数情况下主要使用 `view` 应用组件,
可在[应用配置](structure-applications.md#application-configurations)中配置该组件,如下所示:
可创建[[yii\base\View]]或它的子类实例来获取视图组件,大多数情况下主要使用 `view` 应用组件,
可在[应用配置](structure-applications.md#application-configurations)中配置该组件,
如下所示:
```php
[
@ -573,8 +573,8 @@ $this->title = 'My page title';
### 注册Meta元标签 <span id="registering-meta-tags"></span>
Web页面通常需要生成各种元标签提供给不同的浏览器,如`<head>`中的页面标题,
元标签通常在布局中生成。
Web页面通常需要生成各种元标签提供给不同的浏览器,
如`<head>`中的页面标题,元标签通常在布局中生成。
如果想在内容视图中生成元标签,可在内容视图中调用[[yii\web\View::registerMetaTag()]]方法,
如下所示:
@ -607,9 +607,9 @@ $this->registerMetaTag(['name' => 'description', 'content' => 'This website is a
### 注册链接标签 <span id="registering-link-tags"></span>
和 [Meta标签](#adding-meta-tags) 类似,链接标签有时很实用,
如自定义网站图标,指定Rss订阅,或授权OpenID到其他服务器。
可以和元标签相似的方式调用[[yii\web\View::registerLinkTag()]],例如,在内容视图中注册链接标签如下所示:
和 [Meta标签](#adding-meta-tags) 类似,链接标签有时很实用,如自定义网站图标,指定Rss订阅,或授权OpenID到其他服务器。
可以和元标签相似的方式调用[[yii\web\View::registerLinkTag()]],
例如,在内容视图中注册链接标签如下所示:
```php
$this->registerLinkTag([
@ -656,8 +656,8 @@ $this->registerLinkTag([
## 渲染静态页面 <span id="rendering-static-pages"></span>
静态页面指的是大部分内容为静态的
不需要控制器传递动态数据的Web页面。
静态页面指的是大部分内容为静态的不需要控制器传递
动态数据的Web页面。
可将HTML代码放置在视图中,在控制器中使用以下代码输出静态页面:
@ -716,8 +716,8 @@ http://localhost/index.php?r=site/page&view=about
可遵循以下方法达到这个目标:
* 使用 [布局](#layouts) 来展示公共代码(如,页面头部、尾部);
* 将复杂的视图分成几个小视图,
可使用上面描述的渲染方法将这些小视图渲染并组装成大视图;
* 将复杂的视图分成几个小视图,可使用上面描述的渲染方法将这些
小视图渲染并组装成大视图;
* 创建并使用 [小部件](structure-widgets.md) 作为视图的数据块;
* 创建并使用助手类在视图中转换和格式化数据。

50
docs/guide-zh-CN/structure-widgets.md

@ -13,15 +13,16 @@ use yii\jui\DatePicker;
<?= DatePicker::widget(['name' => 'date']) ?>
```
Yii提供许多优秀的小部件,比如[[yii\widgets\ActiveForm|active form]], [yii\widgets\Menu|menu]],
[jQuery UI widgets](widget-jui.md), [Twitter Bootstrap widgets](widget-bootstrap.md)。
接下来介绍小部件的基本知识,
如果你想了解某个小部件请参考对应的类API文档。
Yii提供许多优秀的小部件,比如[[yii\widgets\ActiveForm|active form]], [[yii\widgets\Menu|menu]],
[jQuery UI widgets](widget-jui.md),
[Twitter Bootstrap widgets](widget-bootstrap.md)。
接下来介绍小部件的基本知识,如果你想了解某个小部件请参考对应的类API文档。
## 使用小部件 <span id="using-widgets"></span>
小部件基本上在[views](structure-views.md)中使用,在视图中可调用 [[yii\base\Widget::widget()]] 方法使用小部件。
小部件基本上在[views](structure-views.md)中使用,
在视图中可调用 [[yii\base\Widget::widget()]] 方法使用小部件。
该方法使用 [配置](concept-configurations.md) 数组初始化小部件并返回小部件渲染后的结果。
例如如下代码插入一个日期选择器小部件,它配置为使用俄罗斯语,
输入框内容为`$model`的`from_date`属性值。
@ -34,14 +35,12 @@ use yii\jui\DatePicker;
'model' => $model,
'attribute' => 'from_date',
'language' => 'ru',
'clientOptions' => [
'dateFormat' => 'yy-mm-dd',
],
'dateFormat' => 'php:Y-m-d',
]) ?>
```
一些小部件可在[[yii\base\Widget::begin()]]
[[yii\base\Widget::end()]] 调用中使用数据内容。
一些小部件可在[[yii\base\Widget::begin()]]
[[yii\base\Widget::end()]] 调用中使用数据内容。
例如如下代码使用[[yii\widgets\ActiveForm]]小部件生成一个登录表单,
小部件会在`begin()` 和0 `end()`执行处分别生成`<form>`的开始标签和结束标签,
中间的任何代码也会被渲染。
@ -68,6 +67,23 @@ use yii\helpers\Html;
注意和调用 [[yii\base\Widget::widget()]] 返回渲染结果不同,
调用 [[yii\base\Widget::begin()]] 方法返回一个可组建小部件内容的小部件实例。
> Note: Some widgets will use [output buffering](http://php.net/manual/en/book.outcontrol.php) to adjust the enclosed
> content when [[yii\base\Widget::end()]] is called. For this reason calling [[yii\base\Widget::begin()]] and
> [[yii\base\Widget::end()]] is expected to happen in the same view file.
> Not following this rule may result in unexpected output.
### Configuring global defaults
Global defaults for a widget type could be configured via DI container:
```php
\Yii::$container->set('yii\widgets\LinkPager', ['maxButtonCount' => 5]);
```
See ["Practical Usage" section in Dependency Injection Container guide](concept-di-container.md#practical-usage) for
details.
### Configuring global defaults
@ -150,11 +166,11 @@ class HelloWidget extends Widget
}
```
如上所示,PHP输出缓冲在`init()`启动,所有在`init()` `run()`方法之间的输出内容都会被获取,
并在`run()`处理和返回。
如上所示,PHP输出缓冲在`init()`启动,所有在`init()`
`run()`方法之间的输出内容都会被获取,并在`run()`处理和返回。
> 注意: 当你调用 [[yii\base\Widget::begin()]] 时会创建一个
新的小部件实例并在构造结束时调用`init()`方法,
> Info: 当你调用 [[yii\base\Widget::begin()]] 时会创建一个新的小部件
实例并在构造结束时调用`init()`方法,
在`end()`时会调用`run()`方法并输出返回结果。
如下代码显示如何使用这种 `HelloWidget`:
@ -170,9 +186,9 @@ use app\components\HelloWidget;
<?php HelloWidget::end(); ?>
```
有时小部件需要渲染很多内容,一种更好的办法
是将内容放入一个[视图](structure-views.md)文件,
然后调用[[yii\base\Widget::render()]]方法渲染该视图文件,例如:
有时小部件需要渲染很多内容,一种更好的办法是将内容放入一个[视图](structure-views.md)文件,
然后调用[[yii\base\Widget::render()]]方法渲染该视图文件,
例如:
```php
public function run()

103
docs/guide-zh-CN/tutorial-core-validators.md

@ -54,8 +54,8 @@ public function rules()
使用,以确保某一输入与 [[yii\captcha\Captcha|CAPTCHA]] 小部件所显示的验证代码(verification code)相同。
- `caseSensitive`:对验证代码的比对是否要求大小写敏感。默认为 false。
- `captchaAction`:指向用于渲染 CAPTCHA 图片的 [[yii\captcha\CaptchaAction|CAPTCHA action]] 的 [路由](structure-controllers.md#routes)。
默认为 `'site/captcha'`
- `captchaAction`:指向用于渲染 CAPTCHA 图片的 [[yii\captcha\CaptchaAction|CAPTCHA action]]
的 [路由](structure-controllers.md#routes)。默认为 `'site/captcha'`
- `skipOnEmpty`:当输入为空时,是否跳过验证。
默认为 false,也就是输入值为必需项。
@ -67,20 +67,23 @@ public function rules()
// 检查 "password" 特性的值是否与 "password_repeat" 的值相同
['password', 'compare'],
// same as above but with explicitly specifying the attribute to compare with
['password', 'compare', 'compareAttribute' => 'password_repeat'],
// 检查年龄是否大于等于 30
['age', 'compare', 'compareValue' => 30, 'operator' => '>='],
]
```
该验证器比较两个特定输入值之间的关系是否与 `operator`
属性所指定的相同。
该验证器比较两个特定输入值之间的关系
是否与 `operator` 属性所指定的相同。
- `compareAttribute`:用于与原特性相比较的特性名称。
当该验证器被用于验证某目标特性时,
该属性会默认为目标属性加后缀 `_repeat`
举例来说,若目标特性为 `password`,则该属性默认为 `password_repeat`
- `compareValue`:用于与输入值相比较的常量值。当该属性与 `compareAttribute` 属性同时被指定时,
该属性优先被使用。
- `compareValue`:用于与输入值相比较的常量值。
当该属性与 `compareAttribute` 属性同时被指定时,该属性优先被使用。
- `operator`:比较操作符。默认为 `==`,意味着检查输入值是否与 `compareAttribute``compareValue` 的值相等。
该属性支持如下操作符:
* `==`:检查两值是否相等。比对为非严格模式。
@ -91,18 +94,48 @@ public function rules()
* `>=`:检查待测目标值是否大于等于给定被测值。
* `<`:检查待测目标值是否小于给定被测值。
* `<=`:检查待测目标值是否小于等于给定被测值。
- `type`: The default comparison type is '[[yii\validators\CompareValidator::TYPE_STRING|string]]', which means the values are
compared byte by byte. When comparing numbers, make sure to set the [[yii\validators\CompareValidator::$type|$type]]
to '[[yii\validators\CompareValidator::TYPE_NUMBER|number]]' to enable numeric comparison.
### Comparing date values
The compare validator can only be used to compare strings and numbers. If you need to compare values
like dates you have two options. For comparing a date against a fixed value, you can simply use the
[[yii\validators\DateValidator|date]] validator and specify its
[[yii\validators\DateValidator::$min|$min]] or [[yii\validators\DateValidator::$max|$max]] property.
If you need to compare two dates entered in the form, e.g. a `fromDate` and a `toDate` field,
you can use a combination of compare and date validator like the following:
```php
['fromDate', 'date', 'timestampAttribute' => 'fromDate'],
['toDate', 'date', 'timestampAttribute' => 'toDate'],
['fromDate', 'compare', 'compareAttribute' => 'toDate', 'operator' => '<', 'enableClientValidation' => false],
```
As validators are executed in the order they are specified this will first validate that the values entered in
`fromDate` and `toDate` are valid date values and if so, they will be converted into a machine readable format.
Afterwards these two values are compared with the compare validator.
Client validation is not enabled as this will only work on the server-side because the date validator currently does not
provide client validation, so [[yii\validators\CompareValidator::$enableClientValidation|$enableClientValidation]]
is set to `false` on the compare validator too.
## [[yii\validators\DateValidator|date(日期)]] <span id="date"></span>
The [[yii\validators\DateValidator|date]] validator comes with three different
shortcuts:
```php
[
[['from', 'to'], 'date'],
[['from_date', 'to_date'], 'date'],
[['from_datetime', 'to_datetime'], 'datetime'],
[['some_time'], 'time'],
]
```
该验证器检查输入值是否为适当格式的 date,time,或者 datetime。另外,
它还可以帮你把输入值转换为一个 UNIX 时间戳并保存到
该验证器检查输入值是否为适当格式的 date,time,或者 datetime。
另外,它还可以帮你把输入值转换为一个 UNIX 时间戳并保存到
[[yii\validators\DateValidator::timestampAttribute|timestampAttribute]] 属性所指定的特性里。
- `format`: the date/time format that the value being validated should be in.
@ -120,12 +153,15 @@ public function rules()
Since version 2.0.4, a format and timezone can be specified for this attribute using
[[yii\validators\DateValidator::$timestampAttributeFormat|$timestampAttributeFormat]] and
[[yii\validators\DateValidator::$timestampAttributeTimeZone|$timestampAttributeTimeZone]].
Note, that when using `timestampAttribute`, the input value will be converted to a unix timestamp, which by definition is in UTC, so
a conversion from the [[yii\validators\DateValidator::timeZone|input time zone]] to UTC will be performed.
- Since version 2.0.4 it is also possible to specify a [[yii\validators\DateValidator::$min|minimum]] or
[[yii\validators\DateValidator::$max|maximum]] timestamp.
In case the input is optional you may also want to add a [default value filter](#default) in addition to the date validator
to ensure empty input is stored as `NULL`. Other wise you may end up with dates like `0000-00-00` in your database
to ensure empty input is stored as `null`. Otherwise you may end up with dates like `0000-00-00` in your database
or `1970-01-01` in the input field of a date picker.
```php
@ -152,8 +188,8 @@ or `1970-01-01` in the input field of a date picker.
]
```
该验证器并不进行数据验证。而是,
给为空的待测特性分配默认值。
该验证器并不进行数据验证。
而是,给为空的待测特性分配默认值。
- `value`:默认值,或一个返回默认值的 PHP Callable 对象(即回调函数)。
它们会分配给检测为空的待测特性。PHP 回调方法的样式如下:
@ -165,7 +201,8 @@ function foo($model, $attribute) {
}
```
> 补充:如何判断待测值是否为空,被写在另外一个话题的
> Info: 如何判断待测值是否为空,
被写在另外一个话题的
[处理空输入](input-validation.md#handling-empty-inputs)章节。
@ -201,13 +238,13 @@ and each array element will be validated by the `integer` validation rule.
- `rule`: an array specifying a validation rule. The first element in the array specifies the class name or
the alias of the validator. The rest of the name-value pairs in the array are used to configure the validator object.
- `allowMessageFromRule`: whether to use the error message returned by the embedded validation rule. Defaults to true.
If false, it will use `message` as the error message.
- `allowMessageFromRule`: whether to use the error message returned by the embedded validation rule. Defaults to `true`.
If `false`, it will use `message` as the error message.
> Note: If the attribute value is not an array, it is considered validation fails and the `message` will be returned
as the error message.
## [[yii\validators\EmailValidator|email(电子邮件)]] <span id="email"></span>
```php
@ -220,11 +257,11 @@ and each array element will be validated by the `integer` validation rule.
该验证器检查输入值是否为有效的邮箱地址。
- `allowName`:检查是否允许带名称的电子邮件地址 (e.g. `张三 <John.san@example.com>`)。 默认为 false。
- `checkDNS`:检查邮箱域名是否存在,且有没有对应的 A 或 MX 记录。不过要知道,
有的时候该项检查可能会因为临时性 DNS 故障而失败,哪怕它其实是有效的。
默认为 false。
- `enableIDN`:验证过程是否应该考虑 IDN(internationalized domain names,国际化域名,
也称多语种域名,比如中文域名)。默认为 false。要注意但是为使用 IDN 验证功能,
- `checkDNS`:检查邮箱域名是否存在,且有没有对应的 A 或 MX 记录。
不过要知道,有的时候该项检查可能会因为临时性 DNS 故障而失败,
哪怕它其实是有效的。默认为 false。
- `enableIDN`:验证过程是否应该考虑 IDN(internationalized domain names,国际化域名,也称多语种域名,比如中文域名)。
默认为 false。要注意但是为使用 IDN 验证功能,
请先确保安装并开启 `intl` PHP 扩展,不然会导致抛出异常。
@ -252,28 +289,28 @@ and each array element will be validated by the `integer` validation rule.
]
```
This validator checks if the input value can be found in a table column represented by
an [Active Record](db-active-record.md) attribute. You can use `targetAttribute` to specify the
[Active Record](db-active-record.md) attribute and `targetClass` the corresponding [Active Record](db-active-record.md)
class. If you do not specify them, they will take the values of the attribute and the model class being validated.
该验证器检查输入值是否在某表字段中存在。
它只对[活动记录](db-active-record.md)
类型的模型类特性起作用,
能支持对一个或多过字段的验证。
You can use this validator to validate against a single column or multiple columns (i.e., the combination of
multiple attribute values should exist).
- `targetClass`:用于查找输入值的目标 [AR](db-active-record.md) 类。若不设置,
则会使用正在进行验证的当前模型类。
- `targetClass`:用于查找输入值的目标 [AR](db-active-record.md) 类。
若不设置,则会使用正在进行验证的当前模型类。
- `targetAttribute`:用于检查输入值存在性的 `targetClass` 的模型特性。
若不设置,它会直接使用待测特性名(整个参数数组的首元素)。
除了指定为字符串以外,你也可以用数组的形式,同时指定多个用于验证的表字段,数组的键和值都是代表字段的特性名,
值表示 `targetClass` 的待测数据源字段,而键表示当前模型的待测特性名。
除了指定为字符串以外,你也可以用数组的形式,同时指定多个用于验证的表字段,
数组的键和值都是代表字段的特性名,值表示 `targetClass` 的待测数据源字段,而键表示当前模型的待测特性名。
若键和值相同,你可以只指定值。(如:`['a2']` 就代表 `['a2'=>'a2']`
- `filter`:用于检查输入值存在性必然会进行数据库查询,而该属性为用于进一步筛选该查询的过滤条件。
可以为代表额外查询条件的字符串或数组(关于查询条件的格式,请参考 [[yii\db\Query::where()]]);
或者样式为 `function ($query)` 的匿名函数,
`$query` 参数为你希望在该函数内进行修改的 [[yii\db\Query|Query]] 对象。
- `allowArray`:是否允许输入值为数组。默认为 false。若该属性为 true 且输入值为数组,则数组的每个元素都必须在目标字段中存在。
值得注意的是,若用吧 `targetAttribute` 设为多元素数组来验证被测值在多字段中的存在性时,
该属性不能设置为 true。
- `allowArray`:是否允许输入值为数组。默认为 false。
若该属性为 true 且输入值为数组,则数组的每个元素都必须在目标字段中存在。
值得注意的是,若用吧 `targetAttribute` 设为多元素数组来验证被测值在多字段中的存在性时,该属性不能设置为 true。
## [[yii\validators\FileValidator|file(文件)]] <span id="file"></span>

66
docs/guide-zh-CN/tutorial-yii-integration.md

@ -1,8 +1,8 @@
引入第三方代码
=============================
有时,你可能会需要在 Yii 应用中使用第三方的代码。又或者是你想要在第三方系统中把 Yii 作为类库引用。在下面这个板块中,
我们向你展示如何实现这些目标。
有时,你可能会需要在 Yii 应用中使用第三方的代码。又或者是你想要在第三方系统中把 Yii 作为类库引用。
在下面这个板块中,我们向你展示如何实现这些目标。
## 在 Yii 中使用第三方类库 <span id="using-libs-in-yii"></span>
@ -20,8 +20,8 @@
2. 运行 `php composer.phar install` 安装这些包。
这些Composer 包内的类库,可以通过 Composer 的自动加载器实现自动加载。
不过请确保你应用的[入口脚本](structure-entry-scripts.md)包含以下
几行用于加载 Composer 自动加载器的代码:
不过请确保你应用的[入口脚本](structure-entry-scripts.md)
包含以下几行用于加载 Composer 自动加载器的代码:
```php
// install Composer autoloader (安装 Composer 自动加载器)
@ -34,8 +34,8 @@ require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
### 使用下载的类库 <span id="using-downloaded-libs"></span>
若你的类库并未发布为一个 Composer 包,你可以参考以下安装说明来安装它。
在大多数情况下,你需要预先下载一个发布文件,并把它解压缩到
`BasePath/vendor` 目录,这里的 `BasePath` 代指你应用程序自身的 [base path(主目录)](structure-applications.md#basePath)。
在大多数情况下,你需要预先下载一个发布文件,并把它解压缩到`BasePath/vendor` 目录,
这里的 `BasePath` 代指你应用程序自身的 [base path(主目录)](structure-applications.md#basePath)。
若该类库包含他自己的类自动加载器,你可以把它安装到你应用的[入口脚本](structure-entry-scripts.md)里。
我们推荐你把它的安装代码置于`Yii.php` 的导入之前,
@ -55,15 +55,16 @@ require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
]
```
若以上情形都不符合,最可能是这些类库需要依赖于 PHP 的 include_path 配置,
来正确定位并导入类文件。只需参考它的安装说明简单地配置一下 PHP 导入路径即可。
若以上情形都不符合,最可能是这些类库需要依赖于 PHP 的 include_path 配置,来正确定位并导入类文件。
只需参考它的安装说明简单地配置一下 PHP 导入路径即可。
最悲催的情形是,该类库需要显式导入每个类文件,
你可以使用以下方法按需导入相关类文件:
* 找出该库内包含哪些类。
* 在应用的[入口脚本](structure-entry-scripts.md)里的 `Yii::$classMap` 数组中列出这些类,
和他们各自对应的文件路径。举例来说,
* 在应用的[入口脚本](structure-entry-scripts.md)里的 `Yii::$classMap` 数组中列出这些类,和他们各自对应的文件路径。
举例来说,
```php
Yii::$classMap['Class1'] = 'path/to/Class1.php';
Yii::$classMap['Class2'] = 'path/to/Class2.php';
@ -74,37 +75,22 @@ Yii::$classMap['Class2'] = 'path/to/Class2.php';
--------------------------------
因为 Yii 提供了很多牛逼的功能,有时,你可能会想要使用它们中的一些功能用来支持开发或完善某些第三方的系统,
比如:WordPress,Joomla,或是用其他 PHP 框架开发的应用程序。举两个例子吧,
你可能会想念方便的 [[yii\helpers\ArrayHelper]] 类,或在第三方系统中使用
[Active Record](db-active-record.md) 活动记录功能。要实现这些目标,
你只需两个步骤:安装 Yii,启动 Yii。
比如:WordPress,Joomla,或是用其他 PHP 框架开发的应用程序。
举两个例子吧,你可能会想念方便的 [[yii\helpers\ArrayHelper]] 类,或在第三方系统中使用
[Active Record](db-active-record.md) 活动记录功能。
要实现这些目标,你只需两个步骤:安装 Yii,启动 Yii。
若这个第三方系统支持 Composer 管理他的依赖文件,
你可以直接运行一下命令来安装 Yii:
composer global require "fxp/composer-asset-plugin:^1.3.1"
composer require yiisoft/yii2
composer install
The first command installs the [composer asset plugin](https://github.com/francoispluchino/composer-asset-plugin/)
which allows managing bower and npm package dependencies through Composer. Even if you only want to use the database
layer or other non-asset related features of Yii, this is required to install the Yii composer package.
If you want to use the [Asset publishing feature of Yii](structure-assets.md) you should also add the following configuration
to the `extra` section in your `composer.json`:
```json
{
...
"extra": {
"asset-installer-paths": {
"npm-asset-library": "vendor/npm",
"bower-asset-library": "vendor/bower"
}
}
}
```bash
composer require yiisoft/yii2
```
In case you would like to use only the database abstraction layer or other non-asset related features of Yii,
you should require a special composer package that prevent Bower and NPM packages installation. See
[cebe/assetfree-yii2](https://github.com/cebe/assetfree-yii2) for details.
See also the general [section about installing Yii](start-installation.md#installing-via-composer) for more information
on Composer and solution to possible issues popping up during the installation.
@ -125,9 +111,9 @@ new yii\web\Application($yiiConfig); // 千万别在这调用 run() 方法。(
因为,`run()` 方法的调用会接管 HTTP 请求的处理流程。
(译注:换言之,这就不是第三方系统而是 Yii 系统了,URL 规则也会跟着换成 Yii 的规则了)
与 Yii 应用中一样,你可以依据运行该第三方系统的环境,
针对性地配置 Yii 应用实例。比如,
为了使用[活动记录](db-active-record.md)功能,你需要先用该第三方系统的 DB 连接信息,配置 Yii 的 `db` 应用组件。
与 Yii 应用中一样,你可以依据运行该第三方系统的环境,针对性地配置 Yii 应用实例。
比如,为了使用[活动记录](db-active-record.md)功能
你需要先用该第三方系统的 DB 连接信息,配置 Yii 的 `db` 应用组件。
现在,你就可以使用 Yii 提供的绝大多数功能了。
比如,创建 AR 类,并用它们来操作数据库。
@ -140,8 +126,8 @@ new yii\web\Application($yiiConfig); // 千万别在这调用 run() 方法。(
不必用 Yii 2 重写整个应用,你也可以通过增添对哪些
Yii 2 独占功能的支持来增强这个系统。下面我们就来详细描述一下具体的实现过程。
> 注意:Yii 2 需要 PHP 5.4+ 的版本。
> 你需要确保你的服务器以及现有应用都可以支持 PHP 5.4。
> Note: Yii 2 需要 PHP 5.4+ 的版本。你需要确保你的服务器以及现有应用都
> 可以支持 PHP 5.4。
首先,参考前文板块中给出的方法,在已有的应用中安装 Yii 2。

Loading…
Cancel
Save