diff --git a/docs/guide-zh-CN/blocktypes.json b/docs/guide-zh-CN/blocktypes.json
deleted file mode 100644
index 67d0c6e..0000000
--- a/docs/guide-zh-CN/blocktypes.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "Warning:": "警告:",
- "Note:": "注意:",
- "Info:": "补充:",
- "Tip:": "提示:"
-}
\ No newline at end of file
diff --git a/docs/guide-zh-CN/caching-data.md b/docs/guide-zh-CN/caching-data.md
index a1d98ca..45fcfa8 100644
--- a/docs/guide-zh-CN/caching-data.md
+++ b/docs/guide-zh-CN/caching-data.md
@@ -1,9 +1,12 @@
数据缓存
============
-数据缓存是指将一些 PHP 变量存储到缓存中,使用时再从缓存中取回。它也是更高级缓存特性的基础,例如[查询缓存](#query-caching)和[内容缓存](caching-content.md)。
+数据缓存是指将一些 PHP 变量存储到缓存中,使用时再从缓存中取回。
+它也是更高级缓存特性的基础,例如[查询缓存](#query-caching)
+和[内容缓存](caching-content.md)。
-如下代码是一个典型的数据缓存使用模式。其中 `$cache` 指向[缓存组件](#cache-components):
+如下代码是一个典型的数据缓存使用模式。其中 `$cache` 指向
+[缓存组件](#cache-components):
```php
// 尝试从缓存中取回 $data
@@ -23,9 +26,13 @@ if ($data === false) {
## 缓存组件
-数据缓存需要**缓存组件**提供支持,它代表各种缓存存储器,例如内存,文件,数据库。
+数据缓存需要**缓存组件**提供支持,它代表各种缓存存储器,
+例如内存,文件,数据库。
-缓存组件通常注册为应用程序组件,这样它们就可以在全局进行配置与访问。如下代码演示了如何配置应用程序组件 `cache` 使用两个 [memcached](http://memcached.org/) 服务器:
+缓存组件通常注册为应用程序组件,这样
+它们就可以在全局进行配置与访问。
+如下代码演示了如何配置应用程序组件 `cache` 使用
+两个 [memcached](http://memcached.org/) 服务器:
```php
'components' => [
@@ -49,7 +56,9 @@ if ($data === false) {
然后就可以通过 `Yii::$app->cache` 访问上面的缓存组件了。
-由于所有缓存组件都支持同样的一系列 API ,并不需要修改使用缓存的业务代码就能直接替换为其他底层缓存组件,只需在应用配置中重新配置一下就可以。例如,你可以将上述配置修改为使用 [[yii\caching\ApcCache|APC cache]]:
+由于所有缓存组件都支持同样的一系列 API ,并不需要修改使用缓存的
+业务代码就能直接替换为其他底层缓存组件,只需在应用配置中重新配置一下就可以。
+例如,你可以将上述配置修改为使用 [[yii\caching\ApcCache|APC cache]]:
```php
@@ -60,44 +69,74 @@ if ($data === false) {
],
```
-> Tip: 你可以注册多个缓存组件,很多依赖缓存的类默认调用名为 `cache` 的组件(例如 [[yii\web\UrlManager]])。
+> Tip: 你可以注册多个缓存组件,很多依赖缓存的类默认调用
+ 名为 `cache` 的组件(例如 [[yii\web\UrlManager]])。
### 支持的缓存存储器
Yii 支持一系列缓存存储器,概况如下:
-* [[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` 可能是 `null`。
-* [[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 及以上版本的支持 )。
-* [[yii\caching\WinCache]]:使用 PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension)([另可参考](http://php.net/manual/en/book.wincache.php))扩展.
+* [[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` 可能是 `null`。
+* [[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 及以上版本的支持 )。
+* [[yii\caching\WinCache]]:使用 PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension)
+ ([另可参考](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) 作为底层缓存媒介。
+* [[yii\caching\ZendDataCache]]:使用
+ [Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm)
+ 作为底层缓存媒介。
-> Tip: 你可以在同一个应用程序中使用不同的缓存存储器。一个常见的策略是使用基于内存的缓存存储器存储小而常用的数据(例如:统计数据),使用基于文件或数据库的缓存存储器存储大而不太常用的数据(例如:网页内容)。
+> Tip: 你可以在同一个应用程序中使用不同的缓存存储器。一个常见的策略是使用基于内存的缓存存储器
+ 存储小而常用的数据(例如:统计数据),使用基于文件
+ 或数据库的缓存存储器存储大而不太常用的数据(例如:网页内容)。
## 缓存 API
所有缓存组件都有同样的基类 [[yii\caching\Cache]] ,因此都支持如下 API:
-* [[yii\caching\Cache::get()|get()]]:通过一个指定的键(key)从缓存中取回一项数据。如果该项数据不存在于缓存中或者已经过期/失效,则返回值 false。
+* [[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::madd()|madd()]]:将多项数据存储到缓存中,每项数据对应一个键。
+ 如果某个键已经存在于缓存中,则该项数据会被跳过。
* [[yii\caching\Cache::exists()|exists()]]:返回一个值,指明某个键是否存在于缓存中。
* [[yii\caching\Cache::delete()|delete()]]:通过一个键,删除缓存中对应的值。
* [[yii\caching\Cache::flush()|flush()]]:删除缓存中的所有数据。
-有些缓存存储器如 MemCache,APC 支持以批量模式取回缓存值,这样可以节省取回缓存数据的开支。 [[yii\caching\Cache::mget()|mget()]] 和 [[yii\caching\Cache::madd()|madd()]] API提供对该特性的支持。如果底层缓存存储器不支持该特性,Yii 也会模拟实现。
+> 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.
-由于 [[yii\caching\Cache]] 实现了 PHP `ArrayAccess` 接口,缓存组件也可以像数组那样使用,下面是几个例子:
+有些缓存存储器如 MemCache,APC 支持以批量模式取回缓存值,这样可以节省取回
+缓存数据的开支。[[yii\caching\Cache::mget()|mget()]] 和
+[[yii\caching\Cache::madd()|madd()]] API提供对该特性的支持。
+如果底层缓存存储器不支持该特性,Yii 也会模拟实现。
+
+由于 [[yii\caching\Cache]] 实现了 PHP `ArrayAccess` 接口,缓存组件也可以像数组那样使用,
+下面是几个例子:
```php
$cache['var1'] = $value1; // 等价于: $cache->set('var1', $value1);
@@ -107,11 +146,15 @@ $value2 = $cache['var2']; // 等价于: $value2 = $cache->get('var2');
### 缓存键
-存储在缓存中的每项数据都通过键作唯一识别。当你在缓存中存储一项数据时,必须为它指定一个键,稍后从缓存中取回数据时,也需要提供相应的键。
+存储在缓存中的每项数据都通过键作唯一识别。当你在缓存中存储一项
+数据时,必须为它指定一个键,稍后从缓存中取回数据时,也需要提供
+相应的键。
-你可以使用一个字符串或者任意值作为一个缓存键。当键不是一个字符串时,它将会自动被序列化为一个字符串。
+你可以使用一个字符串或者任意值作为一个缓存键。当键不是一个字符串时,它将会自动
+被序列化为一个字符串。
-定义一个缓存键常见的一个策略就是在一个数组中包含所有的决定性因素。例如,[[yii\db\Schema]] 使用如下键存储一个数据表的结构信息。
+定义一个缓存键常见的一个策略就是在一个数组中包含所有的决定性因素。
+例如,[[yii\db\Schema]] 使用如下键存储一个数据表的结构信息。
```php
[
@@ -124,7 +167,9 @@ $value2 = $cache['var2']; // 等价于: $value2 = $cache->get('var2');
如你所见,该键包含了可唯一指定一个数据库表所需的所有必要信息。
-当同一个缓存存储器被用于多个不同的应用时,应该为每个应用指定一个唯一的缓存键前缀以避免缓存键冲突。可以通过配置 [[yii\caching\Cache::keyPrefix]] 属性实现。例如,在应用配置中可以编写如下代码:
+当同一个缓存存储器被用于多个不同的应用时,应该为每个应用指定一个唯一的缓存键前缀
+以避免缓存键冲突。可以通过配置 [[yii\caching\Cache::keyPrefix]]
+属性实现。例如,在应用配置中可以编写如下代码:
```php
'components' => [
@@ -140,7 +185,12 @@ $value2 = $cache['var2']; // 等价于: $value2 = $cache->get('var2');
### 缓存过期
-默认情况下,缓存中的数据会永久存留,除非它被某些缓存策略强制移除(例如:缓存空间已满,最老的数据会被移除)。要改变此特性,你可以在调用 [[yii\caching\Cache::set()|set()]] 存储一项数据时提供一个过期时间参数。该参数代表这项数据在缓存中可保持有效多少秒。当你调用 [[yii\caching\Cache::get()|get()]] 取回数据时,如果它已经过了超时时间,该方法将返回 false,表明在缓存中找不到这项数据。例如:
+默认情况下,缓存中的数据会永久存留,除非它被某些缓存策略强制移除(例如:
+缓存空间已满,最老的数据会被移除)。要改变此特性,你可以在调用
+[[yii\caching\Cache::set()|set()]] 存储一项数据时提供一个过期时间参数。
+该参数代表这项数据在缓存中可保持有效多少秒。当你调用
+[[yii\caching\Cache::get()|get()]] 取回数据时,如果它已经过了超时时间,
+该方法将返回 false,表明在缓存中找不到这项数据。例如:
```php
// 将数据在缓存中保留 45 秒
@@ -157,9 +207,15 @@ if ($data === false) {
### 缓存依赖
-除了超时设置,缓存数据还可能受到**缓存依赖**的影响而失效。例如,[[yii\caching\FileDependency]] 代表对一个文件修改时间的依赖。这个依赖条件发生变化也就意味着相应的文件已经被修改。因此,缓存中任何过期的文件内容都应该被置为失效状态,对 [[yii\caching\Cache::get()|get()]] 的调用都应该返回 false。
+除了超时设置,缓存数据还可能受到**缓存依赖**的影响而失效。
+例如,[[yii\caching\FileDependency]] 代表对一个文件修改时间的依赖。
+这个依赖条件发生变化也就意味着相应的文件已经被修改。
+因此,缓存中任何过期的文件内容都应该被置为失效状态,
+对 [[yii\caching\Cache::get()|get()]] 的调用都应该返回 false。
-缓存依赖用 [[yii\caching\Dependency]] 的派生类所表示。当调用 [[yii\caching\Cache::set()|set()]] 在缓存中存储一项数据时,可以同时传递一个关联的缓存依赖对象。例如:
+缓存依赖用 [[yii\caching\Dependency]] 的派生类所表示。当调用
+[[yii\caching\Cache::set()|set()]] 在缓存中存储一项数据时,
+可以同时传递一个关联的缓存依赖对象。例如:
```php
// 创建一个对 example.txt 文件修改时间的缓存依赖
@@ -181,44 +237,150 @@ $data = $cache->get($key);
- [[yii\caching\DbDependency]]:如果指定 SQL 语句的查询结果发生了变化,则依赖改变。
- [[yii\caching\ExpressionDependency]]:如果指定的 PHP 表达式执行结果发生变化,则依赖改变。
- [[yii\caching\FileDependency]]:如果文件的最后修改时间发生变化,则依赖改变。
-- [[yii\caching\GroupDependency]]:将一项缓存数据标记到一个组名,你可以通过调用 [[yii\caching\GroupDependency::invalidate()]] 一次性将相同组名的缓存全部置为失效状态。
+- [[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\db\Connection|数据库连接]] 和一个有效的 `cache` 应用组件。查询缓存的基本用法如下,假设 `$db` 是一个 [[yii\db\Connection]] 实例:
+查询缓存需要一个 [[yii\db\Connection|数据库连接]] 和一个有效的 `cache` 应用组件。
+查询缓存的基本用法如下,假设 `$db` 是一个 [[yii\db\Connection]] 实例:
```php
-$duration = 60; // 缓存查询结果60秒
-$dependency = ...; // 可选的缓存依赖
-
-$db->beginCache($duration, $dependency);
+$result = $db->cache(function ($db) {
-// ...这儿执行数据库查询...
+ // the result of the SQL query will be served from the cache
+ // if query caching is enabled and the query result is found in the cache
+ return $db->createCommand('SELECT * FROM customer WHERE id=1')->queryOne();
-$db->endCache();
+});
```
-如你所见,`beginCache()` 和 `endCache()` 中间的任何查询结果都会被缓存起来。如果缓存中找到了同样查询的结果,则查询会被跳过,直接从缓存中提取结果。
-
查询缓存可以用于 [ActiveRecord](db-active-record.md) 和 [DAO](db-dao.md)。
-> Info: 有些 DBMS (例如:[MySQL](http://dev.mysql.com/doc/refman/5.1/en/query-cache.html))也支持数据库服务器端的查询缓存。你可以选择使用任一查询缓存机制。上文所述的查询缓存的好处在于你可以指定更灵活的缓存依赖因此可能更加高效。
+```php
+$result = Customer::getDb()->cache(function ($db) {
+ return Customer::find()->where(['id' => 1])->one();
+});
+
+
+> Info: 有些 DBMS (例如:[MySQL](http://dev.mysql.com/doc/refman/5.1/en/query-cache.html) )
+ 也支持数据库服务器端的查询缓存。你可以选择使用任一查询缓存机制。
+ 上文所述的查询缓存的好处在于你可以指定更灵活的缓存
+ 依赖因此可能更加高效。
+
+
+### Cache Flushing
+
+When you need to invalidate all the stored cache data, you can call [[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
+
+> 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.
### 配置
-查询缓存有两个通过 [[yii\db\Connection]] 设置的配置项:
+Query caching has three global configurable options through [[yii\db\Connection]]:
+
+* [[yii\db\Connection::enableQueryCache|enableQueryCache]]: whether to turn on or off query caching.
+ It defaults to true. Note that to effectively turn on query caching, you also need to have a valid
+ cache, as specified by [[yii\db\Connection::queryCache|queryCache]].
+* [[yii\db\Connection::queryCacheDuration|queryCacheDuration]]: this represents the number of seconds
+ that a query result can remain valid in the cache. You can use 0 to indicate a query result should
+ remain in the cache forever. This property is the default value used when [[yii\db\Connection::cache()]]
+ is called without specifying a duration.
+* [[yii\db\Connection::queryCache|queryCache]]: 缓存应用组件的 ID。默认为 `'cache'`。
+ 只有在设置了一个有效的缓存应用组件时,查询缓存才会有效。
+
+
+### Usages
+
+You can use [[yii\db\Connection::cache()]] if you have multiple SQL queries that need to take advantage of
+query caching. The usage is as follows,
+
+```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);
+```
-* [[yii\db\Connection::queryCacheDuration|queryCacheDuration]]: 查询结果在缓存中的有效期,以秒表示。如果在调用 [[yii\db\Connection::beginCache()]] 时传递了一个显式的时值参数,则配置中的有效期时值会被覆盖。
-* [[yii\db\Connection::queryCache|queryCache]]: 缓存应用组件的 ID。默认为 `'cache'`。只有在设置了一个有效的缓存应用组件时,查询缓存才会有效。
+Any SQL queries in the anonymous function will be cached for the specified duration with the specified dependency.
+If the result of a query is found valid in the cache, the query will be skipped and the result will be served
+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.
+
+```php
+$result = $db->cache(function ($db) {
+
+ // SQL queries that use query caching
+
+ $db->noCache(function ($db) {
+
+ // SQL queries that do not use query caching
+
+ });
+
+ // ...
+
+ return $result;
+});
+```
+
+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,
+
+```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,
+
+```php
+$result = $db->cache(function ($db) {
+
+ // SQL queries that use query caching
+
+ // do not use query caching for this command
+ $customer = $db->createCommand('SELECT * FROM customer WHERE id=1')->noCache()->queryOne();
+
+ // ...
+
+ return $result;
+});
+```
### 限制条件
-当查询结果中含有资源句柄时,查询缓存无法使用。例如,在有些 DBMS 中使用了 `BLOB` 列的时候,缓存结果会为该数据列返回一个资源句柄。
+当查询结果中含有资源句柄时,查询缓存无法使用。例如,
+在有些 DBMS 中使用了 `BLOB` 列的时候,缓存结果会为
+该数据列返回一个资源句柄。
-有些缓存存储器有大小限制。例如,memcache 限制每条数据最大为 1MB。因此,如果查询结果的大小超出了该限制,则会导致缓存失败。
+有些缓存存储器有大小限制。例如,memcache 限制每条数据
+最大为 1MB。因此,如果查询结果的大小超出了该限制,
+则会导致缓存失败。
diff --git a/docs/guide-zh-CN/caching-fragment.md b/docs/guide-zh-CN/caching-fragment.md
index 88698f6..4b9727e 100644
--- a/docs/guide-zh-CN/caching-fragment.md
+++ b/docs/guide-zh-CN/caching-fragment.md
@@ -1,7 +1,9 @@
片段缓存
================
-片段缓存指的是缓存页面内容中的某个片段。例如,一个页面显示了逐年销售额的摘要表格,可以把表格缓存下来,以消除每次请求都要重新生成表格的耗时。片段缓存是基于[数据缓存](caching-data.md)实现的。
+片段缓存指的是缓存页面内容中的某个片段。例如,一个页面显示了逐年销售额的摘要表格,
+可以把表格缓存下来,以消除每次请求都要重新生成表格
+的耗时。片段缓存是基于[数据缓存](caching-data.md)实现的。
在[视图](structure-views.md)中使用以下结构启用片段缓存:
@@ -14,18 +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` 标记。
## 缓存选项
-如果要为片段缓存指定额外配置项,请通过向 [[yii\base\View::beginCache()|beginCache()]] 方法第二个参数传递配置数组。在框架内部,该数组将被用来配置一个 [[yii\widget\FragmentCache]] 小部件用以实现片段缓存功能。
+如果要为片段缓存指定额外配置项,请通过向 [[yii\base\View::beginCache()|beginCache()]]
+方法第二个参数传递配置数组。在框架内部,
+该数组将被用来配置一个 [[yii\widget\FragmentCache]]
+小部件用以实现片段缓存功能。
### 过期时间(duration)
-或许片段缓存中最常用的一个配置选项就是 [[yii\widgets\FragmentCache::duration|duration]] 了。它指定了内容被缓存的秒数。以下代码缓存内容最多一小时:
+或许片段缓存中最常用的一个配置选项就是
+[[yii\widgets\FragmentCache::duration|duration]] 了。
+它指定了内容被缓存的秒数。以下代码缓存内容最多一小时:
```php
if ($this->beginCache($id, ['duration' => 3600])) {
@@ -36,14 +47,17 @@ if ($this->beginCache($id, ['duration' => 3600])) {
}
```
-如果该选项未设置,则默认为 0,永不过期。
+如果该选项未设置,it will take the default value 60, which means the cached content will expire in 60 seconds.
### 依赖
-和[[数据缓存]](caching-data.md)一样,片段缓存的内容一样可以设置缓存依赖。例如一段被缓存的文章,是否重新缓存取决于它是否被修改过。
+和[[数据缓存]](caching-data.md)一样,片段缓存的内容一样可以设置缓存依赖。例如
+一段被缓存的文章,是否重新缓存取决于它是否被修改过。
-通过设置 [[yii\widgets\FragmentCache::dependency|dependency]] 选项来指定依赖,该选项的值可以是一个 [[yii\caching\Dependency]] 类的派生类,也可以是创建缓存对象的配置数组。以下代码指定了一个片段缓存,它依赖于 `update_at` 字段是否被更改过的。
+通过设置 [[yii\widgets\FragmentCache::dependency|dependency]] 选项来指定依赖,
+该选项的值可以是一个 [[yii\caching\Dependency]] 类的派生类,也可以是创建缓存对象的配置数组。
+以下代码指定了一个片段缓存,它依赖于 `update_at` 字段是否被更改过的。
```php
$dependency = [
@@ -62,9 +76,13 @@ if ($this->beginCache($id, ['dependency' => $dependency])) {
### 变化
-缓存的内容可能需要根据一些参数的更改而变化。例如一个 Web 应用支持多语言,同一段视图代码也许需要生成多个语言的内容。因此可以设置缓存根据应用当前语言而变化。
+缓存的内容可能需要根据一些参数的更改而变化。例如一个 Web 应用
+支持多语言,同一段视图代码也许需要生成多个语言的内容。
+因此可以设置缓存根据应用当前语言而变化。
-通过设置 [[yii\widgets\FragmentCache::variations|variations]] 选项来指定变化,该选项的值应该是一个标量,每个标量代表不同的变化系数。例如设置缓存根据当前语言而变化可以用以下代码:
+通过设置 [[yii\widgets\FragmentCache::variations|variations]] 选项来指定变化,
+该选项的值应该是一个标量,每个标量代表不同的变化系数。
+例如设置缓存根据当前语言而变化可以用以下代码:
```php
if ($this->beginCache($id, ['variations' => [Yii::$app->language]])) {
@@ -78,7 +96,10 @@ if ($this->beginCache($id, ['variations' => [Yii::$app->language]])) {
### 开关
-有时你可能只想在特定条件下开启片段缓存。例如,一个显示表单的页面,可能只需要在初次请求时缓存表单(通过 GET 请求)。随后请求所显示(通过 POST 请求)的表单不该使用缓存,因为此时表单中可能包含用户输入内容。鉴于此种情况,可以使用 [[yii\widgets\FragmentCache::enabled|enabled]] 选项来指定缓存开关,如下所示:
+有时你可能只想在特定条件下开启片段缓存。例如,一个显示表单的页面,可能只
+需要在初次请求时缓存表单(通过 GET 请求)。随后请求所显示(通过 POST 请求)
+的表单不该使用缓存,因为此时表单中可能包含用户输入内容。鉴于此种情况,可以使用
+[[yii\widgets\FragmentCache::enabled|enabled]] 选项来指定缓存开关,如下所示:
```php
if ($this->beginCache($id, ['enabled' => Yii::$app->request->isGet])) {
@@ -92,7 +113,9 @@ if ($this->beginCache($id, ['enabled' => Yii::$app->request->isGet])) {
## 缓存嵌套
-片段缓存可以被嵌套使用。一个片段缓存可以被另一个包裹。例如,评论被缓存在里层,同时整个评论的片段又被缓存在外层的文章中。以下代码展示了片段缓存的嵌套使用:
+片段缓存可以被嵌套使用。一个片段缓存可以被另一个包裹。
+例如,评论被缓存在里层,同时整个评论的片段又被缓存在
+外层的文章中。以下代码展示了片段缓存的嵌套使用:
```php
if ($this->beginCache($id1)) {
@@ -112,18 +135,28 @@ if ($this->beginCache($id1)) {
}
```
-可以为嵌套的缓存设置不同的配置项。例如,内层缓存和外层缓存使用不同的过期时间。甚至当外层缓存的数据过期失效了,内层缓存仍然可能提供有效的片段缓存数据。但是,反之则不然。如果外层片段缓存没有过期而被视为有效,此时即使内层片段缓存已经失效,它也将继续提供同样的缓存副本。因此,你必须谨慎处理缓存嵌套中的过期时间和依赖,否则外层的片段很有可能返回的是不符合你预期的失效数据。
-
+可以为嵌套的缓存设置不同的配置项。例如,内层缓存和外层缓存使用
+不同的过期时间。甚至当外层缓存的数据过期失效了,内层缓存仍然
+可能提供有效的片段缓存数据。但是,反之则不然。如果外层片段缓存
+没有过期而被视为有效,此时即使内层片段缓存已经失效,它也将继续
+提供同样的缓存副本。因此,你必须谨慎处理缓存嵌套中的过期时间和
+依赖,否则外层的片段很有可能返回的是不符合你预期的失效数据。
> 译注:外层的失效时间应该短于内层,外层的依赖条件应该低于内层,以确保最小的片段,返回的是最新的数据。
-
## 动态内容
-使用片段缓存时,可能会遇到一大段较为静态的内容中有少许动态内容的情况。例如,一个显示着菜单栏和当前用户名的页面头部。还有一种可能是缓存的内容可能包含每次请求都需要执行的 PHP 代码(例如注册资源包的代码)。这两个问题都可以使用**动态内容**功能解决。
+使用片段缓存时,可能会遇到一大段较为静态的内容中有少许动态内
+容的情况。例如,一个显示着菜单栏和当前用户名的页面头部。还有
+一种可能是缓存的内容可能包含每次请求都需要执行的 PHP 代码
+(例如注册资源包的代码)。这两个问题都可以
+使用 **动态内容** 功能解决。
-动态内容的意思是这部分输出的内容不该被缓存,即便是它被包裹在片段缓存中。为了使内容保持动态,每次请求都执行 PHP 代码生成,即使这些代码已经被缓存了。
+动态内容的意思是这部分输出的内容不该被缓存,即便是它被包裹
+在片段缓存中。为了使内容保持动态,每次请求都执行 PHP 代码
+生成,即使这些代码已经被缓存了。
-可以在片段缓存中调用 [[yii\base\View::renderDynamic()]] 去插入动态内容,如下所示:
+可以在片段缓存中调用 [[yii\base\View::renderDynamic()]] 去
+插入动态内容,如下所示:
```php
if ($this->beginCache($id1)) {
@@ -138,4 +171,6 @@ if ($this->beginCache($id1)) {
}
```
-[[yii\base\View::renderDynamic()|renderDynamic()]] 方法接受一段 PHP 代码作为参数。代码的返回值被看作是动态内容。这段代码将在每次请求时都执行,无论其外层的片段缓存是否被存储。
+[[yii\base\View::renderDynamic()|renderDynamic()]] 方法接受
+一段 PHP 代码作为参数。代码的返回值被看作是动态内容。这段代
+码将在每次请求时都执行,无论其外层的片段缓存是否被存储。
diff --git a/docs/guide-zh-CN/caching-http.md b/docs/guide-zh-CN/caching-http.md
index 2284197..000ec3a 100644
--- a/docs/guide-zh-CN/caching-http.md
+++ b/docs/guide-zh-CN/caching-http.md
@@ -1,9 +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]]
@@ -14,7 +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
/**
@@ -43,14 +48,23 @@ public function behaviors()
}
```
-上述代码表明 HTTP 缓存只在 `index` 操作时启用。它会基于页面最后修改时间生成一个 `Last-Modified` HTTP 头。当浏览器第一次访问 `index` 页时,服务器将会生成页面并发送至客户端浏览器。之后客户端浏览器在页面没被修改期间访问该页,服务器将不会重新生成页面,浏览器会使用之前客户端缓存下来的内容。因此服务端渲染和内容传输都将省去。
+上述代码表明 HTTP 缓存只在 `index` 操作时启用。它会基于页面
+最后修改时间生成一个 `Last-Modified` HTTP 头。当浏览器第一
+次访问 `index` 页时,服务器将会生成页面并发送至客户端浏览器。
+之后客户端浏览器在页面没被修改期间访问该页,服务器将不会重新
+生成页面,浏览器会使用之前客户端缓存下来的内容。因此服务端
+渲染和内容传输都将省去。
## `ETag` 头
-“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
/**
@@ -79,24 +93,31 @@ public function behaviors()
}
```
-上述代码表明 HTTP 缓存只在 `view` 操作时启用。它会基于用户请求的标题和内容生成一个 `ETag` HTTP 头。当浏览器第一次访问 `view` 页时,服务器将会生成页面并发送至客户端浏览器。之后客户端浏览器标题和内容没被修改在期间访问该页,服务器将不会重新生成页面,浏览器会使用之前客户端缓存下来的内容。因此服务端渲染和内容传输都将省去。
+上述代码表明 HTTP 缓存只在 `view` 操作时启用。它会基于用户
+请求的标题和内容生成一个 `ETag` HTTP 头。当浏览器第一次访问
+`view` 页时,服务器将会生成页面并发送至客户端浏览器。之后
+客户端浏览器标题和内容没被修改在期间访问该页,服务器将不会
+重新生成页面,浏览器会使用之前客户端缓存下来的内容。
+因此服务端渲染和内容传输都将省去。
-ETag 相比 `Last-Modified` 能实现更复杂和更精确的缓存策略。例如,当站点切换到另一个主题时可以使 ETag 失效。
+ETag 相比 `Last-Modified` 能实现更复杂和更精确的缓存策略。
+例如,当站点切换到另一个主题时可以使 ETag 失效。
-复杂的 Etag 生成种子可能会违背使用 `HttpCache` 的初衷而引起不必要的性能开销,因为响应每一次请求都需要重新计算 Etag。请试着找出一个最简单的表达式去触发 Etag 失效。
-
-
-<<<<<<< .merge_file_a06996
-> 注意:为了遵循 [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` 头,则只有前者会被接受。
->>>>>>> .merge_file_a01948
+复杂的 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` 头,则只有前者会被接受。
## `Cache-Control` 头
-`Cache-Control` 头指定了页面的常规缓存策略。可以通过配置 [[yii\filters\HttpCache::cacheControlHeader]] 属性发送相应的头信息。默认发送以下头:
+`Cache-Control` 头指定了页面的常规缓存策略。可以通过配置
+[[yii\filters\HttpCache::cacheControlHeader]] 属性发送相
+应的头信息。默认发送以下头:
```
Cache-Control: public, max-age=3600
@@ -104,10 +125,19 @@ Cache-Control: public, max-age=3600
## 会话缓存限制器
-当页面使 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 影响
-搜索引擎趋向于遵循站点的缓存头。因为一些爬虫的抓取频率有限制,启用缓存头可以可以减少重复请求数量,增加爬虫抓取效率(译者:大意如此,但搜索引擎的排名规则不了解,好的缓存策略应该是可以为用户体验加分的)。
+搜索引擎趋向于遵循站点的缓存头。因为一些爬虫的
+抓取频率有限制,启用缓存头可以可以减少重复请求
+数量,增加爬虫抓取效率(译者:大意如此,但搜索引擎的排名规则不了解,好的缓存策略应该是可以为用户体验加分的)。
diff --git a/docs/guide-zh-CN/caching-overview.md b/docs/guide-zh-CN/caching-overview.md
index b9345cd..1a06d70 100644
--- a/docs/guide-zh-CN/caching-overview.md
+++ b/docs/guide-zh-CN/caching-overview.md
@@ -1,15 +1,17 @@
缓存
=======
-缓存是提升 Web 应用性能简便有效的方式。通过将相对静态的数据存储到缓存并在收到请求时取回缓存,应用程序便节省了每次重新生成这些数据所需的时间。
+缓存是提升 Web 应用性能简便有效的方式。通过将相对静态的数据
+存储到缓存并在收到请求时取回缓存,应用程序便节省了每次重新生
+成这些数据所需的时间。
-缓存可以应用在 Web 应用程序的任何层级任何位置。在服务器端,在较的低层面,缓存可能用于存储基础数据,例如从数据库中取出的最新文章列表;在较高的层面,缓存可能用于存储一段或整个 Web 页面,例如最新文章的渲染结果。在客户端,HTTP 缓存可能用于将最近访问的页面内容存储到浏览器缓存中。
+缓存可以应用在 Web 应用程序的任何层级任何位置。在服务器端,
+在较的低层面,缓存可能用于存储基础数据,例如从数据库中取
+出的最新文章列表;在较高的层面,缓存可能用于存储一段或整
+个 Web 页面,例如最新文章的渲染结果。在客户端,HTTP 缓存
+可能用于将最近访问的页面内容存储到浏览器缓存中。
-<<<<<<< .merge_file_a06272
Yii 支持如上所有缓存机制:
-=======
-Yii 支持如下所有缓存机制:
->>>>>>> .merge_file_a04468
* [数据缓存](caching-data.md)
* [片段缓存](caching-fragment.md)
diff --git a/docs/guide-zh-CN/caching-page.md b/docs/guide-zh-CN/caching-page.md
index a7275a2..f395274 100644
--- a/docs/guide-zh-CN/caching-page.md
+++ b/docs/guide-zh-CN/caching-page.md
@@ -1,9 +1,11 @@
页面缓存
============
-页面缓存指的是在服务器端缓存整个页面的内容。随后当同一个页面被请求时,内容将从缓存中取出,而不是重新生成。
+页面缓存指的是在服务器端缓存整个页面的内容。随后当同一个页面
+被请求时,内容将从缓存中取出,而不是重新生成。
-页面缓存由 [[yii\filters\PageCache]] 类提供支持,该类是一个[过滤器](structure-filters.md)。它可以像这样在控制器类中使用:
+页面缓存由 [[yii\filters\PageCache]] 类提供支持,该类是一个
+[过滤器](structure-filters.md)。它可以像这样在控制器类中使用:
```php
public function behaviors()
@@ -25,16 +27,14 @@ public function behaviors()
}
```
-上述代码表示页面缓存只在 `index` 操作时启用,页面内容最多被缓存 60 秒,会随着当前应用的语言更改而变化。如果文章总数发生变化则缓存的页面会失效。
-
-如你所见,页面缓存和[片段缓存](caching-fragment.md)极其相似。它们都支持 `duration`,`dependencies`,`variations` 和 `enabled` 配置选项。它们的主要区别是页面缓存是由[过滤器](structure-filters.md)实现,而片段缓存则是一个[小部件](structure-widgets.md)。
-
-你可以在使用页面缓存的同时,使用[片段缓存](caching-fragment.md)和[动态内容](caching-fragment.md#dynamic-content)。
-
-
-
-
-
+上述代码表示页面缓存只在 `index` 操作时启用,页面内容最多被缓存
+60 秒,会随着当前应用的语言更改而变化。如果文章总数发生变化则缓
+存的页面会失效。
+如你所见,页面缓存和[片段缓存](caching-fragment.md)极其相似。它们都支持 `duration`,`dependencies`,
+`variations` 和 `enabled` 配置选项。它们的主要区别是页面缓存是由[过滤器](structure-filters.md)实现,
+而片段缓存则是一个[小部件](structure-widgets.md)。
+你可以在使用页面缓存的同时,使用[片段缓存](caching-fragment.md)和
+[动态内容](caching-fragment.md#dynamic-content)。
diff --git a/docs/guide-zh-CN/concept-aliases.md b/docs/guide-zh-CN/concept-aliases.md
index f2f05ba..31ce278 100644
--- a/docs/guide-zh-CN/concept-aliases.md
+++ b/docs/guide-zh-CN/concept-aliases.md
@@ -1,8 +1,12 @@
别名(Aliases)
=======
-别名用来表示文件路径和 URL,这样就避免了在代码中硬编码一些绝对路径和 URL。一个别名必须以 `@` 字符开头,以区别于传统的文件路径和 URL。Yii 预定义了大量可用的别名。例如,别名 `@yii` 指的是 Yii 框架本身的安装目录,而 `@web` 表示的是当前运行应用的根 URL。
+别名用来表示文件路径和 URL,这样就避免了在代码中硬编码一些绝对路径
+和 URL。一个别名必须以 `@` 字符开头,以区别于传统的文件路径和 URL。
+Alias defined without leading `@` will be prefixed with `@` character.
+Yii 预定义了大量可用的别名。例如,别名 `@yii` 指的是 Yii 框架本身的安装
+目录,而 `@web` 表示的是当前运行应用的根 URL。
定义别名
----------------
@@ -17,13 +21,12 @@ Yii::setAlias('@foo', '/path/to/foo');
Yii::setAlias('@bar', 'http://www.example.com');
```
-<<<<<<< .merge_file_a06852
> 注意:别名所指向的文件路径或 URL 不一定是真实存在的文件或资源。
-=======
-> Note: 别名所指向的文件路径或 URL 不一定是真实存在的文件或资源。
->>>>>>> .merge_file_a04208
-可以通过在一个别名后面加斜杠 `/` 和一至多个路径分段生成新别名(无需调用 [[Yii::setAlias()]])。我们把通过 [[Yii::setAlias()]] 定义的别名称为**根别名**,而用他们衍生出去的别名成为**衍生别名**。例如,`@foo` 就是根别名,而 `@foo/bar/file.php` 是一个衍生别名。
+可以通过在一个别名后面加斜杠 `/` 和一至多个路径分段生成新别名
+(无需调用 [[Yii::setAlias()]])。我们把通过 [[Yii::setAlias()]]
+定义的别名称为**根别名**,而用他们衍生出去的别名成为**衍生别名**。
+例如,`@foo` 就是根别名,而 `@foo/bar/file.php` 是一个衍生别名。
你还可以用别名去定义新别名(根别名与衍生别名均可):
@@ -31,7 +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 [
@@ -47,7 +53,8 @@ return [
解析别名
-----------------
-你可以调用 [[Yii::getAlias()]] 命令来解析根别名到对应的文件路径或 URL。同样的页面也可以用于解析衍生别名。例如:
+你可以调用 [[Yii::getAlias()]] 命令来解析根别名到对应的文件路径或 URL。
+同样的页面也可以用于解析衍生别名。例如:
```php
echo Yii::getAlias('@foo'); // 输出:/path/to/foo
@@ -55,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 是通过替换掉衍生别名
+中的根别名部分得到的。
-<<<<<<< .merge_file_a06852
> 注意:[[Yii::getAlias()]] 并不检查结果路径/URL 所指向的资源是否真实存在。
-=======
-> Note: [[Yii::getAlias()]] 并不检查结果路径/URL 所指向的资源是否真实存在。
->>>>>>> .merge_file_a04208
-根别名可能也会包含斜杠 `/`。[[Yii::getAlias()]] 足够智能到判断一个别名中的哪部分是根别名,因此能正确解析文件路径/URL。例如:
+
+根别名可能也会包含斜杠 `/`。[[Yii::getAlias()]]
+足够智能到判断一个别名中的哪部分是根别名,因此
+能正确解析文件路径/URL。例如:
```php
Yii::setAlias('@foo', '/path/to/foo');
@@ -78,7 +85,10 @@ echo Yii::getAlias('@foo/bar/file.php'); // 输出:/path2/bar/file.php
使用别名
-------------
-别名在 Yii 的很多地方都会被正确识别,无需调用 [[Yii::getAlias()]] 来把它们转换为路径/URL。例如,[[yii\caching\FileCache::cachePath]] 能同时接受文件路径或是指向文件路径的别名,因为通过 `@` 前缀能区分它们。
+别名在 Yii 的很多地方都会被正确识别,无需调用 [[Yii::getAlias()]]
+来把它们转换为路径/URL。例如,[[yii\caching\FileCache::cachePath]]
+能同时接受文件路径或是指向文件路径的别名,
+因为通过 `@` 前缀能区分它们。
```php
use yii\caching\FileCache;
@@ -96,21 +106,29 @@ $cache = new FileCache([
Yii 预定义了一系列别名来简化常用路径和 URL 的使用:
-- `@yii` - `BaseYii.php` 文件所在的目录(也被称为框架安装目录)
-- `@app` - 当前运行的应用 [[yii\base\Application::basePath|根路径(base path)]]
-- `@runtime` - 当前运行的应用的 [[yii\base\Application::runtimePath|运行环境(runtime)路径]]
-- `@vendor` - [[yii\base\Application::vendorPath|Composer 供应商目录]]
-- `@webroot` - 当前运行应用的 Web 入口目录
-- `@web` - 当前运行应用的根 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` 别名是在[入口脚本](structure-entry-scripts.md)里包含 `Yii.php` 文件时定义的,其他的别名都是在[配置应用](concept-configurations.md)的时候,于应用的构造方法内定义的。
+`@yii` 别名是在[入口脚本](structure-entry-scripts.md)里包含 `Yii.php` 文件时定义的,
+其他的别名都是在[配置应用](concept-configurations.md)的时候,
+于应用的构造方法内定义的。
扩展的别名
-----------------
-每一个通过 Composer 安装的 [扩展](structure-extensions.md) 都自动添加了一个别名。该别名会以该扩展在 `composer.json` 文件中所声明的根命名空间为名,且他直接代指该包的根目录。例如,如果你安装有 `yiisoft/yii2-jui` 扩展,会自动得到 `@yii/jui` 别名,它定义于[引导启动](runtime-bootstrapping.md)阶段:
+每一个通过 Composer 安装的 [扩展](structure-extensions.md) 都自动添加了一个别名。
+该别名会以该扩展在 `composer.json` 文件中所声明的根命名空间为名,且他直接代指该包的根目录。
+例如,如果你安装有 `yiisoft/yii2-jui` 扩展,
+会自动得到 `@yii/jui` 别名,它定义于[引导启动](runtime-bootstrapping.md)阶段:
```php
Yii::setAlias('@yii/jui', 'VendorPath/yiisoft/yii2-jui');
-```
\ No newline at end of file
+```
diff --git a/docs/guide-zh-CN/concept-autoloading.md b/docs/guide-zh-CN/concept-autoloading.md
index 6d88e41..df9864d 100644
--- a/docs/guide-zh-CN/concept-autoloading.md
+++ b/docs/guide-zh-CN/concept-autoloading.md
@@ -1,13 +1,13 @@
类自动加载(Autoloading)
=================
-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)([中文汉化](https://github.com/hfcorriez/fig-standards/blob/zh_CN/%E6%8E%A5%E5%8F%97/PSR-4-autoloader.md))的自动加载器。该自动加载器会在引入框架文件 `Yii.php` 时安装好。
+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)
+([中文汉化](https://github.com/hfcorriez/fig-standards/blob/zh_CN/%E6%8E%A5%E5%8F%97/PSR-4-autoloader.md))的自动加载器。
+该自动加载器会在引入框架文件 `Yii.php` 时安装好。
-<<<<<<< .merge_file_a06860
-> 注意:为了简化叙述,本篇文档中我们只会提及类的自动加载。不过,要记得文中的描述同样也适用于接口和Trait(特质)的自动加载哦。
-=======
-> Note: 为了简化叙述,本篇文档中我们只会提及类的自动加载。不过,要记得文中的描述同样也适用于接口和Trait(特质)的自动加载哦。
->>>>>>> .merge_file_a06468
+> 注意:为了简化叙述,本篇文档中我们只会提及类的自动加载。
+不过,要记得文中的描述同样也适用于接口和Trait(特质)的自动加载哦。
使用 Yii 自动加载器
@@ -23,18 +23,28 @@ Yii 依靠[类自动加载机制](http://www.php.net/manual/en/language.oop5.aut
$classFile = Yii::getAlias('@' . str_replace('\\', '/', $className) . '.php');
```
-举例来说,若某个类名为 `foo\bar\MyClass`,对应类的文件路径[别名](concept-aliases.md)会是 `@foo/bar/MyClass.php`。为了让该别名能被正确解析为文件路径,`@foo` 或 `@foo/bar`
+举例来说,若某个类名为 `foo\bar\MyClass`,对应类的文件路径[别名](concept-aliases.md)会是 `@foo/bar/MyClass.php`。
+为了让该别名能被正确解析为文件路径,`@foo` 或 `@foo/bar`
中的一个必须是[根别名](concept-aliases.md#defining-aliases)。
-当我们使用[基本应用模版](start-installation.md)时,可以把你的类放置在顶级命名空间 `app` 下,这样它们就可以被 Yii 自动加载,而无需定义一个新的别名。这是因为 `@app` 本身是一个[预定义别名](concept-aliases.md#predefined-aliases),且类似于 `app\components\MyClass` 这样的类名,基于我们刚才所提到的算法,可以正确解析出 `AppBasePath/components/MyClass.php` 路径。
+当我们使用[基本应用模版](start-installation.md)时,可以把你的类放置在顶级命名空间 `app` 下,
+这样它们就可以被 Yii 自动加载,而无需定义一个新的别名。
+这是因为 `@app` 本身是一个[预定义别名](concept-aliases.md#predefined-aliases),且类似于 `app\components\MyClass` 这样的类名,
+基于我们刚才所提到的算法,可以正确解析出 `AppBasePath/components/MyClass.php` 路径。
-在[高级应用模版](tutorial-advanced-app.md)里,每一逻辑层级会使用他自己的根别名。比如,前端层会使用 `@frontend` 而后端层会使用 `@backend`。因此,你可以把前端的类放在 `frontend` 命名空间,而后端的类放在 `backend`。 这样这些类就可以被 Yii 自动加载了。
+在[高级应用模版](tutorial-advanced-app.md)里,每一逻辑层级会使用他自己的根别名。
+比如,前端层会使用 `@frontend` 而后端层会使用 `@backend`。
+因此,你可以把前端的类放在 `frontend` 命名空间,而后端的类放在 `backend`。
+这样这些类就可以被 Yii 自动加载了。
类映射表(Class Map)
---------
-Yii 类自动加载器支持**类映射表**功能,该功能会建立一个从类的名字到类文件路径的映射。当自动加载器加载一个文件时,他首先检查映射表里有没有该类。如果有,对应的文件路径就直接加载了,省掉了进一步的检查。这让类的自动加载变得超级快。事实上所有的 Yii 核心类都是这样加载的。
+Yii 类自动加载器支持**类映射表**功能,该功能会建立一个从类的名字到类文件路径的映射。
+当自动加载器加载一个文件时,他首先检查映射表里有没有该类。
+如果有,对应的文件路径就直接加载了,省掉了进一步的检查。
+这让类的自动加载变得超级快。事实上所有的 Yii 核心类都是这样加载的。
你可以用 `Yii::$classMap` 方法向映射表中添加类,
@@ -42,34 +52,41 @@ Yii 类自动加载器支持**类映射表**功能,该功能会建立一个从
Yii::$classMap['foo\bar\MyClass'] = 'path/to/MyClass.php';
```
-[别名](concept-aliases.md)可以被用于指定类文件的路径。你应该在[引导启动](runtime-bootstrapping.md)的过程中设置类映射表,这样映射表就可以在你使用具体类之前就准备好。
+[别名](concept-aliases.md)可以被用于指定类文件的路径。
+你应该在[引导启动](runtime-bootstrapping.md)的过程中设置类映射表,这样映射表就可以在你使用具体类之前就准备好。
用其他自动加载器
-----------------------
-因为 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');
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
```
-你也可以只使用 Composer 的自动加载,而不用 Yii 的自动加载。不过这样做的话,类的加载效率会下降,且你必须遵循 Composer 所设定的规则,从而让你的类满足可以被自动加载的要求。
+你也可以只使用 Composer 的自动加载,而不用 Yii 的自动加载。
+不过这样做的话,类的加载效率会下降,且你必须遵循 Composer 所设定的规则,
+从而让你的类满足可以被自动加载的要求。
-<<<<<<< .merge_file_a06860
-> 补充:若你不想要使用 Yii 的自动加载器,你必须创建一个你自己版本的 `Yii.php` 文件,并把它包含进你的[入口脚本](structure-entry-scripts.md)里。
-=======
-> Info: 若你不想要使用 Yii 的自动加载器,你必须创建一个你自己版本的 `Yii.php` 文件,并把它包含进你的[入口脚本](structure-entry-scripts.md)里。
->>>>>>> .merge_file_a06468
+> 补充:若你不想要使用 Yii 的自动加载器,你必须创建一个你自己版本的 `Yii.php` 文件,
+ 并把它包含进你的[入口脚本](structure-entry-scripts.md)里。
自动加载扩展类
-----------------------------
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` 的更多细节。
+文件里正确地定义 `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 的自动加载器仍然可以帮你自动加载扩展内的类。
diff --git a/docs/guide-zh-CN/concept-behaviors.md b/docs/guide-zh-CN/concept-behaviors.md
index 5b4ed00..03ddccb 100644
--- a/docs/guide-zh-CN/concept-behaviors.md
+++ b/docs/guide-zh-CN/concept-behaviors.md
@@ -1,7 +1,12 @@
行为
=========
-行为是 [[yii\base\Behavior]] 或其子类的实例。行为,也称为 [mixins](http://en.wikipedia.org/wiki/Mixin),可以无须改变类继承关系即可增强一个已有的 [[yii\base\Component|组件]] 类功能。当行为附加到组件后,它将“注入”它的方法和属性到组件,然后可以像访问组件内定义的方法和属性一样访问它们。此外,行为通过组件能响应被触发的[事件](basic-events.md),从而自定义或调整组件正常执行的代码。
+行为是 [[yii\base\Behavior]] 或其子类的实例。
+行为,也称为 [mixins](http://en.wikipedia.org/wiki/Mixin),
+可以无须改变类继承关系即可增强一个已有的 [[yii\base\Component|组件]] 类功能。
+当行为附加到组件后,它将“注入”它的方法和属性到组件,然后可以像访问组件内定义的方法和属性一样访问它们。
+此外,行为通过组件能响应被触发的[事件](basic-events.md),
+从而自定义或调整组件正常执行的代码。
定义行为
@@ -37,19 +42,22 @@ class MyBehavior extends Behavior
}
```
-以上代码定义了行为类 `app\components\MyBehavior` 并为要附加行为的组件提供了两个属性 `prop1` 、 `prop2` 和一个方法 `foo()` 。注意属性 `prop2` 是通过 getter `getProp2()` 和 setter `setProp2()` 定义的。能这样用是因为 [[yii\base\Object]] 是 [[yii\base\Behavior]] 的祖先类,此祖先类支持用 getter 和 setter 方法定义[属性](basic-properties.md)
+以上代码定义了行为类 `app\components\MyBehavior` 并为要附加行为的组件提供了两个属性 `prop1` 、 `prop2` 和一个方法 `foo()` 。
+注意属性 `prop2` 是通过 getter `getProp2()` 和 setter `setProp2()` 定义的。
+能这样用是因为 [[yii\base\Object]] 是 [[yii\base\Behavior]] 的祖先类,此祖先类支持用 getter 和 setter 方法定义[属性](basic-properties.md)
+
+Because this class is a behavior, when it is attached to a component, that component will then also have the `prop1` and `prop2` properties and the `foo()` method.
-<<<<<<< .merge_file_a05016
> 提示:在行为内部可以通过 [[yii\base\Behavior::owner]] 属性访问行为已附加的组件。
-=======
-> Tip: 在行为内部可以通过 [[yii\base\Behavior::owner]] 属性访问行为已附加的组件。
->>>>>>> .merge_file_a00824
+> Note: In case [[yii\base\Behavior::__get()]] and/or [[yii\base\Behavior::__set()]] method of behavior is overridden you
+need to override [[yii\base\Behavior::canGetProperty()]] and/or [[yii\base\Behavior::canSetProperty()]] as well.
处理事件
-------------
-如果要让行为响应对应组件的事件触发,就应覆写 [[yii\base\Behavior::events()]] 方法,如:
+如果要让行为响应对应组件的事件触发,
+就应覆写 [[yii\base\Behavior::events()]] 方法,如:
```php
namespace app\components;
@@ -75,26 +83,30 @@ class MyBehavior extends Behavior
}
```
-[[yii\base\Behavior::events()|events()]] 方法返回事件列表和相应的处理器。上例声明了 [[yii\db\ActiveRecord::EVENT_BEFORE_VALIDATE|EVENT_BEFORE_VALIDATE]] 事件和它的处理器 `beforeValidate()` 。当指定一个事件处理器时,要使用以下格式之一:
+[[yii\base\Behavior::events()|events()]] 方法返回事件列表和相应的处理器。
+上例声明了 [[yii\db\ActiveRecord::EVENT_BEFORE_VALIDATE|EVENT_BEFORE_VALIDATE]] 事件和它的处理器 `beforeValidate()` 。
+当指定一个事件处理器时,要使用以下格式之一:
* 指向行为类的方法名的字符串,如上例所示;
* 对象或类名和方法名的数组,如 `[$object, 'methodName']`;
* 匿名方法。
-处理器的格式如下,其中 `$event` 指向事件参数。关于事件的更多细节请参考[事件](basic-events.md):
+处理器的格式如下,其中 `$event` 指向事件参数。
+关于事件的更多细节请参考[事件](basic-events.md):
```php
function ($event) {
}
```
-
-附加行为
+附加行为
----------
可以静态或动态地附加行为到[[yii\base\Component|组件]]。前者在实践中更常见。
-要静态附加行为,覆写行为要附加的组件类的 [[yii\base\Component::behaviors()|behaviors()]] 方法即可。[[yii\base\Component::behaviors()|behaviors()]] 方法应该返回行为[配置](basic-configs.md)列表。每个行为配置可以是行为类名也可以是配置数组。如:
+要静态附加行为,覆写行为要附加的组件类的 [[yii\base\Component::behaviors()|behaviors()]] 方法即可。
+[[yii\base\Component::behaviors()|behaviors()]] 方法应该返回行为[配置](basic-configs.md)列表。
+每个行为配置可以是行为类名也可以是配置数组。如:
```php
namespace app\models;
@@ -131,7 +143,9 @@ class User extends ActiveRecord
}
```
-通过指定行为配置数组相应的键可以给行为关联一个名称。这种行为称为**命名行为**。上例中,有两个命名行为:`myBehavior2` 和 `myBehavior4` 。如果行为没有指定名称就是**匿名行为**。
+通过指定行为配置数组相应的键可以给行为关联一个名称。这种行为称为**命名行为**。
+上例中,有两个命名行为:`myBehavior2` 和 `myBehavior4` 。如果行为没有指定名称就是**匿名行为**。
+
要动态附加行为,在对应组件里调用 [[yii\base\Component::attachBehavior()]] 方法即可,如:
@@ -175,15 +189,16 @@ $component->attachBehaviors([
]
```
-详情请参考[配置](concept-configurations.md#configuration-format)章节。
-
+详情请参考
+[配置](concept-configurations.md#configuration-format)章节。
使用行为
---------------
使用行为,必须像前文描述的一样先把它附加到 [[yii\base\Component|component]] 类或其子类。一旦行为附加到组件,就可以直接使用它。
-行为附加到组件后,可以通过组件访问一个行为的**公共**成员变量或 getter 和 setter 方法定义的[属性](concept-properties.md):
+行为附加到组件后,可以通过组件访问一个行为的**公共**成员变量或 getter 和 setter 方法定义的
+[属性](concept-properties.md):
```php
// "prop1" 是定义在行为类的属性
@@ -198,11 +213,14 @@ $component->prop1 = $value;
$component->foo();
```
-如你所见,尽管 `$component` 未定义 `prop1` 和 `foo()` ,它们用起来也像组件自己定义的一样。
+如你所见,尽管 `$component` 未定义 `prop1` 和 `foo()` ,
+它们用起来也像组件自己定义的一样。
-如果两个行为都定义了一样的属性或方法,并且它们都附加到同一个组件,那么**首先**附加上的行为在属性或方法被访问时有优先权。
+如果两个行为都定义了一样的属性或方法,并且它们都附加到同一个组件,
+那么**首先**附加上的行为在属性或方法被访问时有优先权。
-附加行为到组件时的命名行为,可以使用这个名称来访问行为对象,如下所示:
+附加行为到组件时的命名行为,
+可以使用这个名称来访问行为对象,如下所示:
```php
$behavior = $component->getBehavior('myBehavior');
@@ -234,7 +252,9 @@ $component->detachBehaviors();
使用 `TimestampBehavior`
----------------------------
-最后以 [[yii\behaviors\TimestampBehavior]] 的讲解来结尾,这个行为支持在 [[yii\db\ActiveRecord|Active Record]] 存储时自动更新它的时间戳属性。
+最后以 [[yii\behaviors\TimestampBehavior]] 的讲解来结尾,
+这个行为支持在 [[yii\db\ActiveRecord|Active Record]]
+存储时自动更新它的时间戳属性。
首先,附加这个行为到计划使用该行为的 [[yii\db\ActiveRecord|Active Record]] 类:
@@ -257,6 +277,8 @@ class User extends ActiveRecord
ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],
],
+ // if you're using datetime instead of UNIX timestamp:
+ // 'value' => new Expression('NOW()'),
],
];
}
@@ -265,11 +287,14 @@ class User extends ActiveRecord
以上指定的行为数组:
-* 当记录插入时,行为将当前时间戳赋值给 `created_at` 和 `updated_at` 属性;
-* 当记录更新时,行为将当前时间戳赋值给 `updated_at` 属性。
+* 当记录插入时,
+ 行为将当前的 UNIX 时间戳赋值给 `created_at` 和 `updated_at` 属性;
+* 当记录更新时,行为将当前的 UNIX 时间戳赋值给 `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` 属性自动填充了当前时间戳:
+保存 `User` 对象,
+将会发现它的 `created_at` 和 `updated_at` 属性自动填充了当前时间戳:
```php
$user = new User;
@@ -278,36 +303,58 @@ $user->save();
echo $user->created_at; // 显示当前时间戳
```
-[[yii\behaviors\TimestampBehavior|TimestampBehavior]] 行为还提供了一个有用的方法 [[yii\behaviors\TimestampBehavior::touch()|touch()]],这个方法能将当前时间戳赋值给指定属性并保存到数据库:
+[[yii\behaviors\TimestampBehavior|TimestampBehavior]] 行为还提供了一个有用的方法
+[[yii\behaviors\TimestampBehavior::touch()|touch()]],
+这个方法能将当前时间戳赋值给指定属性并保存到数据库:
```php
$user->touch('login_time');
```
+Other behaviors
+---------------
+
+There are several built-in and external behaviors available:
-与 PHP traits 的比较
--------------------
+- [[yii\behaviors\BlameableBehavior]] - automatically fills the specified attributes with the current user ID.
+- [[yii\behaviors\SluggableBehavior]] - automatically fills the specified attribute with a value that can be used
+ as a slug in a URL.
+- [[yii\behaviors\AttributeBehavior]] - automatically assigns a specified value to one or multiple attributes of
+ an ActiveRecord object when certain events happen.
+- [yii2tech\ar\softdelete\SoftDeleteBehavior](https://github.com/yii2tech/ar-softdelete) - provides methods to soft-delete
+ and soft-restore ActiveRecord i.e. set flag or status which marks record as deleted.
+- [yii2tech\ar\position\PositionBehavior](https://github.com/yii2tech/ar-position) - allows managing records order in an
+ integer field by providing reordering methods.
-尽管行为在 "注入" 属性和方法到主类方面类似于 [traits](http://www.php.net/traits) ,它们在很多方面却不相同。如上所述,它们各有利弊。它们更像是互补的而不是相互替代。
+Comparing Behaviors with Traits
+----------------------
+While behaviors are similar to [traits](http://www.php.net/traits) in that they both "inject" their
+properties and methods to the primary class, they differ in many aspects. As explained below, they
+both have pros and cons. They are more like complements to each other rather than alternatives.
-### 行为的优势
-行为类像普通类支持继承。另一方面,traits 可以视为 PHP 语言支持的复制粘贴功能,它不支持继承。
+### Reasons to Use Behaviors
-行为无须修改组件类就可动态附加到组件或移除。要使用 traits,必须修改使用它的类。
+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 不能。
+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.
-行为以响应事件来自定义组件的代码执行。
+Behaviors are configurable while traits are not.
-当不同行为附加到同一组件产生命名冲突时,这个冲突通过先附加行为的优先权自动解决。而由不同 traits 引发的命名冲突需要通过手工重命名冲突属性或方法来解决。
+Behaviors can customize the code execution of a component by responding to its events.
+When there can be name conflicts among different behaviors attached to the same component, the conflicts are
+automatically resolved by prioritizing the behavior attached to the component first.
+Name conflicts caused by different traits requires manual resolution by renaming the affected
+properties or methods.
-### traits 的优势
-traits 比起行为更高效,因为行为是对象,消耗时间和内存。
+### Reasons to Use Traits
-IDE 对 traits 更友好,因为它们是语言结构。
+Traits are much more efficient than behaviors as behaviors are objects that take both time and memory.
+IDEs are more friendly to traits as they are a native language construct.
diff --git a/docs/guide-zh-CN/concept-components.md b/docs/guide-zh-CN/concept-components.md
index b9feaa3..4044c9e 100644
--- a/docs/guide-zh-CN/concept-components.md
+++ b/docs/guide-zh-CN/concept-components.md
@@ -1,13 +1,16 @@
组件(Component)
==========
-组件是 Yii 应用的主要基石。是 [[yii\base\Component]] 类或其子类的实例。三个用以区分它和其它类的主要功能有:
+组件是 Yii 应用的主要基石。是 [[yii\base\Component]] 类或其子类的实例。
+三个用以区分它和其它类的主要功能有:
* [属性(Property)](concept-properties.md)
* [事件(Event)](concept-events.md)
* [行为(Behavior)](concept-behaviors.md)
-或单独使用,或彼此配合,这些功能的应用让 Yii 的类变得更加灵活和易用。以小部件 [[yii\jui\DatePicker|日期选择器]] 来举例,这是个方便你在 [视图](structure-view.md) 中生成一个交互式日期选择器的 UI 组件:
+或单独使用,或彼此配合,这些功能的应用让 Yii 的类变得更加灵活和易用。
+以小部件 [[yii\jui\DatePicker|日期选择器]] 来举例,
+这是个方便你在 [视图](structure-view.md) 中生成一个交互式日期选择器的 UI 组件:
```php
use yii\jui\DatePicker;
@@ -23,11 +26,17 @@ echo DatePicker::widget([
这个小部件继承自 [[yii\base\Component]],它的各项属性改写起来会很容易。
-正是因为组件功能的强大,他们比常规的对象(Object)稍微重量级一点,因为他们要使用额外的内存和 CPU 时间来处理 [事件](concept-events.md) 和 [行为](concept-behaviors.md) 。如果你不需要这两项功能,可以继承 [[yii\base\Object]] 而不是 [[yii\base\Component]]。这样组件可以像普通 PHP 对象一样高效,同时还支持[属性(Property)](concept-properties.md)功能。
+正是因为组件功能的强大,他们比常规的对象(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]] 时,推荐你使用如下的编码风格:
+当继承 [[yii\base\Component]] 或 [[yii\base\Object]] 时,
+推荐你使用如下的编码风格:
-- 若你需要重写构造方法(Constructor),传入 `$config` 作为构造器方法**最后一个**参数,然后把它传递给父类的构造方法。
+- 若你需要重写构造方法(Constructor),传入 `$config` 作为构造器方法**最后一个**参数,
+ 然后把它传递给父类的构造方法。
- 永远在你重写的构造方法**结尾处**调用一下父类的构造方法。
- 如果你重写了 [[yii\base\Object::init()]] 方法,请确保你在 `init` 方法的**开头处**调用了父类的 `init` 方法。
@@ -71,11 +80,8 @@ $component = \Yii::createObject([
], [1, 2]);
```
-<<<<<<< .merge_file_a01348
-> 补充:尽管调用 [[Yii::createObject()]] 的方法看起来更加复杂,但这主要因为它更加灵活强大,它是基于[依赖注入容器](concept-di-container.md)实现的。
-=======
-> Info: 尽管调用 [[Yii::createObject()]] 的方法看起来更加复杂,但这主要因为它更加灵活强大,它是基于[依赖注入容器](concept-di-container.md)实现的。
->>>>>>> .merge_file_a06700
+> 补充:尽管调用 [[Yii::createObject()]] 的方法看起来更加复杂,
+> 但这主要因为它更加灵活强大,它是基于[依赖注入容器](concept-di-container.md)实现的。
[[yii\base\Object]] 类执行时的生命周期如下:
@@ -85,4 +91,5 @@ $component = \Yii::createObject([
3. 在 [[yii\base\Object::init()|init()]] 方法内进行初始化后的收尾工作。你可以通过重写此方法,进行一些良品检验,属性的初始化之类的工作。
4. 对象方法调用。
-前三步都是在对象的构造方法内发生的。这意味着一旦你获得了一个对象实例,那么它就已经初始化就绪可供使用。
+前三步都是在对象的构造方法内发生的。
+这意味着一旦你获得了一个对象实例,那么它就已经初始化就绪可供使用。
diff --git a/docs/guide-zh-CN/concept-properties.md b/docs/guide-zh-CN/concept-properties.md
index eab95c2..7da3ce5 100644
--- a/docs/guide-zh-CN/concept-properties.md
+++ b/docs/guide-zh-CN/concept-properties.md
@@ -1,23 +1,31 @@
属性(Property)
==========
-在 PHP 中,类的成员变量也被称为**属性(properties)**。它们是类定义的一部分,用来表现一个实例的状态(也就是区分类的不同实例)。在具体实践中,常常会想用一个稍微特殊些的方法实现属性的读写。例如,如果有需求每次都要对 `label` 属性执行 trim 操作,就可以用以下代码实现:
+在 PHP 中,类的成员变量也被称为**属性(properties)**。
+它们是类定义的一部分,用来表现一个实例的状态(也就是区分类的不同实例)。
+在具体实践中,常常会想用一个稍微特殊些的方法实现属性的读写。
+例如,如果有需求每次都要对 `label` 属性执行 trim 操作,
+就可以用以下代码实现:
```php
$object->label = trim($label);
```
-上述代码的缺点是只要修改 `label` 属性就必须再次调用 `trim()` 函数。若将来需要用其它方式处理 `label` 属性,比如首字母大写,就不得不修改所有给 `label` 属性赋值的代码。这种代码的重复会导致 bug,这种实践显然需要尽可能避免。
+上述代码的缺点是只要修改 `label` 属性就必须再次调用 `trim()` 函数。
+若将来需要用其它方式处理 `label` 属性,比如首字母大写,
+就不得不修改所有给 `label` 属性赋值的代码。
+这种代码的重复会导致 bug,这种实践显然需要尽可能避免。
-为解决该问题,Yii 引入了一个名为 [[yii\base\Object]] 的基类,它支持基于类内的 **getter** 和 **setter**(读取器和设定器)方法来定义属性。如果某类需要支持这个特性,只需要继承 [[yii\base\Object]] 或其子类即可。
+为解决该问题,Yii 引入了一个名为 [[yii\base\Object]] 的基类,
+它支持基于类内的 **getter** 和 **setter**(读取器和设定器)方法来定义属性。
+如果某类需要支持这个特性,只需要继承 [[yii\base\Object]] 或其子类即可。
-<<<<<<< .merge_file_a06884
-> 补充:几乎每个 Yii 框架的核心类都继承自 [[yii\base\Object]] 或其子类。这意味着只要在核心类中见到 getter 或 setter 方法,就可以像调用属性一样调用它。
-=======
-> Info: 几乎每个 Yii 框架的核心类都继承自 [[yii\base\Object]] 或其子类。这意味着只要在核心类中见到 getter 或 setter 方法,就可以像调用属性一样调用它。
->>>>>>> .merge_file_a04208
+> 补充:几乎每个 Yii 框架的核心类都继承自 [[yii\base\Object]] 或其子类。
+ 这意味着只要在核心类中见到 getter 或 setter 方法,就可以像调用属性一样调用它。
-getter 方法是名称以 `get` 开头的方法,而 setter 方法名以 `set` 开头。方法名中 `get` 或 `set` 后面的部分就定义了该属性的名字。如下面代码所示,getter 方法 `getLabel()` 和 setter 方法 `setLabel()` 操作的是 `label` 属性,:
+getter 方法是名称以 `get` 开头的方法,而 setter 方法名以 `set` 开头。
+方法名中 `get` 或 `set` 后面的部分就定义了该属性的名字。
+如下面代码所示,getter 方法 `getLabel()` 和 setter 方法 `setLabel()` 操作的是 `label` 属性,:
```php
namespace app\components;
@@ -40,9 +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();
@@ -52,13 +63,24 @@ $label = $object->label;
$object->label = 'abc';
```
-只定义了 getter 没有 setter 的属性是**只读属性**。尝试赋值给这样的属性将导致 [[yii\base\InvalidCallException|InvalidCallException]] (无效调用)异常。类似的,只有 setter 方法而没有 getter 方法定义的属性是**只写属性**,尝试读取这种属性也会触发异常。使用只写属性的情况几乎没有。
+只定义了 getter 没有 setter 的属性是**只读属性**。
+尝试赋值给这样的属性将导致 [[yii\base\InvalidCallException|InvalidCallException]] (无效调用)异常。
+类似的,只有 setter 方法而没有 getter 方法定义的属性是**只写属性**,尝试读取这种属性也会触发异常。
+使用只写属性的情况几乎没有。
通过 getter 和 setter 定义的属性也有一些特殊规则和限制:
-* 这类属性的名字是**不区分大小写**的。如,`$object->label` 和 `$object->Label` 是同一个属性。因为 PHP 方法名是不区分大小写的。
-* 如果此类属性名和类成员变量相同,以后者为准。例如,假设以上 `Foo` 类有个 `label` 成员变量,然后给 `$object->label = 'abc'` 赋值,将赋给成员变量而不是 setter `setLabel()` 方法。
+* 这类属性的名字是**不区分大小写**的。如,`$object->label` 和 `$object->Label` 是同一个属性。
+ 因为 PHP 方法名是不区分大小写的。
+* 如果此类属性名和类成员变量相同,以后者为准。
+ 例如,假设以上 `Foo` 类有个 `label` 成员变量,
+ 然后给 `$object->label = 'abc'` 赋值,将赋给成员变量而不是 setter `setLabel()` 方法。
* 这类属性不支持可见性(访问限制)。定义属性的 getter 和 setter 方法是 public、protected 还是 private 对属性的可见性没有任何影响。
* 这类属性的 getter 和 setter 方法只能定义为**非静态**的,若定义为静态方法(static)则不会以相同方式处理。
+* A normal call to `property_exists()` does not work to determine magic properties. You should call [[yii\base\Object::canGetProperty()|canGetProperty()]]
+ or [[yii\base\Object::canSetProperty()|canSetProperty()]] respectively.
-回到开头提到的问题,与其处处要调用 `trim()` 函数,现在我们只需在 setter `setLabel()` 方法内调用一次。如果 label 首字母变成大写的新要求来了,我们只需要修改`setLabel()` 方法,而无须接触任何其它代码。
\ No newline at end of file
+回到开头提到的问题,与其处处要调用 `trim()` 函数,
+现在我们只需在 setter `setLabel()` 方法内调用一次。
+如果 label 首字母变成大写的新要求来了,我们只需要修改`setLabel()` 方法,
+而无须接触任何其它代码。
diff --git a/docs/guide-zh-CN/concept-service-locator.md b/docs/guide-zh-CN/concept-service-locator.md
index c9f278d..242dd5c 100644
--- a/docs/guide-zh-CN/concept-service-locator.md
+++ b/docs/guide-zh-CN/concept-service-locator.md
@@ -1,15 +1,21 @@
服务定位器
===============
-服务定位器是一个了解如何提供各种应用所需的服务(或组件)的对象。在服务定位器中,每个组件都只有一个单独的实例,并通过ID 唯一地标识。用这个 ID 就能从服务定位器中得到这个组件。
+服务定位器是一个了解如何提供各种应用所需的服务(或组件)的对象。
+在服务定位器中,每个组件都只有一个单独的实例,并通过ID 唯一地标识。
+用这个 ID 就能从服务定位器中得到这个组件。
在 Yii 中,服务定位器是 [[yii\di\ServiceLocator]] 或其子类的一个实例。
-最常用的服务定位器是**application(应用)**对象,可以通过 `\Yii::$app` 访问。它所提供的服务被称为**application components(应用组件)**,比如:`request`、`response`、`urlManager` 组件。可以通过服务定位器所提供的功能,非常容易地配置这些组件,或甚至是用你自己的实现替换掉他们。
+最常用的服务定位器是**application(应用)**对象,可以通过 `\Yii::$app` 访问。
+它所提供的服务被称为**application components(应用组件)**,比如:`request`、`response`、`urlManager` 组件。
+可以通过服务定位器所提供的功能,非常容易地配置这些组件,
+或甚至是用你自己的实现替换掉他们。
除了 application 对象,每个模块对象本身也是一个服务定位器。
-要使用服务定位器,第一步是要注册相关组件。组件可以通过 [[yii\di\ServiceLocator::set()]] 方法进行注册。以下的方法展示了注册组件的不同方法:
+要使用服务定位器,第一步是要注册相关组件。
+组件可以通过 [[yii\di\ServiceLocator::set()]] 方法进行注册。以下的方法展示了注册组件的不同方法:
```php
use yii\di\ServiceLocator;
@@ -45,11 +51,21 @@ $cache = $locator->get('cache');
$cache = $locator->cache;
```
-如上所示, [[yii\di\ServiceLocator]] 允许通过组件 ID 像访问一个属性值那样访问一个组件。当你第一次访问某组件时,[[yii\di\ServiceLocator]] 会通过该组件的注册信息创建一个该组件的实例,并返回它。之后,如果再次访问,则服务定位器会返回同一个实例。
+如上所示, [[yii\di\ServiceLocator]] 允许通过组件 ID 像访问一个属性值那样访问一个组件。
+当你第一次访问某组件时,
+[[yii\di\ServiceLocator]] 会通过该组件的注册信息创建一个该组件的实例,并返回它。
+之后,如果再次访问,则服务定位器会返回同一个实例。
-你可以通过 [[yii\di\ServiceLocator::has()]] 检查某组件 ID 是否被注册。若你用一个无效的 ID 调用 [[yii\di\ServiceLocator::get()]],则会抛出一个异常。
+你可以通过 [[yii\di\ServiceLocator::has()]] 检查某组件 ID 是否被注册。
+若你用一个无效的 ID 调用 [[yii\di\ServiceLocator::get()]],则会抛出一个异常。
+
+
+因为服务定位器,经常会在创建时附带[配置信息](concept-configurations.md),
+因此我们提供了一个可写的属性,
+名为 [[yii\di\ServiceLocator::setComponents()|components]],
+这样就可以配置该属性,或一次性注册多个组件。
+下面的代码展示了如何用一个配置数组,配置一个应用并注册"db","cache" 和 "search" 三个组件:
-因为服务定位器,经常会在创建时附带[配置信息](concept-configurations.md),因此我们提供了一个可写的属性,名为 [[yii\di\ServiceLocator::setComponents()|components]],这样就可以配置该属性,或一次性注册多个组件。下面的代码展示了如何用一个配置数组,配置一个应用并注册"db","cache" 和 "search" 三个组件:
```php
return [
// ...
@@ -62,8 +78,40 @@ return [
],
'cache' => 'yii\caching\ApcCache',
'search' => function () {
- return new app\components\SolrService;
+ $solr = new app\components\SolrService('127.0.0.1');
+ // ... other initializations ...
+ return $solr;
},
],
];
```
+
+In the above, there is an alternative way to configure the "search" component. Instead of directly writing a PHP
+callback which builds a `SolrService` instance, you can use a static class method to return such a callback, like
+shown as below:
+
+```php
+class SolrServiceBuilder
+{
+ public static function build($ip)
+ {
+ return function () use ($ip) {
+ $solr = new app\components\SolrService($ip);
+ // ... other initializations ...
+ return $solr;
+ };
+ }
+}
+
+return [
+ // ...
+ 'components' => [
+ // ...
+ 'search' => SolrServiceBuilder::build('127.0.0.1'),
+ ],
+];
+```
+
+This alternative approach is most preferable when you are releasing a Yii component which encapsulates some non-Yii
+3rd-party library. You use the static method like shown above to represent the complex logic of building the
+3rd-party object, and the user of your component only needs to call the static method to configure the component.
diff --git a/docs/guide-zh-CN/helper-array.md b/docs/guide-zh-CN/helper-array.md
index a2a69ef..bef0999 100755
--- a/docs/guide-zh-CN/helper-array.md
+++ b/docs/guide-zh-CN/helper-array.md
@@ -113,32 +113,96 @@ $result = ArrayHelper::getColumn($array, function ($element) {
键名(译者注:第二个参数)可以是子数组的键名、对象的属性名,
也可以是一个返回给定元素数组键值的匿名函数。
-如果一个键值(译者注:第二个参数对应的值)是 null,相应的数组元素将被丢弃并且不会放入到结果中,例如,
+The `$groups` attribute is an array of keys, that will be used to group the input array into one or more sub-arrays
+based on keys specified.
+
+If the `$key` attribute or its value for the particular element is null and `$groups` is not defined, the array
+element will be discarded. Otherwise, if `$groups` is specified, array element will be added to the result array
+without any key.
+
+For example:
```php
$array = [
- ['id' => '123', 'data' => 'abc'],
- ['id' => '345', 'data' => 'def'],
+ ['id' => '123', 'data' => 'abc', 'device' => 'laptop'],
+ ['id' => '345', 'data' => 'def', 'device' => 'tablet'],
+ ['id' => '345', 'data' => 'hgi', 'device' => 'smartphone'],
];
$result = ArrayHelper::index($array, 'id');
-// the result is:
-// [
-// '123' => ['id' => '123', 'data' => 'abc'],
-// '345' => ['id' => '345', 'data' => 'def'],
-// ]
+```
+
+The result will be an associative array, where the key is the value of `id` attribute
+
+```php
+[
+ '123' => ['id' => '123', 'data' => 'abc', 'device' => 'laptop'],
+ '345' => ['id' => '345', 'data' => 'hgi', 'device' => 'smartphone']
+ // The second element of an original array is overwritten by the last element because of the same id
+]
+```
+
+Anonymous function, passed as a `$key`, gives the same result.
-// using anonymous function
+```php
$result = ArrayHelper::index($array, function ($element) {
return $element['id'];
});
```
+Passing `id` as a third argument will group `$array` by `id`:
+
+```php
+$result = ArrayHelper::index($array, null, 'id');
+```
+
+The result will be a multidimensional array grouped by `id` on the first level and not indexed on the second level:
+
+```php
+[
+ '123' => [
+ ['id' => '123', 'data' => 'abc', 'device' => 'laptop']
+ ],
+ '345' => [ // all elements with this index are present in the result array
+ ['id' => '345', 'data' => 'def', 'device' => 'tablet'],
+ ['id' => '345', 'data' => 'hgi', 'device' => 'smartphone'],
+ ]
+]
+```
+
+An anonymous function can be used in the grouping array as well:
+
+```php
+$result = ArrayHelper::index($array, 'data', [function ($element) {
+ return $element['id'];
+}, 'device']);
+```
+
+The result will be a multidimensional array grouped by `id` on the first level, by `device` on the second level and
+indexed by `data` on the third level:
+
+```php
+[
+ '123' => [
+ 'laptop' => [
+ 'abc' => ['id' => '123', 'data' => 'abc', 'device' => 'laptop']
+ ]
+ ],
+ '345' => [
+ 'tablet' => [
+ 'def' => ['id' => '345', 'data' => 'def', 'device' => 'tablet']
+ ],
+ 'smartphone' => [
+ 'hgi' => ['id' => '345', 'data' => 'hgi', 'device' => 'smartphone']
+ ]
+ ]
+]
+```
## 建立哈希表
为了从一个多维数组或者一个对象数组中建立一个映射表(键值对),你可以使用
`map`方法.`$from` 和 `$to` 参数分别指定了欲构建的映射表的键名和属性名。
-根据需要,你可以按照一个分组字段 `$group` 将映射表进行分组,例如。
+根据需要,你可以按照一个分组字段 `$group` 将映射表进行分组,例如,
```php
$array = [
@@ -201,9 +265,9 @@ ArrayHelper::multisort($data, function($item) {
});
```
-第三个参数表示增降顺序。单键排序时,它可以是 `SORT_ASC` 或者 `SORT_DESC` 之一。
-如果是按多个键名排序,你可以用一个数组为各个键指定不同的顺序。
-
+第三个参数表示增降顺序。单键排序时,它可以是 `SORT_ASC` 或者
+`SORT_DESC` 之一。如果是按多个键名排序,你可以用一个数组为
+各个键指定不同的顺序。
最后一个参数(译者注:第四个参数)是PHP的排序标识(sort flag),可使用的值和调用PHP
[sort()](http://php.net/manual/zh/function.sort.php) 函数时传递的值一样。
@@ -301,3 +365,22 @@ $data = ArrayHelper::toArray($posts, [
也可以在一个特定的类中实现[[yii\base\Arrayable|Arrayable]]接口,
从而为其对象提供默认的转换成数组的方法。
+
+## Testing against Arrays
+
+Often you need to check if an element is in an array or a set of elements is a subset of another.
+While PHP offers `in_array()`, this does not support subsets or `\Traversable` objects.
+
+To aid these kinds of tests, [[yii\base\ArrayHelper]] provides [[yii\base\ArrayHelper::isIn()|isIn()]]
+and [[yii\base\ArrayHelper::isSubset()|isSubset()]] with the same signature as [[in_array()]].
+
+```php
+// true
+ArrayHelper::isIn('a', ['a']);
+// true
+ArrayHelper::isIn('a', new(ArrayObject['a']));
+
+// true
+ArrayHelper::isSubset(new(ArrayObject['a', 'c']), new(ArrayObject['a', 'b', 'c'])
+
+```
diff --git a/docs/guide-zh-CN/helper-html.md b/docs/guide-zh-CN/helper-html.md
index 45dd66f..66e50b9 100644
--- a/docs/guide-zh-CN/helper-html.md
+++ b/docs/guide-zh-CN/helper-html.md
@@ -78,6 +78,56 @@ echo Html::tag('div', 'Pwede na', $options);
基于同样的目的,针对 `style` 属性:
```php
+$options = ['class' => ['btn', 'btn-default']];
+
+echo Html::tag('div', 'Save', $options);
+// renders '
Save
'
+```
+
+While adding or removing classes you may use the array format as well:
+
+```php
+$options = ['class' => 'btn'];
+
+if ($type === 'success') {
+ Html::addCssClass($options, ['btn-success', 'btn-lg']);
+}
+
+echo Html::tag('div', 'Save', $options);
+// renders '
Save
'
+```
+
+`Html::addCssClass()` prevents duplicating classes, so you don't need to worry that the same class may appear twice:
+
+```php
+$options = ['class' => 'btn btn-default'];
+
+Html::addCssClass($options, 'btn-default'); // class 'btn-default' is already present
+
+echo Html::tag('div', 'Save', $options);
+// renders '
Save
'
+```
+
+If the CSS class option is specified via the array format, you may use a named key to mark the logical purpose of the class.
+In this case, a class with the same key in the array format will be ignored in `Html::addCssClass()`:
+
+```php
+$options = [
+ 'class' => [
+ 'btn',
+ 'theme' => 'btn-default',
+ ]
+];
+
+Html::addCssClass($options, ['theme' => 'btn-success']); // 'theme' key is already taken
+
+echo Html::tag('div', 'Save', $options);
+// renders '
Save
'
+```
+
+CSS styles can be setup in similar way using `style` attribute:
+
+```php
$options = ['style' => ['width' => '100px', 'height' => '100px']];
// gives style="width: 100px; height: 200px; position: absolute;"
@@ -149,15 +199,15 @@ Yii 也提供了一系列的方法来辅助处理表单标签。
= Html::resetButton('Reset', ['class' => 'reset']) ?>
```
-上述三个方法的第一个参数为按钮的标题,第二个是标签属性。标题默认没有进行转码,如果标题是由终端用输入的,那么请自行用 [[yii\helpers\Html::encode()|Html::encode()]] 方法进行转码。
-
+上述三个方法的第一个参数为按钮的标题,第二个是标签属性。标题默认没有进行转码,如果标题是由终端用输入的,
+那么请自行用 [[yii\helpers\Html::encode()|Html::encode()]] 方法进行转码。
### 输入栏
-input 相关的方法有两组:以 `active` 开头的被称为 active inputs,另一组则不以其开头。
-active inputs 依据指定的模型和属性获取数据,而普通 input 则是直接指定数据。
-
+input 相关的方法有两组:以 `active` 开头的被称为 active inputs,
+另一组则不以其开头。active inputs 依据指定的模型和属性获取数据,
+而普通 input 则是直接指定数据。
一般用法如下:
diff --git a/docs/guide-zh-CN/helper-overview.md b/docs/guide-zh-CN/helper-overview.md
index 5098128..331594b 100644
--- a/docs/guide-zh-CN/helper-overview.md
+++ b/docs/guide-zh-CN/helper-overview.md
@@ -1,11 +1,7 @@
助手类
=======
-<<<<<<< .merge_file_a01044
> 注意:这部分正在开发中。
-=======
-> Note: 这部分正在开发中。
->>>>>>> .merge_file_a06768
Yii 提供许多类来简化常见编码,如对字条串或数组的操作,
HTML 代码生成,等等。这些助手类被编写在命名空间 `yii\helpers` 下,并且
@@ -19,12 +15,8 @@ use yii\helpers\Html;
echo Html::encode('Test > test');
```
-<<<<<<< .merge_file_a01044
> 注意:为了支持 [自定义助手类](#customizing-helper-classes),Yii 将每一个助手类
-=======
-> Note: 为了支持 [自定义助手类](#customizing-helper-classes),Yii 将每一个助手类
->>>>>>> .merge_file_a06768
- 分隔成两个类:一个基类 (例如 `BaseArrayHelper`) 和一个具体的类 (例如 `ArrayHelper`).
+ 分隔成两个类:一个基类 (例如 `BaseArrayHelper`) 和一个具体的类 (例如 `ArrayHelper`)。
当使用助手类时,应该仅使用具体的类版本而不使用基类。
diff --git a/docs/guide-zh-CN/input-file-upload.md b/docs/guide-zh-CN/input-file-upload.md
index eabbed5..5d5895a 100755
--- a/docs/guide-zh-CN/input-file-upload.md
+++ b/docs/guide-zh-CN/input-file-upload.md
@@ -77,6 +77,8 @@ use yii\widgets\ActiveForm;
需要注意的是要记得在表单选项里加入 `enctype` 属性以确保文件能被正常上传。
`fileInput()` 方法会渲染一个 `` 标签,让用户可以选择一个文件上传。
+> Tip: since version 2.0.8, [[yii\web\widgets\ActiveField::fileInput|fileInput]] adds `enctype` option to the form
+ automatically when file input field is used.
## 视图和模型的连接
@@ -119,8 +121,10 @@ class SiteController extends Controller
将前面所述的代码做一些调整,也可以一次性上传多个文件。
首先你得调整模型类,在 `file` 验证规则里增加一个 `maxFiles` 选项,用以限制一次上传文件的最大数量。
-`upload()`方法也得修改,
-以便一个一个地保存上传的文件。
+`upload()`方法也得修改,以便一个一个地保存上传的文件。Setting `maxFiles` to `0` means there is no limit on the number of files
+that can be uploaded simultaneously. The maximum number of files allowed to be uploaded simultaneously is also limited
+with PHP directive [`max_file_uploads`](http://php.net/manual/en/ini.core.php#ini.max-file-uploads),
+which defaults to 20. The `upload()` method should also be updated to save the uploaded files one by one.
```php
namespace app\models;
diff --git a/docs/guide-zh-CN/input-forms.md b/docs/guide-zh-CN/input-forms.md
index 64ce58b..98f9e1b 100644
--- a/docs/guide-zh-CN/input-forms.md
+++ b/docs/guide-zh-CN/input-forms.md
@@ -1,14 +1,16 @@
创建表单
========
-在 Yii 中使用表单的主要方式是通过 [[yii\widgets\ActiveForm]]。如果是基于模型的表单应首选这种方式。此外,在 [[yii\helpers\Html]]
-中也有一些实用的方法用于添加按钮和帮助文本。
+在 Yii 中使用表单的主要方式是通过 [[yii\widgets\ActiveForm]]。如果是基于
+模型的表单应首选这种方式。此外,在 [[yii\helpers\Html]]中也有一些实用的
+方法用于添加按钮和帮助文本。
在客户端上显示的表单,大多数情况下有一个相应的[模型](structure-models.md),用来验证其输入的服务器数据
(可在 [输入验证](input-validation.md) 一节获取关于验证的细节)。
-当创建基于模型的表单时,第一步是定义模型本身。该模式可以是一个基于[活动记录](db-active-record.md)的类,表示数据库中的数据,
-也可以是一个基于通用模型的类(继承自 [[yii\base\Model]] ),来获取任意的输入数据,如登录表单。
-在下面的例子中,我们展示了一个用来做登录表单的通用模型:
+当创建基于模型的表单时,第一步是定义模型本身。该模式可以是一个基于[活动记录](db-active-record.md)的类,
+表示数据库中的数据,也可以是一个基于通用模型的类(继承自 [[yii\base\Model]] ),
+来获取任意的输入数据,如登录表单。在下面的例子中,我们展示了一个用来做
+登录表单的通用模型:
```php
` 标签中。
与任何小部件一样,你可以指定一些选项,通过传递数组到 `begin` 方法中来配置该小部件。在这种情况下,
-一个额外的 CSS 类和 ID 会在 `