diff --git a/.gitignore b/.gitignore
index 18e2a7877f..e887db84c1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,7 +35,7 @@ phpunit.phar
# local phpunit config
/phpunit.xml
-# ignore sub directory for dev installed apps and extensions
+# ignore dev installed apps and extensions
/apps
/extensions
diff --git a/.travis.yml b/.travis.yml
index 755ad1dfc4..fe7aa431d8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,6 +8,12 @@ dist: trusty
# faster builds on new travis setup not using sudo
sudo: false
+# build only on master branches
+branches:
+ only:
+ - master
+ - 2.1
+
#
# Test Matrix
@@ -58,21 +64,6 @@ matrix:
services:
- mysql
- postgresql
- - php: 5.4
- addons:
- apt:
- packages:
- - php5.4-gd
- - php: 5.5
- addons:
- apt:
- packages:
- - php5.5-gd
- - php: 5.6
- addons:
- apt:
- packages:
- - php5.6-gd
# have a separate branch for javascript tests
- language: node_js
node_js: 6
@@ -87,7 +78,7 @@ matrix:
- phpenv config-rm xdebug.ini || echo "xdebug is not installed"
- travis_retry composer self-update && composer --version
- travis_retry composer global require "fxp/composer-asset-plugin:^1.2.0" --no-plugins
- - travis_retry composer update --prefer-dist --no-interaction
+ - travis_retry composer install --prefer-dist --no-interaction
before_script:
- node --version
- npm --version
@@ -102,6 +93,8 @@ matrix:
services:
- memcached
+ - mysql
+ - postgresql
# cache vendor dirs
cache:
@@ -125,13 +118,15 @@ install:
- travis_retry composer self-update && composer --version
- travis_retry composer global require "fxp/composer-asset-plugin:^1.2.0" --no-plugins
- export PATH="$HOME/.composer/vendor/bin:$PATH"
-# core framework:
- - travis_retry composer update --prefer-dist --no-interaction
+ # core framework:
+ - travis_retry composer install --prefer-dist --no-interaction
- tests/data/travis/apc-setup.sh
- tests/data/travis/memcache-setup.sh
-# - tests/data/travis/cubrid-setup.sh
+ - tests/data/travis/imagick-setup.sh
before_script:
+ # Disable the HHVM JIT for faster Unit Testing
+ - if [[ $TRAVIS_PHP_VERSION = hhv* ]]; then echo 'hhvm.jit = 0' >> /etc/hhvm/php.ini; fi
# show some versions and env information
- php -r "echo INTL_ICU_VERSION . \"\n\";"
- php -r "echo INTL_ICU_DATA_VERSION . \"\n\";"
@@ -152,6 +147,8 @@ before_script:
script:
+ # ensure no files contain UTF-8 byte order mark
+ - if ! grep -rlI $'\xEF\xBB\xBF' framework/ ; then echo "no utf8 BOM found"; else echo "found utf8 BOM in some files. See above."; exit 1; fi
# validate composer.json
- composer validate --no-check-lock
- cd framework && composer validate --no-check-lock && cd ..
diff --git a/build/controllers/ReleaseController.php b/build/controllers/ReleaseController.php
index c05a897071..cf2b8eba8f 100644
--- a/build/controllers/ReleaseController.php
+++ b/build/controllers/ReleaseController.php
@@ -465,8 +465,10 @@ class ReleaseController extends Controller
$this->stdout(" **** Commit, Tag and Push it! ****\n", Console::FG_YELLOW, Console::BOLD);
$this->stdout("\n\nHint: if you decide 'no' for any of the following, the command will not be executed. You may manually run them later if needed. E.g. try the release locally without pushing it.\n\n");
- $this->runGit("git commit -a -m \"release version $version\"", $frameworkPath);
- $this->runGit("git tag -a $version -m \"version $version\"", $frameworkPath);
+ $this->stdout("Make sure to have your git set up for GPG signing. The following tag and commit should be signed.\n\n");
+
+ $this->runGit("git commit -S -a -m \"release version $version\"", $frameworkPath);
+ $this->runGit("git tag -s $version -m \"version $version\"", $frameworkPath);
$this->runGit("git push", $frameworkPath);
$this->runGit("git push --tags", $frameworkPath);
@@ -578,8 +580,10 @@ class ReleaseController extends Controller
$this->stdout(" **** Commit, Tag and Push it! ****\n", Console::FG_YELLOW, Console::BOLD);
$this->stdout("\n\nHint: if you decide 'no' for any of the following, the command will not be executed. You may manually run them later if needed. E.g. try the release locally without pushing it.\n\n");
- $this->runGit("git commit -a -m \"release version $version\"", $path);
- $this->runGit("git tag -a $version -m \"version $version\"", $path);
+ $this->stdout("Make sure to have your git set up for GPG signing. The following tag and commit should be signed.\n\n");
+
+ $this->runGit("git commit -S -a -m \"release version $version\"", $path);
+ $this->runGit("git tag -s $version -m \"version $version\"", $path);
$this->runGit("git push", $path);
$this->runGit("git push --tags", $path);
@@ -694,8 +698,10 @@ class ReleaseController extends Controller
$this->stdout(" **** Commit, Tag and Push it! ****\n", Console::FG_YELLOW, Console::BOLD);
$this->stdout("\n\nHint: if you decide 'no' for any of the following, the command will not be executed. You may manually run them later if needed. E.g. try the release locally without pushing it.\n\n");
- $this->runGit("git commit -a -m \"release version $version\"", $path);
- $this->runGit("git tag -a $version -m \"version $version\"", $path);
+ $this->stdout("Make sure to have your git set up for GPG signing. The following tag and commit should be signed.\n\n");
+
+ $this->runGit("git commit -S -a -m \"release version $version\"", $path);
+ $this->runGit("git tag -s $version -m \"version $version\"", $path);
$this->runGit("git push", $path);
$this->runGit("git push --tags", $path);
diff --git a/composer.json b/composer.json
index 49d58bf986..d167ec228d 100644
--- a/composer.json
+++ b/composer.json
@@ -47,6 +47,12 @@
"name": "Dmitry Naumenko",
"email": "d.naumenko.a@gmail.com",
"role": "Core framework development"
+ },
+ {
+ "name": "Boudewijn Vahrmeijer",
+ "email": "info@dynasource.eu",
+ "homepage": "http://dynasource.eu",
+ "role": "Core framework development"
}
],
"support": {
diff --git a/docs/guide-es/concept-autoloading.md b/docs/guide-es/concept-autoloading.md
index 5c58e514a2..6c913291fe 100644
--- a/docs/guide-es/concept-autoloading.md
+++ b/docs/guide-es/concept-autoloading.md
@@ -3,7 +3,7 @@ Autocarga de clases
Yii depende del [mecanismo de autocarga de clases](http://www.php.net/manual/es/language.oop5.autoload.php) para localizar
e incluir los archivos de las clases requiridas. Proporciona un cargador de clases de alto rendimiento que cumple con el
-[estandard PSR-4](https://github.com/php-fig/fig-standards/blob/master/proposed/psr-4-autoloader/psr-4-autoloader.md).
+[estandard PSR-4](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md).
El cargador se instala cuando incluyes el archivo `Yii.php`.
> Note: Para simplificar la descripción, en esta sección sólo hablaremos de la carga automática de clases. Sin embargo,
diff --git a/docs/guide-ja/caching-data.md b/docs/guide-ja/caching-data.md
index d49ebeb552..3e9af59bed 100644
--- a/docs/guide-ja/caching-data.md
+++ b/docs/guide-ja/caching-data.md
@@ -13,14 +13,41 @@ $data = $cache->get($key);
if ($data === false) {
// キャッシュの中に $data が見つからない場合は一から作る
+ $data = $this->calculateSomething();
- // 次回はそれを取得できるように $data をキャッシュに格納する
+ // $data をキャッシュに格納して、次回はそれを取得できるようにする
$cache->set($key, $data);
}
-// $data はここで利用できる
+// この時点で $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);
+});
+```
+
+> Note: [[yii\caching\Cache::getOrSet()|getOrSet()]] メソッドは、有効期限と依存もサポートしています。
+ 詳しくは [キャッシュの有効期限](#cache-expiration) と [キャッシュの依存](#cache-dependencies) を参照してください。
+
## キャッシュコンポーネント
@@ -97,6 +124,8 @@ Yii はさまざまなキャッシュストレージをサポートしていま
* [[yii\caching\Cache::get()|get()]]: 指定されたキーを用いてキャッシュからデータを取得します。データが見つからないか、もしくは有効期限が切れたり無効になったりしている場合は false を返します。
* [[yii\caching\Cache::set()|set()]]: キーによって識別されるデータをキャッシュに格納します。
* [[yii\caching\Cache::add()|add()]]: キーがキャッシュ内で見つからない場合に、キーによって識別されるデータをキャッシュに格納します。
+* [[yii\caching\Cache::getOrSet()|getOrSet()]]: 指定されたキーを用いてキャッシュからデータを取得します。
+ 取得できなかった場合は、渡されたコールバック関数を実行し、関数の返り値をそのキーでキャッシュに保存し、そしてその値を返します。
* [[yii\caching\Cache::multiGet()|multiGet()]]: 指定されたキーを用いてキャッシュから複数のデータを取得します。
* [[yii\caching\Cache::multiSet()|multiSet()]]: キャッシュに複数のデータを格納します。各データはキーによって識別されます。
* [[yii\caching\Cache::multiAdd()|multiAdd()]]: キャッシュに複数のデータを格納します。各データはキーによって識別されます。もしキャッシュ内にキーがすでに存在する場合はスキップされます。
@@ -174,6 +203,9 @@ if ($data === false) {
}
```
+バージョン 2.0.11 以降は、デフォルトの無限の有効期限に替えて特定の有効期限を指定したい場合には、キャッシュコンポーネントの構成で [[yii\caching\Cache::$defaultDuration|defaultDuration]] の値を指定することが出来ます。
+これによって、特定の `duration` パラメータを毎回 [[yii\caching\Cache::set()|set()]] に渡さなくてもよくなります。
+
### キャッシュの依存
@@ -259,7 +291,7 @@ $result = Customer::getDb()->cache(function ($db) {
クエリキャッシュには [[yii\db\Connection]] を通して設定可能な三つのグローバルなオプションがあります:
-* [[yii\db\Connection::enableQueryCache|enableQueryCache]]: クエリキャッシュを可能にするかどうか。デフォルトは true です。
+* [[yii\db\Connection::enableQueryCache|enableQueryCache]]: クエリキャッシュを可能にするかどうか。デフォルトは `true` です。
実効的にクエリキャッシュをオンにするには [[yii\db\Connection::queryCache|queryCache]] によって指定される有効なキャッシュを持っている必要があることに注意してください。
* [[yii\db\Connection::queryCacheDuration|queryCacheDuration]]: これはクエリ結果がキャッシュ内に有効な状態として持続できる秒数を表します。
クエリキャッシュを永遠にキャッシュに残したい場合は 0 を指定することができます。
diff --git a/docs/guide-ja/caching-fragment.md b/docs/guide-ja/caching-fragment.md
index 550a82ec63..2f94ed95a2 100644
--- a/docs/guide-ja/caching-fragment.md
+++ b/docs/guide-ja/caching-fragment.md
@@ -15,7 +15,7 @@ if ($this->beginCache($id)) {
```
つまり、コンテント生成ロジックを [[yii\base\View::beginCache()|beginCache()]] と [[yii\base\View::endCache()|endCache()]] の呼び出しのペアで囲みます。
-コンテントがキャッシュ内で見つかった場合、[[yii\base\View::beginCache()|beginCache()]] はキャッシュされたコンテントをレンダリングして false を返し、結果として、コンテント生成ロジックがスキップされます。
+コンテントがキャッシュ内で見つかった場合、[[yii\base\View::beginCache()|beginCache()]] はキャッシュされたコンテントをレンダリングして `false` を返し、結果として、コンテント生成ロジックがスキップされます。
それ以外の場合はコンテント生成ロジックが呼ばれ、そして [[yii\base\View::endCache()|endCache()]] が呼ばれたときに、生成されたコンテントがキャプチャされ、キャッシュに格納されます。
[データキャッシュ](caching-data.md) と同様に、キャッシュされるコンテントを識別するためにユニークな `$id` が必要になります。
diff --git a/docs/guide-ja/concept-autoloading.md b/docs/guide-ja/concept-autoloading.md
index f793f01914..eb3fff93a2 100644
--- a/docs/guide-ja/concept-autoloading.md
+++ b/docs/guide-ja/concept-autoloading.md
@@ -2,7 +2,7 @@
=================
Yiiは、必要となるすべてのクラスファイルを特定してインクルードするにあたり、 [クラスのオートローディングメカニズム](http://www.php.net/manual/ja/language.oop5.autoload.php)
-を頼りにします。Yii は、[PSR-4 標準](https://github.com/php-fig/fig-standards/blob/master/proposed/psr-4-autoloader/psr-4-autoloader.md) に準拠した、高性能なクラスのオートローダーを提供しています。
+を頼りにします。Yii は、[PSR-4 標準](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md) に準拠した、高性能なクラスのオートローダーを提供しています。
このオートローダーは、あなたが `Yii.php` ファイルをインクルードするときにインストールされます。
> Note: 説明を簡単にするため、このセクションではクラスのオートローディングについてのみお話しします。しかし、
diff --git a/docs/guide-ja/concept-configurations.md b/docs/guide-ja/concept-configurations.md
index 27c904cad1..26979c25ec 100644
--- a/docs/guide-ja/concept-configurations.md
+++ b/docs/guide-ja/concept-configurations.md
@@ -130,6 +130,26 @@ $config = [
アプリケーションの `components` プロパティ構成の詳細については、 [アプリケーション](structure-applications.md) セクションと [サービスロケータ](concept-service-locator.md) セクションにあります。
+バージョン 2.0.11 以降では、アプリケーション構成で `container` プロパティを使って [依存注入コンテナ](concept-di-container.md) を構成することがサポートされています。
+
+```php
+$config = [
+ 'id' => 'basic',
+ 'basePath' => dirname(__DIR__),
+ 'extensions' => require(__DIR__ . '/../vendor/yiisoft/extensions.php'),
+ 'container' => [
+ 'definitions' => [
+ 'yii\widgets\LinkPager' => ['maxButtonCount' => 5]
+ ],
+ 'singletons' => [
+ // 依存注入コンテナのシングルトンの構成
+ ]
+ ]
+];
+```
+
+`definitions` と `singletons` の構成情報配列に使用できる値とその実例についてさらに知るためには、
+[依存注入コンテナ](concept-di-container.md)の記事の [高度な実際の使用方法](concept-di-container.md#advanced-practical-usage) の節を読んでください。
### ウィジェットの構成
diff --git a/docs/guide-ja/concept-di-container.md b/docs/guide-ja/concept-di-container.md
index 730ee0587e..a221ebea3d 100644
--- a/docs/guide-ja/concept-di-container.md
+++ b/docs/guide-ja/concept-di-container.md
@@ -19,9 +19,9 @@ Yii は [[yii\di\Container]] クラスを通して DI コンテナの機能を
### コンストラクタ·インジェクション
-DI コンテナは、コンストラクタパラメータの型ヒントの助けを借りた、コンストラクタ·インジェクションをサポートしています。
+DI コンテナは、コンストラクタのパラメータの型ヒントの助けを借りた、コンストラクタ·インジェクションをサポートしています。
型ヒントは、コンテナが新しいオブジェクトの作成に使用されるさい、オブジェクトがどういうクラスやインタフェースに依存しているかをコンテナに教えます。
-コンテナは、依存クラスやインタフェースのインスタンスを取得することを試み、コンストラクタを通して、新しいオブジェクトにそれらの注入します。
+コンテナは、依存クラスやインタフェースのインスタンスを取得することを試み、コンストラクタを通して、新しいオブジェクトにそれらを注入します。
たとえば
```php
@@ -61,8 +61,8 @@ class MyClass extends \yii\base\Component
}
```
-あなた自身で `\my\heavy\Dependency` のインスタンスを渡すか、次のように
-[[yii\di\Container::invoke()]] を使えば、このメソッドを呼ぶことが出来ます。
+このメソッドを呼ぶためには、あなた自身で `\my\heavy\Dependency` のインスタンスを渡すか、または、次のように
+[[yii\di\Container::invoke()]] を使います。
```php
$obj = new MyClass(/*...*/);
@@ -73,7 +73,7 @@ Yii::$container->invoke([$obj, 'doSomething'], ['param1' => 42]); // $something
### セッター/プロパティ·インジェクション
セッター/プロパティ·インジェクションは、[構成情報](concept-configurations.md) を通してサポートされます。
-依存がそれに対応するセッターまたはプロパティを通して注入される場合、依存関係を登録するときや、新しいオブジェクトを作成するときに、依存注入のためにコンテナが使用する構成情報を提供することが出来ます。
+依存を登録するときや、新しいオブジェクトを作成するときに、対応するセッターまたはプロパティを通しての依存注入に使用される構成情報を、コンテナに提供することが出来ます。
たとえば
```php
@@ -110,7 +110,7 @@ $container->get('Foo', [], [
この場合、コンテナは、登録された PHP のコーラブルを使用して、クラスの新しいインスタンスを構築します。
[[yii\di\Container::get()]] が呼ばれるたびに、対応するコーラブルが起動されます。
-このコーラブルが、依存関係を解決し、新しく作成されたオブジェクトに適切に依存を注入する役目を果たします。
+このコーラブルが、依存を解決し、新しく作成されたオブジェクトに適切に依存を注入する役目を果たします。
たとえば
```php
@@ -145,10 +145,10 @@ $foo = $container->get('Foo');
このようにすれば、`Foo` クラスを構成しようとする人は、`Foo` がどのように構築されるかを気にする必要はもうなくなります。
-依存関係の登録
---------------
+依存の登録
+----------
-あなたは、[[yii\di\Container::set()]] を使って依存関係を登録することができます。
+[[yii\di\Container::set()]] を使って依存を登録することができます。
登録には依存の名前だけでなく、依存の定義が必要です。
依存の名前は、クラス名、インタフェース名、エイリアス名を指定することができます。
依存の定義には、クラス名、構成情報配列、PHPのコーラブルを指定できます。
@@ -213,20 +213,20 @@ $container->setSingleton('yii\db\Connection', [
```
-依存関係の解決
+依存の解決
--------------
-依存関係を登録すると、新しいオブジェクトを作成するのに DI コンテナを使用することができます。
+依存を登録すると、新しいオブジェクトを作成するのに DI コンテナを使用することができます。
そして、コンテナが自動的に依存をインスタンス化し、新しく作成されたオブジェクトに注入して、
-依存関係を解決します。依存関係の解決は再帰的に行われます。つまり、ある依存が他の依存関係を持っている場合、
-それらの依存関係も自動的に解決されます。
+依存を解決します。依存の解決は再帰的に行われます。つまり、ある依存が他の依存を持っている場合、
+それらの依存も自動的に解決されます。
-[[yii\di\Container::get()]] を使って、新しいオブジェクトを作成することができます。
-このメソッドは、クラス名、インタフェース名、エイリアス名で指定できる依存の名前を受け取ります。
-依存の名前は、 `set()` や `setSingleton()` を介して登録されている場合もあれば、登録されていない場合もあります。
-オプションで、クラスのコンストラクタのパラメータのリストや、新しく作成されたオブジェクトを設定するための
-[設定情報](concept-configurations.md) を渡すことができます。
-たとえば
+[[yii\di\Container::get()|get()]] を使って、オブジェクトのインスタンスを取得または作成することができます。
+このメソッドは依存の名前を引数として取ります、依存の名前は、クラス名、インタフェース名、あるいは、エイリアス名で指定できます。
+依存の名前は、 [[yii\di\Container::set()|set()]] または [[yii\di\Container::setSingleton()|setSingleton()]] を介して登録されている場合もあります。
+オプションで、クラスのコンストラクタのパラメータのリストや、[設定情報](concept-configurations.md) を渡して、新しく作成されるオブジェクトを構成することも出来ます。
+
+たとえば、
```php
// "db" は事前に登録されたエイリアス名
@@ -238,12 +238,12 @@ $engine = $container->get('app\components\SearchEngine', [$apiKey, $apiSecret],
見えないところで、DIコンテナは、単に新しいオブジェクトを作成するよりもはるかに多くの作業を行います。
コンテナは、最初にクラスのコンストラクタを調査し、依存クラスまたはインタフェースの名前を見つけると、
-自動的にそれらの依存関係を再帰的に解決します。
+自動的にそれらの依存を再帰的に解決します。
次のコードでより洗練された例を示します。 `UserLister` クラスは `UserFinderInterface`
インタフェースを実装するオブジェクトに依存します。 `UserFinder` クラスはこのインターフェイスを実装していて、かつ、
-`Connection` オブジェクトに依存します。これらのすべての依存関係は、クラスのコンストラクタのパラメータの型ヒントによって宣言されています。
-プロパティ依存性の登録をすれば、DI コンテナは自動的にこれらの依存関係を解決し、単純に `get('userLister')`
+`Connection` オブジェクトに依存します。これらのすべての依存は、クラスのコンストラクタのパラメータの型ヒントによって宣言されています。
+プロパティ依存性の登録をすれば、DI コンテナは自動的にこれらの依存を解決し、単純に `get('userLister')`
を呼び出すだけで新しい `UserLister` インスタンスを作成できます。
```php
@@ -303,17 +303,17 @@ $lister = new UserLister($finder);
```
-実際の使いかた
+実際の使用方法
--------------
あなたのアプリケーションの [エントリスクリプト](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\di\Container::get()|get()]] メソッドを呼び出して新しいオブジェクトを作成します。
+前述のとおり、DI コンテナは(もしあれば)自動的に依存を解決し、取得されたオブジェクトにそれらを注入します。
+Yii は、新しいオブジェクトを作成するコアコードのほとんどにおいて [[Yii::createObject()]] を使用しています。このことは、
+[[Yii::$container]] を操作することでグローバルにオブジェクトをカスタマイズすることができるということを意味しています。
-たとえば、 [[yii\widgets\LinkPager]] のページネーションボタンのデフォルト個数をグローバルにカスタマイズすることができます:
+例として、 [[yii\widgets\LinkPager]] のページネーションボタンのデフォルト個数をグローバルにカスタマイズしてみましょう。
```php
\Yii::$container->set('yii\widgets\LinkPager', ['maxButtonCount' => 5]);
@@ -334,9 +334,9 @@ echo \yii\widgets\LinkPager::widget(['maxButtonCount' => 20]);
> Tip: どのような型の値であろうとも上書きされますので、オプションの配列の指定には気を付けてください。オプションの配列はマージされません。
-DI コンテナの自動コンストラクタ・インジェクションの利点を活かす別の例です。
+もう一つの例は、DI コンテナの自動コンストラクタ・インジェクションの利点を活かすものです。
あなたのコントローラクラスが、ホテル予約サービスのような、いくつかの他のオブジェクトに依存するとします。
-あなたは、コンストラクタパラメータを通して依存関係を宣言して、DI コンテナにあなたの課題を解決させることができます。
+あなたは、コンストラクタのパラメータを通して依存を宣言して、DI コンテナにそれを解決させることができます。
```php
namespace app\controllers;
@@ -357,26 +357,155 @@ class HotelController extends Controller
```
あなたがブラウザからこのコントローラにアクセスすると、 `BookingInterface` をインスタンス化できない、という不平を言う
-エラーが表示されるでしょう。これは、この依存関係に対処する方法を DI コンテナに教える必要があるからです:
+エラーが表示されるでしょう。これは、この依存に対処する方法を DI コンテナに教える必要があるからです:
```php
\Yii::$container->set('app\components\BookingInterface', 'app\components\BookingService');
```
-これで、あなたが再びコントローラにアクセスするときは、 `app\components\BookingService`
+これで、あなたが再びコントローラにアクセスするときは、`app\components\BookingService`
のインスタンスが作成され、コントローラのコンストラクタに3番目のパラメータとして注入されるようになります。
-いつ依存関係を登録するか
-------------------------
+高度な実際の使用方法
+--------------------
-依存関係は、新しいオブジェクトが作成されるとき必要とされるので、それらの登録は可能な限り早期に行われるべきです。
-推奨プラクティス以下のとおりです:
+API アプリケーションを開発していて、以下のクラスを持っているとします。
-* あなたがアプリケーションの開発者である場合、アプリケーションの [エントリスクリプト](structure-entry-scripts.md) 内、
- またはエントリスクリプトにインクルードされるスクリプト内で、依存関係を登録することができます。
+- `app\components\Request` クラス。`yii\web\Request` から拡張され、追加の機能を提供する。
+- `app\components\Response` クラス。`yii\web\Response` から拡張。生成されるときに、`format` プロパティが `json` に設定されなければならない。
+- `app\storage\FileStorage` および `app\storage\DocumentsReader` クラス。
+ 何らかのファイルストレージに配置されているドキュメントを操作するロジックを実装する。
+
+ ```php
+ class FileStorage
+ {
+ public function __contruct($root) {
+ // あれやこれや
+ }
+ }
+
+ class DocumentsReader
+ {
+ public function __contruct(FileStorage $fs) {
+ // なんやかんや
+ }
+ }
+ ```
+
+[[yii\di\Container::setDefinitions()|setDefinitions()]] または [[yii\di\Container::setSingletons()|setSingletons()]]
+のメソッドに構成情報の配列を渡して、複数の定義を一度に構成することが可能です。
+これらのメソッドは、構成情報配列を反復して、各アイテムに対し、それぞれ [[yii\di\Container::set()|set()]] を呼び出します。
+
+構成情報配列のフォーマットは、
+
+ - `key`: クラス名、インタフェイス名、または、エイリアス名。
+ このキーが [[yii\di\Container::set()|set()]] メソッドの最初の引数 `$class` として渡されます。
+ - `value`: `$class` と関連づけられる定義。指定できる値は、[[yii\di\Container::set()|set()]] の `$definition`
+ パラメータのドキュメントで説明されています。[[set()]] メソッドに二番目のパラメータ `$definition` として渡されます。
+
+例として、上述の要求に従うように私たちのコンテナを構成しましょう。
+
+```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);
+// 構成情報に書かれている依存とともに DocumentReader オブジェクトが生成されます
+```
+
+> Tip: バージョン 2.0.11 以降では、アプリケーションの構成情報を使って、宣言的なスタイルでコンテナを構成することが出来ます。
+[構成情報](concept-configurations.md) のガイドの [アプリケーションの構成](concept-configurations.md#application-configurations) の節を参照してください。
+これで全部動きますが、`DocumentWriter` クラスを生成する必要がある場合には、
+`FileStorage` オブジェクトを生成する行をコピペすることになるでしょう。
+もちろん、それが一番スマートな方法ではありません。
+
+[依存を解決する](#resolving-dependencies) の節で説明したように、[[yii\di\Container::set()|set()]] と [[yii\di\Container::setSingleton()|setSingleton()]] は、
+オプションで、第三の引数として依存のコンストラクタのパラメータを取ることが出来ます。
+コンストラクタのパラメータを設定するために、以下の構成情報配列の形式を使うことが出来ます。
+
+ - `key`: クラス名、インタフェイス名、または、エイリアス名。
+ このキーが [[yii\di\Container::set()|set()]] メソッドの最初の引数 `$class` として渡されます。
+ - `value`: 二つの要素を持つ配列。最初の要素は [[set()]] メソッドに二番目のパラメータ `$definition` として渡され、第二の要素が `$params` として渡されます。
+
+では、私たちの例を修正しましょう。
+
+```php
+$container->setDefinitions([
+ 'tempFileStorage' => [ // 便利なようにエイリアスを作りました
+ ['class' => 'app\storage\FileStorage'],
+ ['/var/tempfiles'] // 何らかの構成ファイルから抽出することも可能
+ ],
+ '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);
+// 前の例と全く同じオブジェクトが生成されます
+```
+
+`Instance::of('tempFileStorage')` という記法に気づいたことでしょう。
+これは、[[yii\di\Container|Container]] が、`tempFileStorage` という名前で登録されている依存を黙示的に提供して、
+`app\storage\DocumentsWriter` のコンストラクタの最初の引数として渡す、ということを意味しています。
+
+> Note: [[yii\di\Container::setDefinitions()|setDefinitions()]] および [[yii\di\Container::setSingletons()|setSingletons()]]
+ のメソッドは、バージョン 2.0.11 以降で利用できます。
+
+構成情報の最適化にかかわるもう一つのステップは、いくつかの依存をシングルトンとして登録することです。
+[[yii\di\Container::set()|set()]] を通じて登録された依存は、必要になるたびに、毎回インスタンス化されます。
+しかし、ある種のクラスは実行時を通じて状態を変化させませんので、アプリケーションのパフォーマンスを高めるためにシングルトンとして登録することが出来ます。
+
+`app\storage\FileStorage` クラスが好例でしょう。これは単純な API によってファイルシステムに対する何らかの操作を実行するもの
+(例えば `$fs->read()` や `$fs->write()`) ですが、これらの操作はクラスの内部状態を変化させないものです。
+従って、このクラスのインスタンスを一度だけ生成して、それを複数回使用することが可能です。
+
+```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);
+```
+
+いつ依存を登録するか
+--------------------
+
+依存は、新しいオブジェクトが作成されるとき必要とされるので、それらの登録は可能な限り早期に行われるべきです。
+推奨されるプラクティスは以下のとおりです:
+
+* あなたがアプリケーションの開発者である場合は、アプリケーションの構成情報を使って依存を登録することが出来ます。
+ [構成情報](concept-configurations.md) のガイドの [アプリケーションの構成](concept-configurations.md#application-configurations) の節を読んでください。
* あなたが再配布可能な [エクステンション](structure-extensions.md) の開発者である場合は、エクステンションのブートストラップクラス内で
- 依存関係を登録することができます。
+ 依存を登録することができます。
まとめ
@@ -388,5 +517,5 @@ class HotelController extends Controller
Yii はその [サービスロケータ](concept-service-locator.md) を、依存注入 (DI) コンテナの上に実装しています。
サービスロケータは、新しいオブジェクトのインスタンスを作成しようとするとき、DI コンテナに呼び出しを転送します。
-後者は、依存関係を、上で説明したように自動的に解決します。
+後者は、依存を、上で説明したように自動的に解決します。
diff --git a/docs/guide-ja/db-active-record.md b/docs/guide-ja/db-active-record.md
index c8b99a496f..8bc243856c 100644
--- a/docs/guide-ja/db-active-record.md
+++ b/docs/guide-ja/db-active-record.md
@@ -48,7 +48,19 @@ Yii は次のリレーショナルデータベースに対して、アクティ
## アクティブレコードクラスを宣言する
まずは、[[yii\db\ActiveRecord]] を拡張してアクティブレコードクラスを宣言するところから始めましょう。
-すべてのアクティブレコードクラスはデータベーステーブルと関連付けられますので、このクラスの中で [[yii\db\ActiveRecord::tableName()|tableName()]] メソッドをオーバーライドして、どのテーブルにこのクラスが関連付けられるかを指定しなければなりません。
+
+### テーブル名を設定する
+
+デフォルトでは、すべてのアクティブレコードクラスはデータベーステーブルと関連付けられます。
+[[yii\db\ActiveRecord::tableName()|tableName()]] メソッドが、クラス名を [[yii\helpers\Inflector::camel2id()]] によって変換して、テーブル名を返します。
+テーブル名がこの規約に従っていない場合は、このメソッドをオーバライドすることが出来ます。
+
+同時に、デフォルトの [[yii\db\Connection::$tablePrefix|tablePrefix]] を適用することも可能です。
+例えば、[[yii\db\Connection::$tablePrefix|tablePrefix]] が `tbl_` である場合は、`Customer` は `tbl_customer` になり、`OrderItem` は`tbl_order_item` になります。
+
+テーブル名が `{{%TableName}}` という形式で与えられた場合は、パーセント記号 `%` がテーブルプレフィックスに置き換えられます。
+例えば、`{{%post}}` は `{{tbl_post}}` となります。
+テーブル名を囲む二重波括弧は、[テーブル名を囲む引用符号](db-dao.md#quoting-table-and-column-names) となります。
次の例では、`customer` というデータベーステーブルのための `Customer` という名前のアクティブレコードクラスを宣言しています。
@@ -67,11 +79,13 @@ class Customer extends ActiveRecord
*/
public static function tableName()
{
- return 'customer';
+ return '{{customer}}';
}
}
```
+### アクティブレコードは「モデル」と呼ばれる
+
アクティブレコードのインスタンスは [モデル](structure-models.md) であると見なされます。
この理由により、私たちは通常 `app\models` 名前空間 (あるいはモデルクラスを保管するための他の名前空間) の下にアクティブレコードクラスを置きます。
@@ -429,6 +443,27 @@ $customer->loadDefaultValues();
```
+### 属性の型キャスト
+
+[[yii\db\ActiveRecord]] は、クエリの結果を投入されるときに、[データベーステーブルスキーマ](db-dao.md#database-schema)
+からの情報を使って、自動的な型キャストを実行します。これによって、整数として宣言されているテーブルカラムから取得されるデータを
+アクティブレコードのインスタンスでも PHP の integer として投入し、
+真偽値として宣言されているデータを boolean として投入することが出来るようになっています。
+しかしながら、型キャストのメカニズムには、いくつかの制約があります。
+
+* 浮動小数点数値は変換されず、文字列として表されます。そうしないと精度が失われるおそれがあるからです。
+* 整数値の変換は、あなたが使っているオペレーティングシステムの整数の大きさに依存します。具体的に言うと、
+ 'unsigned integer' または 'big integer' として宣言されたカラムの値は、64-bit オペレーティングシステムでのみ PHP の integer に変換されます。
+ 32-bit オペレーティングシステムでは、文字列として表されます。
+
+属性の型キャストは、アクティブレコードのインスタンスにクエリの結果から値を投入するときだけしか実行されないことに注意してください。
+HTTP リクエストから値をロードしたり、プロパティにアクセスして直接に値を設定したりするときには、自動的な変換は行われません。
+また、アクティブレコードのデータ保存のための SQL 文を準備する際にもテーブルスキーマが使用されて、値が正しい型でクエリにバインドされることを保証します。
+しかし、アクティブレコードのインスタンスの属性値は保存の過程において変換されることはありません。
+
+> Tip: アクティブレコードのバリデーションや保存の際の属性型キャストを楽にするために
+[[yii\behaviors\AttributeTypecastBehavior]] を使うことが出来ます。
+
### 複数の行を更新する
上述のメソッドは、すべて、個別のアクティブレコードインスタンスに対して作用し、個別のテーブル行を挿入したり更新したりするものです。
@@ -559,9 +594,17 @@ try {
} catch(\Exception $e) {
$transaction->rollBack();
throw $e;
+} catch(\Throwable $e) {
+ $transaction->rollBack();
+ throw $e;
}
```
+> Note: 上記のコードでは、PHP 5.x と PHP 7.x との互換性のために、二つの
+> catch ブロックを持っています。`\Exception` は PHP 7.0 以降では、
+> [`\Throwable` インターフェイス](http://php.net/manual/ja/class.throwable.php) を実装しています。
+> 従って、あなたのアプリケーションが PHP 7.0 以上しか使わない場合は、`\Exception` の部分を省略することが出来ます。
+
第二の方法は、トランザクションのサポートが必要な DB 操作を [[yii\db\ActiveRecord::transactions()]] メソッドに列挙するという方法です。
```php
@@ -944,7 +987,7 @@ $customers = Customer::find()->with([
>
> ```php
> $orders = Order::find()->select(['id', 'amount'])->with('customer')->all();
-> // この場合、$orders[0]->customer は常に null になります。
+> // この場合、$orders[0]->customer は常に `null` になります。
> // 問題を修正するためには、次のようにしなければなりません。
> $orders = Order::find()->select(['id', 'amount', 'customer_id'])->with('customer')->all();
> ```
@@ -1052,6 +1095,17 @@ $query->joinWith([
$query->joinWith(['orders o'])->orderBy('o.id');
```
+上記の文法が動作するのは単純なリレーションの場合です。ネストされたリレーションを結合する
+(例えば、`$query->joinWith(['orders.product'])` ) ときに、中間テーブルのエイリアスが必要になった場合は、
+次の例のように、joinWith の呼び出しをネストさせる必要があります。
+
+```php
+$query->joinWith(['orders o' => function($q) {
+ $q->joinWith('product p');
+ }])
+ ->where('o.amount > 100');
+```
+
### 逆リレーション
リレーションの宣言は、たいていの場合、二つのアクティブレコードクラスの間で相互的なものになります。
@@ -1233,10 +1287,10 @@ $customers = Customer::find()->with('comments')->all();
例えば、
```php
+// file Comment.php
namespace app\models;
use yii\db\ActiveRecord;
-use yii\db\ActiveQuery;
class Comment extends ActiveRecord
{
@@ -1245,39 +1299,52 @@ class Comment extends ActiveRecord
return new CommentQuery(get_called_class());
}
}
-
-class CommentQuery extends ActiveQuery
-{
- // ...
-}
```
-このようにすると、`Comment` のクエリを実行したり (例えば `find()` や `findOne()` を呼んだり) リレーションを定義したり (例えば `hasOne()` を定義したり) する際には、いつでも、`AcctiveQuery` の代りに `CommentQuery` のインスタンスを使用することになります。
+このようにすると、`Comment` のクエリを実行したり (例えば `find()` や `findOne()` を呼んだり)、`Comment` とのリレーションを定義したり (例えば `hasOne()` を定義したり) する際には、いつでも、`AcctiveQuery` の代りに `CommentQuery` のインスタンスを使用することになります。
-> Tip: 大きなプロジェクトでは、アクティブレコードクラスをクリーンに保つことが出来るように、クエリ関連のコードのほとんどをカスタマイズされたクエリクラスに保持することが推奨されます。
-
-クエリクラスは、さまざまのクリエイティブな方法によってカスタマイズして、あなたのクエリ構築の体験を向上させることが出来ます。
-例えば、カスタマイズされたクエリクラスにおいて、新しいクエリ構築メソッドを定義することが出来ます。
+さて、`CommentQuery` クラスを定義しなければならない訳ですが、このクラスをさまざまな創造的方法でカスタマイズして、
+あなたのクエリ構築作業を楽しいものにすることが出来ます。例えば、
```php
+// file CommentQuery.php
+namespace app\models;
+
+use yii\db\ActiveQuery;
+
class CommentQuery extends ActiveQuery
{
+ // デフォルトで条件を追加 (省略可)
+ public function init()
+ {
+ $this->andOnCondition(['deleted' => false]);
+ parent::init();
+ }
+
+ // ... ここにカスタマイズしたクエリメソッドを追加 ...
+
public function active($state = true)
{
- return $this->andWhere(['active' => $state]);
+ return $this->andOnCondition(['active' => $state]);
}
}
```
-> Note: 新しいクエリ構築メソッドを定義する場合は、通常は、既存の条件が上書きされないように、[[yii\db\ActiveQuery::where()|where()]] ではなく、[[yii\db\ActiveQuery::andWhere()|andWhere()]] または [[yii\db\ActiveQuery::orWhere()|orWhere()]] を呼んで条件を追加しなければなりません。
+> Note: 新しいクエリ構築メソッドを定義するときには、通常は、既存のどの条件も上書きしないように、
+[[yii\db\ActiveQuery::onCondition()|onCondition()]] ではなく、
+[[yii\db\ActiveQuery::andOnCondition()|andOnCondition()]] または [[yii\db\ActiveQuery::orOnCondition()|orOnCondition()]]
+を呼んで条件を追加しなければなりません。
+
+このようにすると、次のようなクエリ構築のコードを書くことが出来るようになります。
-このようにすると、次のようにクエリ構築のコードを書くことが出来るようになります。
-
```php
$comments = Comment::find()->active()->all();
$inactiveComments = Comment::find()->active(false)->all();
```
+
+> Tip: 大きなプロジェクトでは、アクティブレコードクラスをクリーンに保つことが出来るように、クエリ関連のコードのほとんどをカスタマイズされたクエリクラスに保持することが推奨されます。
+
この新しいクエリ構築メソッドは、`Comment` に関するリレーションを定義するときや、リレーショナルクエリを実行するときにも使用することが出来ます。
```php
@@ -1292,7 +1359,14 @@ class Customer extends \yii\db\ActiveRecord
$customers = Customer::find()->with('activeComments')->all();
// あるいは、また
-
+class Customer extends \yii\db\ActiveRecord
+{
+ public function getComments()
+ {
+ return $this->hasMany(Comment::className(), ['customer_id' => 'id']);
+ }
+}
+
$customers = Customer::find()->with([
'comments' => function($q) {
$q->active();
@@ -1374,7 +1448,8 @@ $customers = Customer::find()
```
この方法を使うことの短所の一つは、情報が SQL クエリでロードされていない場合には、それを別途計算しなければならない、ということです。
-このことは、また、新しく保存したレコードも追加のフィールドについては情報を持っていないことになることを意味します。
+従って、追加のセレクト文を持たない通常のクエリによって特定のレコードを読み出した場合には、追加のフィールドの実際の値を返すことは不可能になります。
+同じことが新しく保存されたレコードでも起こります。
```php
$room = new Room();
@@ -1382,7 +1457,7 @@ $room->length = 100;
$room->width = 50;
$room->height = 2;
-$room->volume; // まだ指定されていないため、この値は null になります。
+$room->volume; // まだ指定されていないため、この値は `null` になります。
```
[[yii\db\BaseActiveRecord::__get()|__get()]] と [[yii\db\BaseActiveRecord::__set()|__set()]] のマジックメソッドを使用すれば、プロパティの動作をエミュレートすることが出来ます。
@@ -1418,18 +1493,18 @@ class Room extends \yii\db\ActiveRecord
このようにすると、SELECT クエリによって容積が提供されていない場合に、モデルの他の属性を使って容積を自動的に計算することが出来ます。
-この手法は、リレーショナルデータに依存する追加のフィールドに対しても、同じように使用する事が出来ます。
+集約フィールドも、同じように、定義されたリレーションを使って計算することが出来ます。
```php
class Customer extends \yii\db\ActiveRecord
{
private $_ordersCount;
-
+
public function setOrdersCount($count)
{
$this->_ordersCount = (int) $count;
}
-
+
public function getOrdersCount()
{
if ($this->isNewRecord) {
@@ -1437,7 +1512,7 @@ class Customer extends \yii\db\ActiveRecord
}
if ($this->_ordersCount === null) {
- $this->setOrdersCount(count($this->orders));
+ $this->setOrdersCount(count($this->orders)); // 要求に応じてリレーションから集約を計算
}
return $this->_ordersCount;
@@ -1451,3 +1526,54 @@ class Customer extends \yii\db\ActiveRecord
}
}
```
+
+このコードでは、'ordersCount' が 'select' 文に存在する場合は、`Customer::ordersCount` はクエリの結果によって投入されます。
+そうでない場合は、要求に応じて、`Customer::orders` リレーションを使って計算されます。
+
+マジックメソッドによってプロパティをエミュレートする手法は、ある種のリレーショナルデータ、特に集約のショートカットを作成するためにも使用することが出来ます。
+例えば、
+
+```php
+class Customer extends \yii\db\ActiveRecord
+{
+ /**
+ * 読み出し専用の集約データの仮想プロパティを定義
+ */
+ public function getOrdersCount()
+ {
+ if ($this->isNewRecord) {
+ return null; // プライマリキーが null の場合のリレーショナルクエリを防止
+ }
+
+ return $this->ordersAggregation[0]['counted'];
+ }
+
+ /**
+ * 通常の 'orders' リレーションを宣言
+ */
+ public function getOrders()
+ {
+ return $this->hasMany(Order::className(), ['customer_id' => 'id']);
+ }
+
+ /**
+ * 集約データを提供する新しいリレーションを 'orders' を元にして宣言
+ */
+ public function getOrdersAggregation()
+ {
+ return $this->getOrders()
+ ->select(['customer_id', 'counted' => 'count(*)'])
+ ->groupBy('customer_id')
+ ->asArray(true);
+ }
+
+ // ...
+}
+
+foreach (Customer::find()->with('ordersAggregation')->all() as $customer) {
+ echo $customer->ordersCount; // イーガーローディングにより、追加のクエリなしに、リレーションから集約データを出力
+}
+
+$customer = Customer::findOne($pk);
+$customer->ordersCount; // レイジーロードされたリレーションから集約データを出力
+```
diff --git a/docs/guide-ja/db-dao.md b/docs/guide-ja/db-dao.md
index 19c0ecacda..1b69959016 100644
--- a/docs/guide-ja/db-dao.md
+++ b/docs/guide-ja/db-dao.md
@@ -18,6 +18,8 @@ Yii は下記の DBMS のサポートを内蔵しています。
- [Oracle](http://www.oracle.com/us/products/database/overview/index.html)
- [MSSQL](https://www.microsoft.com/en-us/sqlserver/default.aspx): バージョン 2008 以上。
+> Note: PHP 7 用の pdo_oci の新しいバージョンは、現在、ソースコードとしてのみ存在します。
+ [コミュニティによる説明](https://github.com/yiisoft/yii2/issues/10975#issuecomment-248479268) に従って、コンパイルしてください。
## DB 接続を作成する
@@ -320,11 +322,11 @@ try {
// ... その他の SQL 文を実行 ...
$transaction->commit();
-
} catch(\Exception $e) {
-
$transaction->rollBack();
-
+ throw $e;
+} catch(\Throwable $e) {
+ $transaction->rollBack();
throw $e;
}
```
@@ -337,6 +339,12 @@ try {
が呼ばれて、トランザクションの中で失敗したクエリに先行するクエリによって行なわれた変更が、ロールバックされます。
そして、`throw $e` が、まるでそれをキャッチしなかったかのように、例外を再スローしますので、通常のエラー処理プロセスがその例外の面倒を見ることになります。
+> Note: 上記のコードでは、PHP 5.x と PHP 7.x との互換性のために、二つの
+> catch ブロックを持っています。`\Exception` は PHP 7.0 以降では、
+> [`\Throwable` インターフェイス](http://php.net/manual/ja/class.throwable.php) を実装しています。
+> 従って、あなたのアプリケーションが PHP 7.0 以上しか使わない場合は、`\Exception` の部分を省略することが出来ます。
+
+
### 分離レベルを指定する
Yii は、トランザクションの [分離レベル] の設定もサポートしています。
@@ -408,12 +416,18 @@ try {
} catch (\Exception $e) {
$innerTransaction->rollBack();
throw $e;
+ } catch(\Throwable $e) {
+ $transaction->rollBack();
+ throw $e;
}
$outerTransaction->commit();
} catch (\Exception $e) {
$outerTransaction->rollBack();
throw $e;
+} catch(\Throwable $e) {
+ $transaction->rollBack();
+ throw $e;
}
```
@@ -549,6 +563,9 @@ try {
} catch(\Exception $e) {
$transaction->rollBack();
throw $e;
+} catch(\Throwable $e) {
+ $transaction->rollBack();
+ throw $e;
}
```
@@ -567,7 +584,7 @@ $rows = Yii::$app->db->useMaster(function ($db) {
});
```
-直接に `Yii::$app->db->enableSlaves` を false に設定して、全てのクエリをマスタ接続に向けることも出来ます。
+直接に `Yii::$app->db->enableSlaves` を `false` に設定して、全てのクエリをマスタ接続に向けることも出来ます。
## データベーススキーマを扱う
diff --git a/docs/guide-ja/db-migrations.md b/docs/guide-ja/db-migrations.md
index a812a43d3b..e8c2cccc67 100644
--- a/docs/guide-ja/db-migrations.md
+++ b/docs/guide-ja/db-migrations.md
@@ -409,6 +409,11 @@ class m160328_040430_create_post_table extends Migration
上記の例で `author_id:integer:notNull:foreignKey(user)` は、`user` テーブルへの外部キーを持つ `author_id` という名前のカラムを生成します。
一方、`category_id:integer:defaultValue(1):foreignKey` は、`category` テーブルへの外部キーを持つ `category_id` というカラムを生成します。
+2.0.11 以降では、`foreignKey` キーワードは空白で区切られた第二のパラメータを取ることが出来ます。
+これは、生成される外部キーに関連づけられるカラム名を表します。
+第二のパラメータが渡されなかった場合は、カラム名はテーブルスキーマから取得されます。
+スキーマが存在しない場合や、プライマリキーが設定されていなかったり、複合キーであったりする場合は、デフォルト名として `id` が使用されます。
+
### テーブルを削除する
@@ -590,6 +595,9 @@ class m160328_041642_create_junction_table_for_post_and_tag_tables extends Migra
}
```
+2.0.11 以降では、中間テーブルの外部キーのカラム名はテーブルスキーマから取得されます。
+スキーマでテーブルが定義されていない場合や、プライマリキーが設定されていなかったり複合キーであったりする場合は、デフォルト名 `id` が使われます。
+
### トランザクションを使うマイグレーション
@@ -861,6 +869,86 @@ return [
もう、`migrationTable` のコマンドラインオプションを使ってテーブルを指定する必要はなくなります。
+### Namespaced Migrations
+
+Since 2.0.10 you can use namespaces for the migration classes. You can specify the list of the migration namespaces via
+[[yii\console\controllers\MigrateController::migrationNamespaces|migrationNamespaces]]. Using of the namespaces for
+migration classes allows you usage of the several source locations for the migrations. For example:
+
+```php
+return [
+ 'controllerMap' => [
+ 'migrate' => [
+ 'class' => 'yii\console\controllers\MigrateController',
+ 'migrationNamespaces' => [
+ 'app\migrations', // Common migrations for the whole application
+ 'module\migrations', // Migrations for the specific project's module
+ 'some\extension\migrations', // Migrations for the specific extension
+ ],
+ ],
+ ],
+];
+```
+
+> Note: migrations applied from different namespaces will create a **single** migration history, e.g. you might be
+ unable to apply or revert migrations from particular namespace only.
+
+While operating namespaced migrations: creating new, reverting and so on, you should specify full namespace before
+migration name. Note that backslash (`\`) symbol is usually considered a special character in the shell, so you need
+to escape it properly to avoid shell errors or incorrect behavior. For example:
+
+```
+yii migrate/create 'app\\migrations\\createUserTable'
+```
+
+> Note: migrations specified via [[yii\console\controllers\MigrateController::migrationPath|migrationPath]] can not
+ contain a namespace, namespaced migration can be applied only via [[yii\console\controllers\MigrateController::migrationNamespaces]]
+ property.
+
+
+### 分離されたマイグレーション
+
+Sometimes using single migration history for all project migrations is not desirable. For example: you may install some
+'blog' extension, which contains fully separated functionality and contain its own migrations, which should not affect
+the ones dedicated to main project functionality.
+
+これらをお互いに完全に分離して適用かつ追跡したい場合は、別々の名前空間とマイグレーション履歴テーブルを使う
+複数のマイグレーションコマンドを構成することが出来ます。
+
+```php
+return [
+ 'controllerMap' => [
+ // アプリケーション全体のための共通のマイグレーション
+ 'migrate-app' => [
+ 'class' => 'yii\console\controllers\MigrateController',
+ 'migrationNamespaces' => ['app\migrations'],
+ 'migrationTable' => 'migration_app',
+ ],
+ // 特定のモジュールのためのマイグレーション
+ 'migrate-module' => [
+ 'class' => 'yii\console\controllers\MigrateController',
+ 'migrationNamespaces' => ['module\migrations'],
+ 'migrationTable' => 'migration_module',
+ ],
+ // 特定のエクステンションのためのマイグレーション
+ 'migrate-rbac' => [
+ 'class' => 'yii\console\controllers\MigrateController',
+ 'migrationPath' => '@yii/rbac/migrations',
+ 'migrationTable' => 'migration_rbac',
+ ],
+ ],
+];
+```
+
+データベースを同期するためには、一つではなく複数のコマンドを実行しなければならなくなることに注意してください。
+
+```
+yii migrate-app
+yii migrate-module
+yii migrate-rbac
+```
+
+
## 複数のデータベースにマイグレーションを適用する
デフォルトでは、マイグレーションは `db` [アプリケーションコンポーネント](structure-application-components.md) によって指定された同じデータベースに対して適用されます。
diff --git a/docs/guide-ja/db-query-builder.md b/docs/guide-ja/db-query-builder.md
index dbbfd36ee9..e8288b5e27 100644
--- a/docs/guide-ja/db-query-builder.md
+++ b/docs/guide-ja/db-query-builder.md
@@ -328,7 +328,7 @@ $query->filterWhere([
[[yii\db\Query::filterWhere()|filterWhere()]] と [[yii\db\Query::where()|where()]] の唯一の違いは、前者は [ハッシュ形式](#hash-format) の条件において提供された空の値を無視する、という点です。
従って、`$email` が空で `$sername` がそうではない場合は、上記のコードは、結果として `WHERE username=:username` という SQL 条件になります。
-> Info: 値が空であると見なされるのは、null、空の配列、空の文字列、または空白のみを含む文字列である場合です。
+> Info: 値が空であると見なされるのは、`null`、空の配列、空の文字列、または空白のみを含む文字列である場合です。
[[yii\db\Query::andWhere()|andWhere()]] または [[yii\db\Query::orWhere()|orWhere()]] と同じように、[[yii\db\Query::andFilterWhere()|andFilterWhere()]] または [[yii\db\Query::orFilterWhere()|orFilterWhere()]] を使って、既存の条件に別のフィルタ条件を追加することも出来ます。
@@ -346,6 +346,12 @@ $query->andFilterCompare('value', '<=100');
$query->andFilterCompare('name', 'Doe', 'like');
```
+Yii 2.0.11 以降には、`HAVING` の条件のためにも、同様のメソッドがあります。
+
+- [[yii\db\Query::filterHaving()|filterHaving()]]
+- [[yii\db\Query::andFilterHaving()|andFilterHaving()]]
+- [[yii\db\Query::orFilterHaving()|orFilterHaving()]]
+
### [[yii\db\Query::orderBy()|orderBy()]]
[[yii\db\Query::orderBy()|orderBy()]] メソッドは SQL クエリの `ORDER BY` 句を指定します。例えば、
diff --git a/docs/guide-ja/helper-array.md b/docs/guide-ja/helper-array.md
index e0af8350c6..39541b629d 100644
--- a/docs/guide-ja/helper-array.md
+++ b/docs/guide-ja/helper-array.md
@@ -88,7 +88,7 @@ if (!ArrayHelper::keyExists('username', $data1, false) || !ArrayHelper::keyExist
良くある例は、ID のリストの取得です。
```php
-$data = [
+$array = [
['id' => '123', 'data' => 'abc'],
['id' => '345', 'data' => 'def'],
];
@@ -114,7 +114,7 @@ $result = ArrayHelper::getColumn($array, function ($element) {
`$groups` 属性はキーの配列であり、入力値の配列を一つまたは複数のサブ配列にグループ化するために使用されます。
-特定の要素の `$key` 属性またはその値が null であるとき、`$groups` が定義されていない場合は、その要素は破棄されて、結果には入りません。
+特定の要素の `$key` 属性またはその値が `null` であるとき、`$groups` が定義されていない場合は、その要素は破棄されて、結果には入りません。
そうではなく、`$groups` が指定されている場合は、配列の要素はキー無しで結果の配列に追加されます。
例えば、
@@ -398,7 +398,7 @@ $data = ArrayHelper::toArray($posts, [
- キー/値 のペア - 配列のキー名にしたい文字列と、値を取得すべきモデルのカラムの名前。
- キー/値 のペア - 配列のキー名にしたい文字列と、値を返すコールバック。
-変換の結果は以下のようになります。
+単一のモデルに対する上記の変換の結果は以下のようになります。
```php
diff --git a/docs/guide-ja/helper-html.md b/docs/guide-ja/helper-html.md
index 80637ee26e..e1942a049b 100644
--- a/docs/guide-ja/helper-html.md
+++ b/docs/guide-ja/helper-html.md
@@ -42,7 +42,7 @@ Yii はそのような手助けを Html ヘルパの形式で提供します。
オプションは多くの Html ヘルパのメソッドとさまざまなウィジェットで使用されます。
その全ての場合において、いくつか追加の処理がなされることを知っておいてください。
-- 値が null である場合は、対応する属性はレンダリングされません。
+- 値が `null` である場合は、対応する属性はレンダリングされません。
- 値が真偽値である属性は、[真偽値属性 (boolean attributes)](http://www.w3.org/TR/html5/infrastructure.html#boolean-attributes) として扱われます。
- 属性の値は [[yii\helpers\Html::encode()|Html::encode()]] を使って HTML エンコードされます。
- 属性の値が配列である場合は、次のように処理されます。
diff --git a/docs/guide-ja/tutorial-console.md b/docs/guide-ja/tutorial-console.md
index 8e4790687c..6b4a5a4a0b 100644
--- a/docs/guide-ja/tutorial-console.md
+++ b/docs/guide-ja/tutorial-console.md
@@ -140,7 +140,7 @@ class HelloController extends Controller
{
public $message;
- public function options()
+ public function options($actionID)
{
return ['message'];
}
diff --git a/docs/guide-ru/README.md b/docs/guide-ru/README.md
index f4b79b7333..527dc1a27c 100644
--- a/docs/guide-ru/README.md
+++ b/docs/guide-ru/README.md
@@ -147,7 +147,7 @@ All Rights Reserved.
* [Отладочная панель и отладчик](https://github.com/yiisoft/yii2-debug/blob/master/docs/guide/README.md)
* [Генерация кода с Gii](https://github.com/yiisoft/yii2-gii/blob/master/docs/guide/README.md)
-* **TBD** [Генератор документации API](https://github.com/yiisoft/yii2-apidoc)
+* [Генератор документации API](https://github.com/yiisoft/yii2-apidoc)
Тестирование
@@ -180,14 +180,14 @@ All Rights Reserved.
Виджеты
-------
-* GridView: link to demo page
-* ListView: link to demo page
-* DetailView: link to demo page
-* ActiveForm: link to demo page
-* Pjax: link to demo page
-* Menu: link to demo page
-* LinkPager: link to demo page
-* LinkSorter: link to demo page
+* [GridView](http://www.yiiframework.com/doc-2.0/yii-grid-gridview.html)
+* [ListView](http://www.yiiframework.com/doc-2.0/yii-widgets-listview.html)
+* [DetailView](http://www.yiiframework.com/doc-2.0/yii-widgets-detailview.html)
+* [ActiveForm](http://www.yiiframework.com/doc-2.0/guide-input-forms.html#activerecord-based-forms-activeform)
+* [Pjax](http://www.yiiframework.com/doc-2.0/yii-widgets-pjax.html)
+* [Menu](http://www.yiiframework.com/doc-2.0/yii-widgets-menu.html)
+* [LinkPager](http://www.yiiframework.com/doc-2.0/yii-widgets-linkpager.html)
+* [LinkSorter](http://www.yiiframework.com/doc-2.0/yii-widgets-linksorter.html)
* [Виджеты Bootstrap](https://github.com/yiisoft/yii2-bootstrap/blob/master/docs/guide/README.md)
* [Виджеты Jquery UI](https://github.com/yiisoft/yii2-jui/blob/master/docs/guide/README.md)
diff --git a/docs/guide-ru/caching-data.md b/docs/guide-ru/caching-data.md
index 60ce0abcca..226d9bde2a 100644
--- a/docs/guide-ru/caching-data.md
+++ b/docs/guide-ru/caching-data.md
@@ -11,8 +11,8 @@
$data = $cache->get($key);
if ($data === false) {
-
- // $data нет в кэше, считаем с нуля.
+ // $data нет в кэше, вычисляем заново
+ $data = $this->calculateSomething();
// Сохраняем значение $data в кэше. Данные можно получить в следующий раз.
$cache->set($key, $data);
@@ -21,6 +21,33 @@ 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);
+});
+```
+
+> Note: В [[yii\caching\Cache::getOrSet()|getOrSet()]] можно передать срока действия и зависимости кэша.
+ Прочтите [Срок действия кэша](#cache-expiration) и [Зависимости кеша](#cache-dependencies) чтобы узнать больше.
+
## Компоненты кэширования
@@ -88,6 +115,8 @@ Yii поддерживает множество хранилищ кэша:
значение `false` будет возвращено;
* [[yii\caching\Cache::set()|set()]]: сохраняет данные по ключу;
* [[yii\caching\Cache::add()|add()]]: сохраняет данные по ключу если такого ключа ещё нет;
+* [[yii\caching\Cache::getOrSet()|getOrSet()]]: возвращает данные по указанному ключу или выполняет переданную
+ анонимную функцию для вычисления значения, а полученные данные сохраняет в кэш и возвращает;
* [[yii\caching\Cache::multiGet()|multiGet()]]: извлекает сразу несколько элементов данных из кэша по заданным ключам;
* [[yii\caching\Cache::multiSet()|multiSet()]]: сохраняет несколько элементов данных. Каждый элемент идентифицируется ключом;
* [[yii\caching\Cache::multiAdd()|multiAdd()]]: сохраняет несколько элементов данных. Каждый элемент идентифицируется ключом.
@@ -161,8 +190,8 @@ if ($data === false) {
}
```
-Начиная с версии 2.0.11 вы можете изменить значение по умолчанию (бесконечность) для длительности кеширования задав
-[[yii\caching\Cache::$defaultDuration|defaultDuration]] в конфигурации компонента кеша. Таким образом, можно будет
+Начиная с версии 2.0.11 вы можете изменить значение по умолчанию (бесконечность) для длительности кэширования задав
+[[yii\caching\Cache::$defaultDuration|defaultDuration]] в конфигурации компонента кэша. Таким образом, можно будет
не передавать значение `duration` в [[yii\caching\Cache::set()|set()]] каждый раз.
### Зависимости кэша
@@ -231,7 +260,7 @@ $result = Customer::getDb()->cache(function ($db) {
- `yii cache`: отображает список доступных кэширующих компонентов приложения
- `yii cache/flush cache1 cache2`: очищает кэш в компонентах `cache1`, `cache2` (можно передать несколько названий
компонентов кэширования, разделяя их пробелом)
- - `yii cache/flush-all`: очищает кэш во всех кеширующих компонентах приложения
+ - `yii cache/flush-all`: очищает кэш во всех кэширующих компонентах приложения
> Info: Консольное приложение использует отдельный конфигурационный файл по умолчанию. Для получения должного
результата, убедитесь, что в конфигурациях консольного и веб-приложения у вас одинаковые компоненты кэширования.
@@ -311,4 +340,4 @@ $result = $db->cache(function ($db) {
Кэширование запросов не работает с результатами запросов, которые содержат обработчики ресурсов. Например, при использовании типа столбца `BLOB` в некоторых СУБД, в качестве результата запроса будет выведен ресурс обработчик данных столбца.
-Некоторые кэш хранилища имеют ограничение в размере данных. Например, Memcache ограничивает максимальный размер каждой записи до 1 Мб. Таким образом, если результат запроса превышает этот предел, данные не будут закешированы.
+Некоторые кэш хранилища имеют ограничение в размере данных. Например, Memcache ограничивает максимальный размер каждой записи до 1 Мб. Таким образом, если результат запроса превышает этот предел, данные не будут закэшированы.
diff --git a/docs/guide-ru/concept-autoloading.md b/docs/guide-ru/concept-autoloading.md
index 531c86b02e..5005d8a298 100644
--- a/docs/guide-ru/concept-autoloading.md
+++ b/docs/guide-ru/concept-autoloading.md
@@ -3,7 +3,7 @@
Поиск и подключение файлов классов в Yii реализовано при помощи
[автозагрузки классов](http://www.php.net/manual/ru/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)
автозагрузчик, который устанавливается в момент подключения `Yii.php`.
> Note: Для простоты повествования, в этом разделе мы будем говорить только об автозагрузке классов. Тем не менее,
diff --git a/docs/guide-ru/concept-components.md b/docs/guide-ru/concept-components.md
index 78fd0d693f..dec5a1d7f0 100644
--- a/docs/guide-ru/concept-components.md
+++ b/docs/guide-ru/concept-components.md
@@ -10,7 +10,7 @@
Как по отдельности, так и вместе, эти возможности делают классы Yii более простыми в настройке и использовании.
Например, пользовательские компоненты, включающие в себя [[yii\jui\DatePicker|виджет выбора даты]], могут быть
-использованы в [представлении](structure-view.md) для генерации интерактивных элементов выбора даты:
+использованы в [представлении](structure-views.md) для генерации интерактивных элементов выбора даты:
```php
use yii\jui\DatePicker;
diff --git a/docs/guide-ru/db-active-record.md b/docs/guide-ru/db-active-record.md
index e023e37c5a..4df276e864 100644
--- a/docs/guide-ru/db-active-record.md
+++ b/docs/guide-ru/db-active-record.md
@@ -644,9 +644,16 @@ try {
} catch(\Exception $e) {
$transaction->rollBack();
throw $e;
+} catch(\Throwable $e) {
+ $transaction->rollBack();
+ throw $e;
}
```
+> Note: в коде выше ради совместимости с PHP 5.x и PHP 7.x использованы два блока catch.
+> `\Exception` реализует интерфейс [`\Throwable` interface](http://php.net/manual/ru/class.throwable.php)
+> начиная с PHP 7.0. Если вы используете только PHP 7 и новее, можете пропустить блок с `\Exception`.
+
Второй способ заключается в том, чтобы перечислить операции с базой данных, которые требуют тразнакционного выполнения,
в методе [[yii\db\ActiveRecord::transactions()]]. Например:
diff --git a/docs/guide-ru/db-dao.md b/docs/guide-ru/db-dao.md
index da1d9c89ad..0c710f9d04 100644
--- a/docs/guide-ru/db-dao.md
+++ b/docs/guide-ru/db-dao.md
@@ -329,15 +329,18 @@ try {
// ... executing other SQL statements ...
$transaction->commit();
-
} catch(\Exception $e) {
-
$transaction->rollBack();
-
throw $e;
+} catch(\Throwable $e) {
+ $transaction->rollBack();
}
```
+> Note: в коде выше ради совместимости с PHP 5.x и PHP 7.x использованы два блока catch.
+> `\Exception` реализует интерфейс [`\Throwable` interface](http://php.net/manual/ru/class.throwable.php)
+> начиная с PHP 7.0. Если вы используете только PHP 7 и новее, можете пропустить блок с `\Exception`.
+
При вызове метода [[yii\db\Connection::beginTransaction()|beginTransaction()]], будет запущена новая транзакция.
Транзакция представлена объектом [[yii\db\Transaction]] сохранённым в переменной `$transaction`. Потом, запросы будут
выполняться в блоке `try...catch...`. Если запросы будут выполнены удачно, будет выполнен метод [[yii\db\Transaction::commit()|commit()]].
@@ -357,7 +360,7 @@ Yii::$app->db->transaction(function ($db) {
....
}, $isolationLevel);
-// or alternatively
+// или
$transaction = Yii::$app->db->beginTransaction($isolationLevel);
```
@@ -393,10 +396,10 @@ Yii предоставляет четыре константы для наибо
```php
Yii::$app->db->transaction(function ($db) {
- // outer transaction
+ // внешняя транзакция
$db->transaction(function ($db) {
- // inner transaction
+ // внутренняя транзакция
});
});
```
@@ -415,11 +418,17 @@ try {
$innerTransaction->commit();
} catch (\Exception $e) {
$innerTransaction->rollBack();
+ } catch (\Throwable $e) {
+ $innerTransaction->rollBack();
+ throw $e;
}
$outerTransaction->commit();
} catch (\Exception $e) {
$outerTransaction->rollBack();
+} catch (\Throwable $e) {
+ $innerTransaction->rollBack();
+ throw $e;
}
```
@@ -560,6 +569,9 @@ try {
} catch(\Exception $e) {
$transaction->rollBack();
throw $e;
+} catch (\Throwable $e) {
+ $innerTransaction->rollBack();
+ throw $e;
}
```
diff --git a/docs/guide-ru/db-migrations.md b/docs/guide-ru/db-migrations.md
index f6c9941888..a55e00c5ca 100644
--- a/docs/guide-ru/db-migrations.md
+++ b/docs/guide-ru/db-migrations.md
@@ -783,6 +783,87 @@ return [
С приведённой выше конфигурацией, каждый раз при запуске команды миграции, таблица `backend_migration` будет использована для записи истории миграций. И Вам больше не нужно указывать её через параметр `migrationTable` в командной строке.
+
+### Миграции с пространсвом имен
+
+Начиная с версии 2.0.10 вы можете использовать пространства имен при объявлении класса миграции. Вы можете указать список пространств
+имен миграций через [[yii\console\controllers\MigrateController::migrationNamespaces|migrationNamespaces]]. Использование пространств
+имен для классов миграции позволяет сочетать несколько источников миграций. Например:
+
+```php
+return [
+ 'controllerMap' => [
+ 'migrate' => [
+ 'class' => 'yii\console\controllers\MigrateController',
+ 'migrationNamespaces' => [
+ 'app\migrations', // Общие миграции приложения
+ 'module\migrations', // Миграции одного из модулей проекта
+ 'some\extension\migrations', // Миграции одного из расширений
+ ],
+ ],
+ ],
+];
+```
+
+> Замечание: миграции из различных пространств имен образуют **единую** историю, т.е. вы не сможете
+ применить или откатить миграции из одного конкретного пространства имен.
+
+Работая с миграциями по пространствам имен: при создании, отмене и т.д., следует указывать полное имя пространства имен
+перед именем миграции. Имейте в виду, что символ обратного слеша (`\`), как правило, является специальным символом в консоли,
+так что вам придется экранировать его соответствующим образом во избежании ошибок или неверного поведения. Например:
+
+```
+yii migrate/create 'app\\migrations\\createUserTable'
+```
+
+> Замечание: миграции заданные через [[yii\console\controllers\MigrateController::migrationPath|migrationPath]] не могут содержать
+ пространство имен, миграции, объявленные с пространством имен могут быть применены только используя свойство [[yii\console\controllers\MigrateController::migrationNamespaces]].
+
+
+### Отдельностоящие Миграции
+
+Иногда использование единой истории для всех миграция проекта не желательно. Например: вы можете установить расширение
+'blog', которое содержит полностью независимый функционал и содержит собственные миграции, которые не должны затрагивать
+миграции связанные с основной функциональностью проекта.
+
+Если необходимо, чтобы миграции из разных источников были независимы друг от друга, вы можете сконфигурировать
+несколько команд миграции, которые будут использовать разные пространства имён и разные таблицы для хранения истории
+миграций:
+
+```php
+return [
+ 'controllerMap' => [
+ // Общие миграции приложения
+ 'migrate-app' => [
+ 'class' => 'yii\console\controllers\MigrateController',
+ 'migrationNamespaces' => ['app\migrations'],
+ 'migrationTable' => 'migration_app',
+ ],
+ // Миграции одного из модулей проекта
+ 'migrate-module' => [
+ 'class' => 'yii\console\controllers\MigrateController',
+ 'migrationNamespaces' => ['module\migrations'],
+ 'migrationTable' => 'migration_module',
+ ],
+ // Миграции одного из расширений
+ 'migrate-rbac' => [
+ 'class' => 'yii\console\controllers\MigrateController',
+ 'migrationPath' => '@yii/rbac/migrations',
+ 'migrationTable' => 'migration_rbac',
+ ],
+ ],
+];
+```
+
+Учтите, что для синхронизации базы данных при такой конфигурации потребуется вызвать несколько команд вместо одной:
+
+```
+yii migrate-app
+yii migrate-module
+yii migrate-rbac
+```
+
+
## Миграции в Несколько Баз Данных
По умолчанию, миграции применяются для базы данных, указанной в `db` [компоненте приложения](structure-application-components.md).
@@ -826,3 +907,4 @@ yii migrate --migrationPath=@app/migrations/db2 --db=db2
```
Первая команда применит миграции в директории `@app/migrations/db1` к базе данных `db1`, а вторая команда применит миграции в директории `@app/migrations/db2` к базе данных `db2` и так далее.
+
diff --git a/docs/guide-ru/intro-upgrade-from-v1.md b/docs/guide-ru/intro-upgrade-from-v1.md
index e7b98eea73..51a4ed5b38 100644
--- a/docs/guide-ru/intro-upgrade-from-v1.md
+++ b/docs/guide-ru/intro-upgrade-from-v1.md
@@ -18,7 +18,7 @@
Yii 2.0 широко использует [Composer](https://getcomposer.org/), который является основным менеджером зависимостей для PHP.
Установка как фреймворка, так и расширений, осуществляется через Composer. Подробно о установке Yii 2.0 вы можете узнать
из раздела «[Установка Yii](start-installation.md)». О том, как создавать расширения для Yii 2.0 или адаптировать
-уже имеющиеся расширения от версии 1.1, вы можете узнать из раздела «[Создание расширений](extend-creating-extensions.md)».
+уже имеющиеся расширения от версии 1.1, вы можете узнать из раздела «[Создание расширений](structure-extensions.md#creating-extensions)».
Требования PHP
@@ -528,4 +528,4 @@ User и IdentityInterface
----------------------------------
Информация об использовании кода для Yii 1.1 вместе с Yii 2.0 представлена в разделе
-«[Одновременное использование Yii 1.1 и 2.0](extend-using-v1-v2.md)».
+«[Одновременное использование Yii 1.1 и 2.0](tutorial-yii-integration.md#using-both-yii2-yii1)».
diff --git a/docs/guide-ru/output-formatting.md b/docs/guide-ru/output-formatting.md
index f1024c09be..4afb759acb 100644
--- a/docs/guide-ru/output-formatting.md
+++ b/docs/guide-ru/output-formatting.md
@@ -17,7 +17,7 @@ Formatter может быть использован двумя различны
echo Yii::$app->formatter->asEmail('cebe@example.com'); // выведет: cebe@example.com
echo Yii::$app->formatter->asBoolean(true); // выведет: Yes
// он также умеет отображать null значения:
- echo Yii::$app->formatter->asDate(null); // выведет: (Not set)
+ echo Yii::$app->formatter->asDate(null); // выведет: (not set)
```
2. Используя метод [[yii\i18n\Formatter::format()|format()]] и имя формата.
diff --git a/docs/guide-ru/start-gii.md b/docs/guide-ru/start-gii.md
index 7fb95f4911..f68ef7a8da 100644
--- a/docs/guide-ru/start-gii.md
+++ b/docs/guide-ru/start-gii.md
@@ -1,7 +1,7 @@
Генерация кода при помощи Gii
========================
-В этом разделе мы опишем, как использовать [Gii](tool-gii.md) для автоматической генерации кода,
+В этом разделе мы опишем, как использовать [Gii](https://github.com/yiisoft/yii2-gii/blob/master/docs/guide-ru/README.md) для автоматической генерации кода,
реализующего некоторые общие функции вебсайта. Для достижения этой цели всё, что вам нужно, это просто ввести необходимую информацию в соответствии с инструкциями, отображаемыми на веб-страницах Gii.
В этом руководстве вы узнаете:
@@ -15,7 +15,7 @@
Запускаем Gii
------------
-[Gii](tool-gii.md) представлен в Yii как [модуль](structure-modules.md). Вы можете активировать Gii,
+[Gii](https://github.com/yiisoft/yii2-gii/blob/master/docs/guide-ru/README.md) представлен в Yii как [модуль](structure-modules.md). Вы можете активировать Gii,
настроив его в свойстве [[yii\base\Application::modules|modules]]. В зависимости от того, каким образом вы создали приложение, вы можете удостовериться в наличии следующего кода в конфигурационном файле `config/web.php`,
```php
@@ -119,7 +119,7 @@ http://hostname/index.php?r=country%2Findex
* Модели: `models/Country.php` и `models/CountrySearch.php`
* Вид: `views/country/*.php`
-> Info: Gii разработан как тонконастраиваемый и расширяемый инструмент генерации кода. Используя его с умом, вы можете значительно ускорить скорость разработки приложений. Для более подробной информации, пожалуйста, обратитесь к разделу [Gii](tool-gii.md).
+> Info: Gii разработан как тонконастраиваемый и расширяемый инструмент генерации кода. Используя его с умом, вы можете значительно ускорить скорость разработки приложений. Для более подробной информации, пожалуйста, обратитесь к разделу [Gii](https://github.com/yiisoft/yii2-gii/blob/master/docs/guide-ru/README.md).
Заключение
diff --git a/docs/guide-ru/start-installation.md b/docs/guide-ru/start-installation.md
index 0147746e04..236149042e 100644
--- a/docs/guide-ru/start-installation.md
+++ b/docs/guide-ru/start-installation.md
@@ -1,4 +1,4 @@
-Установка Yii
+Установка Yii
==============
Вы можете установить Yii двумя способами: используя [Composer](https://getcomposer.org/) или скачав архив.
diff --git a/docs/guide-ru/structure-applications.md b/docs/guide-ru/structure-applications.md
index dc0427b634..0f3cee6209 100644
--- a/docs/guide-ru/structure-applications.md
+++ b/docs/guide-ru/structure-applications.md
@@ -190,7 +190,7 @@ if (YII_ENV_DEV) {
#### [[yii\base\Application::components|components]]
Данное свойство является наиболее важным. Оно позволяет вам зарегистрировать список именованных компонентов, называемых
-[компоненты приложения](#structure-application-components.md), которые Вы можете использовать в других местах.
+[компоненты приложения](structure-application-components.md), которые Вы можете использовать в других местах.
Например,
```php
diff --git a/docs/guide-ru/structure-widgets.md b/docs/guide-ru/structure-widgets.md
index 69895487bf..ea13a38f82 100644
--- a/docs/guide-ru/structure-widgets.md
+++ b/docs/guide-ru/structure-widgets.md
@@ -201,7 +201,7 @@ public function run()
Разрабатываемые виджеты должны быть самодостаточными. Это означает, что для их использования должно быть
достаточно всего лишь добавить виджет в представление. Добиться этого бывает затруднительно в том случае,
когда для его функционирования требуются внешние ресурсы, такие как CSS, JavaScript, изображения и т.д.
-К счастью, Yii предоставляет поддержку механизма для работы с ресурсами [asset bundles](structure-asset-bundles.md),
+К счастью, Yii предоставляет поддержку механизма для работы с ресурсами [asset bundles](structure-assets.md),
который может быть успешно использован для решения данной проблемы.
В случае, когда виджет не содержит логики, а содержит только код, отвечающий за вывод разметки, он мало
diff --git a/docs/guide-ru/tutorial-console.md b/docs/guide-ru/tutorial-console.md
index cea69deb60..022554a999 100644
--- a/docs/guide-ru/tutorial-console.md
+++ b/docs/guide-ru/tutorial-console.md
@@ -107,6 +107,55 @@ exit($exitCode);
> yii --appconfig=path/to/config.php ...
> ```
+Автодополнение консольных команд
+---------------
+
+Автодополнение аргументов команд является полезной возможностью при работе в командной строке.
+Начиная с версии 2.0.11, команда `./yii` поддерживает автодополнение для Bash и ZSH.
+
+### Автодополнение для Bash
+
+Убедитесь, что средства автодополнения для Bash установлены. В большинстве дистрибутивов они поставляются по умолчанию.
+
+Сохраните скрипт для автодополнения в директорию `/etc/bash_completion.d/`:
+
+ curl -L https://raw.githubusercontent.com/yiisoft/yii2/master/contrib/completion/bash/yii -o /etc/bash_completion.d/yii
+
+Для временного использования, вы можете сохранить файл в произвольную директорию и подключить его на время работы сессии,
+вызвав команду `source yii`.
+
+Если скрипт был установлен глобально, вам потребуется перезапустить терминал или выполнить команду `source ~/.bashrc`
+для активации автодополнения.
+
+Обратитесь к [инструкции по автодополнению в Bash](https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html)
+чтобы узнать о других способах подключения скриптов автодополнения в ваше окружение.
+
+### Автодополнение для ZSH
+
+Сохраните скрипт автодополнения в директорию для скриптов автодополнения. Например, `~/.zsh/completion/`
+
+```
+mkdir -p ~/.zsh/completion
+curl -L https://raw.githubusercontent.com/yiisoft/yii2/master/contrib/completion/zsh/_yii -o ~/.zsh/completion/_yii
+```
+
+Добавьте эту директорию в переменную среды `$fpath`, например добавив в конец `~/.zshrc` следующую строку:
+
+```
+fpath=(~/.zsh/completion $fpath)
+```
+
+Убедитесь, что программа `compinit` запущена. Если это не так - добавьте в `~/.zshrc` следующие строки:
+
+```
+autoload -Uz compinit && compinit -i
+```
+
+Затем перезапустите ваш терминал, либо выполните команду
+
+```
+exec $SHELL -l
+```
Создание ваших собственных команд
----------------------------------
@@ -159,7 +208,7 @@ class HelloController extends Controller
{
public $message;
- public function options()
+ public function options($actionID)
{
return ['message'];
}
diff --git a/docs/guide-ru/tutorial-core-validators.md b/docs/guide-ru/tutorial-core-validators.md
index db5c623d5f..9c583f32c7 100644
--- a/docs/guide-ru/tutorial-core-validators.md
+++ b/docs/guide-ru/tutorial-core-validators.md
@@ -33,8 +33,8 @@ public function rules()
Этот валидатор проверяет, что второе значение является *boolean*.
-- `trueValue`: значение, соответствующее *true*. По умолчанию - `'1'`.
-- `falseValue`: значение, соответствующее *false*. По умолчанию - `'0'`.
+- `trueValue`: значение, соответствующее `true`. По умолчанию - `'1'`.
+- `falseValue`: значение, соответствующее `false`. По умолчанию - `'0'`.
- `strict`: должна ли проверка учитывать соответствие типов данных `trueValue` или `falseValue`. По умолчанию - `false`.
> Note: Из-за того, что как правило данные, полученные из HTML-форм, представляются в виде строки, обычно вам стоит
@@ -65,9 +65,12 @@ public function rules()
[
// проверяет, является ли значение атрибута "password" таким же, как "password_repeat"
['password', 'compare'],
+
+ // то же, что и выше, но атрбут для сравнения указан явно
+ ['password', 'compare', 'compareAttribute' => 'password_repeat'],
// проверяет, что возраст больше или равен 30
- ['age', 'compare', 'compareValue' => 30, 'operator' => '>='],
+ ['age', 'compare', 'compareValue' => 30, 'operator' => '>=', 'type' => 'number'],
]
```
@@ -90,24 +93,59 @@ public function rules()
* `>=`: проверяет, что валидируемое значение больше или равно тому, с которым происходит сравнение.
* `<`: проверяет, что валидируемое значение меньше, чем то, с которым происходит сравнение.
* `<=`: проверяет, что валидируемое значение меньше или равно тому, с которым происходит сравнение.
+- `type`: По умолчанию при сравнении используется тип '[[yii\validators\CompareValidator::TYPE_STRING|string]]'. То есть
+ значения сравниваются побайтово. При сравнении чисел необходимо задать [[yii\validators\CompareValidator::$type|$type]]
+ как '[[yii\validators\CompareValidator::TYPE_NUMBER|number]]'.
## [[yii\validators\DateValidator|date]]
+Валидатор [[yii\validators\DateValidator|date]] можно использовать тремя способами:
+
```php
[
[['from', 'to'], 'date'],
+ [['from_datetime', 'to_datetime'], 'datetime'],
+ [['some_time'], 'time'],
]
```
+
Этот валидатор проверяет соответствие входящих данных форматам *date*, *time* или *datetime*.
Опционально, он может конвертировать входящее значение в UNIX timestamp и сохранить в атрибуте,
описанном здесь: [[yii\validators\DateValidator::timestampAttribute|timestampAttribute]].
-- `format`: формат даты/времени, согласно которому должна быть сделана проверка. Чтобы узнать больше о формате
- строки, пожалуйста, посмотрите [руководство PHP по date_create_from_format()](http://www.php.net/manual/ru/datetime.createfromformat.php)
- Значением по умолчанию является `'Y-m-d'`.
-- `timestampAttribute`: имя атрибута, которому этот валидатор может передать UNIX timestamp, конвертированный
- из строки даты/времени.
+- `format`: формат даты/времени, согласно которому должна быть сделана проверка.
+ Значение может быть паттерном, описанным в [руководстве ICU](http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax)
+ или форматом PHP префиксированным `php:`. Формат должен приниматься классом `Datetime`. Подробнее о нём можно
+ прочитать в [руководстве PHP по date_create_from_format()](http://www.php.net/manual/ru/datetime.createfromformat.php).
+ Если значение не задано, используется `Yii::$app->formatter->dateFormat`.
+ Подробнее читайте в [[yii\validators\DateValidator::$format|документации по API]].
+- `timestampAttribute`: имя атрибута, которому данный валидатор может присваивать значение UNIX timestamp,
+ получаемое из входных даты и времени. Это может быть как тот же атрибут, что валидируется в данный момент. Если это так,
+ после валидации оригинальное значение будет перезаписано значеним timestamp.
+ Дополнительные примеры вы модете найти в разделе ["Handling date input with the DatePicker"](https://github.com/yiisoft/yii2-jui/blob/master/docs/guide/topics-date-picker.md).
+
+ Начиная с версии 2.0.4, для атрибута могут быть заданы формат и часовой пояс через
+ [[yii\validators\DateValidator::$timestampAttributeFormat|$timestampAttributeFormat]] и
+ [[yii\validators\DateValidator::$timestampAttributeTimeZone|$timestampAttributeTimeZone]] соответственно.
+
+ При использовании `timestampAttribute`, входное значение будет конвертировано в unix timestamp, который по определению
+ содержит время в UTC. То есть будет произведено преобразование из [[yii\validators\DateValidator::timeZone|входного часового пояса]]
+ в UTC.
+
+- Начиная с версии 2.0.4 также можно задать [[yii\validators\DateValidator::$min|минимальное]] и
+ [[yii\validators\DateValidator::$max|максимальное]] значение timestamp.
+
+В том случае, если ввод не обязателен, вам может понадобится добавить [фильтр значения по умолчанию](#default) в
+дополнение к валидатору даты для того, чтобы пустой ввод сохранялся как `null`. В противном случае вы можете получить
+даты вроде `0000-00-00` в базе данных или `1970-01-01` в полях ввода виджета date picker.
+
+```php
+[
+ [['from_date', 'to_date'], 'default', 'value' => null],
+ [['from_date', 'to_date'], 'date'],
+],
+```
## [[yii\validators\DefaultValueValidator|default]]
diff --git a/docs/guide-uk/concept-autoloading.md b/docs/guide-uk/concept-autoloading.md
index 1dbcf3c3e1..60bbebdbc1 100644
--- a/docs/guide-uk/concept-autoloading.md
+++ b/docs/guide-uk/concept-autoloading.md
@@ -4,7 +4,7 @@
Пошук і підключення файлів класів в Yii реалізовано за допомогою
[автозавантаження класів](http://www.php.net/manual/ru/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),
який встановлюється в момент підключення файлу `Yii.php`.
> Note: Для простоти опису, в цьому розділі ми будемо говорити тільки про автозавантаження класів.
diff --git a/docs/guide-uk/tutorial-console.md b/docs/guide-uk/tutorial-console.md
index a155c09744..7ec4a218ff 100644
--- a/docs/guide-uk/tutorial-console.md
+++ b/docs/guide-uk/tutorial-console.md
@@ -143,7 +143,7 @@ class HelloController extends Controller
{
public $message;
- public function options()
+ public function options($actionID)
{
return ['message'];
}
diff --git a/docs/guide-zh-CN/concept-autoloading.md b/docs/guide-zh-CN/concept-autoloading.md
index 1149c74879..471b98ca02 100644
--- a/docs/guide-zh-CN/concept-autoloading.md
+++ b/docs/guide-zh-CN/concept-autoloading.md
@@ -1,7 +1,7 @@
类自动加载(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/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` 时安装好。
> Note: 为了简化叙述,本篇文档中我们只会提及类的自动加载。不过,要记得文中的描述同样也适用于接口和Trait(特质)的自动加载哦。
diff --git a/docs/guide/caching-data.md b/docs/guide/caching-data.md
index 72b36bee9d..e74696a2b4 100644
--- a/docs/guide/caching-data.md
+++ b/docs/guide/caching-data.md
@@ -13,8 +13,8 @@ a [cache component](#cache-components):
$data = $cache->get($key);
if ($data === false) {
-
// $data is not found in cache, calculate it from scratch
+ $data = $this->calculateSomething();
// store $data in cache so that it can be retrieved next time
$cache->set($key, $data);
@@ -23,6 +23,32 @@ if ($data === false) {
// $data is available here
```
+Since version 2.0.11, [cache component](#cache-components) provides [[yii\caching\Cache::getOrSet()|getOrSet()]] method
+that simplifies code for data getting, calculating and storing. The following code does exactly the same as the
+previous example:
+
+```php
+$data = $cache->getOrSet($key, function () {
+ return $this->calculateSomething();
+});
+```
+
+When cache has data associated with the `$key`, the cached value will be returned.
+Otherwise, the passed anonymous function will be executed to calculate the value that will be cached and returned.
+
+If the anonymous function requires some data from the outer scope, you can pass it with the `use` statement.
+For example:
+
+```php
+$user_id = 42;
+$data = $cache->getOrSet($key, function () use ($user_id) {
+ return $this->calculateSomething($user_id);
+});
+```
+
+> Note: [[yii\caching\Cache::getOrSet()|getOrSet()]] method supports duration and dependencies as well.
+ See [Cache Expiration](#cache-expiration) and [Cache Dependencies](#cache-dependencies) to know more.
+
## Cache Components
@@ -118,6 +144,8 @@ All cache components have the same base class [[yii\caching\Cache]] and thus sup
value will be returned if the data item is not found in the cache or is expired/invalidated.
* [[yii\caching\Cache::set()|set()]]: stores a data item identified by a key in cache.
* [[yii\caching\Cache::add()|add()]]: stores a data item identified by a key in cache if the key is not found in the cache.
+* [[yii\caching\Cache::getOrSet()|getOrSet()]]: retrieves a data item from cache with a specified key or executes passed
+ callback, stores return of the callback in a cache by a key and returns that data.
* [[yii\caching\Cache::multiGet()|multiGet()]]: retrieves multiple data items from cache with the specified keys.
* [[yii\caching\Cache::multiSet()|multiSet()]]: stores multiple data items in cache. Each item is identified by a key.
* [[yii\caching\Cache::multiAdd()|multiAdd()]]: stores multiple data items in cache. Each item is identified by a key.
@@ -128,7 +156,7 @@ All cache components have the same base class [[yii\caching\Cache]] and thus sup
> 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.
+this array instead to avoid this problem.
Some cache storage, such as MemCache, APC, support retrieving multiple cached values in a batch mode,
which may reduce the overhead involved in retrieving cached data. The APIs [[yii\caching\Cache::multiGet()|multiGet()]]
@@ -167,6 +195,10 @@ For example, [[yii\db\Schema]] uses the following key to cache schema informatio
As you can see, the key includes all necessary information needed to uniquely specify a database table.
+> Note: Values stored in cache via [[yii\caching\Cache::multiSet()|multiSet()]] or [[yii\caching\Cache::multiAdd()|multiAdd()]] can
+have only string or integer keys. If you need to set more complex key store the value separately via
+[[yii\caching\Cache::set()|set()]] or [[yii\caching\Cache::add()|add()]].
+
When the same cache storage is used by different applications, you should specify a unique cache key prefix
for each application to avoid conflicts of cache keys. This can be done by configuring the [[yii\caching\Cache::keyPrefix]]
property. For example, in the application configuration you can write the following code:
diff --git a/docs/guide/concept-components.md b/docs/guide/concept-components.md
index 44bc104901..e3ddcb63c2 100644
--- a/docs/guide/concept-components.md
+++ b/docs/guide/concept-components.md
@@ -9,7 +9,7 @@ or an extended class. The three main features that components provide to other c
* [Behaviors](concept-behaviors.md)
Separately and combined, these features make Yii classes much more customizable and easier to use. For example,
-the included [[yii\jui\DatePicker|date picker widget]], a user interface component, can be used in a [view](structure-view.md)
+the included [[yii\jui\DatePicker|date picker widget]], a user interface component, can be used in a [view](structure-views.md)
to generate an interactive date picker:
```php
diff --git a/docs/guide/concept-di-container.md b/docs/guide/concept-di-container.md
index 1f74678fee..2f9d455305 100644
--- a/docs/guide/concept-di-container.md
+++ b/docs/guide/concept-di-container.md
@@ -336,7 +336,9 @@ You can still override the value set via DI container, though:
echo \yii\widgets\LinkPager::widget(['maxButtonCount' => 20]);
```
-> Tip: no matter which value type it is, it will be overwritten so be careful with option arrays. They won't be merged.
+> 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.
Another example is to take advantage of the automatic constructor injection of the DI container.
Assume your controller class depends on some other objects, such as a hotel booking service. You
@@ -378,7 +380,7 @@ 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 the implement some logic on
+- `app\storage\FileStorage` and `app\storage\DocumentsReader` classes that implement some logic on
working with documents that are located in some file storage:
```php
@@ -430,10 +432,10 @@ $reader = $container->get('app\storage\DocumentsReader);
```
> Tip: Container may be configured in declarative style using application configuration since version 2.0.11.
-Check out the [Application Configurations](concept-service-locator.md#application-configurations) subsection of
+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 create `DocumentWriter` class,
+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()]]
@@ -442,7 +444,7 @@ a third argument. To set the constructor parameters, you may use the following c
- `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 the [[yii\di\Container::set()|set()]] method as the
+ - `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:
@@ -468,7 +470,7 @@ $reader = $container->get('app\storage\DocumentsReader);
```
You might notice `Instance::of('tempFileStorage')` notation. It means, that the [[yii\di\Container|Container]]
-will implicitly provide dependency, registered with `tempFileStorage` name and pass it as the first argument
+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()]]
@@ -512,7 +514,7 @@ Because dependencies are needed when new objects are being created, their regist
as early as possible. The following are the recommended practices:
* If you are the developer of an application, you can register your dependencies using application configuration.
- Please, read the [Application Configurations](concept-service-locator.md#application-configurations) subsection of
+ Please, read the [Application Configurations](concept-configurations.md#application-configurations) subsection of
the [Configurations](concept-configurations.md) guide article.
* If you are the developer of a redistributable [extension](structure-extensions.md), you can register dependencies
in the bootstrapping class of the extension.
diff --git a/docs/guide/db-active-record.md b/docs/guide/db-active-record.md
index e93a0f4b95..7a08c9fc00 100644
--- a/docs/guide/db-active-record.md
+++ b/docs/guide/db-active-record.md
@@ -636,9 +636,16 @@ try {
} catch(\Exception $e) {
$transaction->rollBack();
throw $e;
+} catch(\Throwable $e) {
+ $transaction->rollBack();
+ throw $e;
}
```
+> Note: in the above code we have two catch-blocks for compatibility
+> with PHP 5.x and PHP 7.x. `\Exception` implements the [`\Throwable` interface](http://php.net/manual/en/class.throwable.php)
+> since PHP 7.0, so you can skip the part with `\Exception` if your app uses only PHP 7.0 and higher.
+
The second way is to list the DB operations that require transactional support in the [[yii\db\ActiveRecord::transactions()]]
method. For example,
@@ -1603,7 +1610,7 @@ class Customer extends \yii\db\ActiveRecord
With this code, in case 'ordersCount' is present in 'select' statement - `Customer::ordersCount` will be populated
by query results, otherwise it will be calculated on demand using `Customer::orders` relation.
-This approach can be as well used for creation of the shortcuts for the some relational data, especially for the aggregation.
+This approach can be as well used for creation of the shortcuts for some relational data, especially for the aggregation.
For example:
```php
diff --git a/docs/guide/db-dao.md b/docs/guide/db-dao.md
index b344b11824..a4402a2891 100644
--- a/docs/guide/db-dao.md
+++ b/docs/guide/db-dao.md
@@ -328,18 +328,17 @@ The above code is equivalent to the following, which gives you more control abou
```php
$db = Yii::$app->db;
$transaction = $db->beginTransaction();
-
try {
$db->createCommand($sql1)->execute();
$db->createCommand($sql2)->execute();
// ... executing other SQL statements ...
$transaction->commit();
-
} catch(\Exception $e) {
-
$transaction->rollBack();
-
+ throw $e;
+} catch(\Throwable $e) {
+ $transaction->rollBack();
throw $e;
}
```
@@ -352,6 +351,10 @@ will be triggered and caught, the [[yii\db\Transaction::rollBack()|rollBack()]]
the changes made by the queries prior to that failed query in the transaction. `throw $e` will then re-throw the
exception as if we had not caught it, so the normal error handling process will take care of it.
+> Note: in the above code we have two catch-blocks for compatibility
+> with PHP 5.x and PHP 7.x. `\Exception` implements the [`\Throwable` interface](http://php.net/manual/en/class.throwable.php)
+> since PHP 7.0, so you can skip the part with `\Exception` if your app uses only PHP 7.0 and higher.
+
### Specifying Isolation Levels
@@ -424,12 +427,18 @@ try {
} catch (\Exception $e) {
$innerTransaction->rollBack();
throw $e;
+ } catch (\Throwable $e) {
+ $innerTransaction->rollBack();
+ throw $e;
}
$outerTransaction->commit();
} catch (\Exception $e) {
$outerTransaction->rollBack();
throw $e;
+} catch (\Throwable $e) {
+ $outerTransaction->rollBack();
+ throw $e;
}
```
@@ -573,6 +582,9 @@ try {
} catch(\Exception $e) {
$transaction->rollBack();
throw $e;
+} catch(\Throwable $e) {
+ $transaction->rollBack();
+ throw $e;
}
```
diff --git a/docs/guide/db-migrations.md b/docs/guide/db-migrations.md
index 5e070c61d7..97af74d337 100644
--- a/docs/guide/db-migrations.md
+++ b/docs/guide/db-migrations.md
@@ -608,7 +608,7 @@ class m160328_041642_create_junction_table_for_post_and_tag_tables extends Migra
```
Since 2.0.11 foreign key column names for junction tables are fetched from table schema.
-In case table isn't defined in schema, isn't set or is composite, default name `id` is used.
+In case table isn't defined in schema, or the primary key isn't set or is composite, default name `id` is used.
### Transactional Migrations
@@ -891,12 +891,11 @@ will be used to record the migration history. You no longer need to specify it v
command-line option.
-### Separated Migrations
+### Namespaced Migrations
-Sometimes you may need to use migrations from a different namespace. It can be some extension or module in your own
-project. One of such examples is migrations for [RBAC component](security-authorization.md#configuring-rbac).
-Since version 2.0.10 you can use [[yii\console\controllers\MigrateController::migrationNamespaces|migrationNamespaces]]
-to solve this task:
+Since 2.0.10 you can use namespaces for the migration classes. You can specify the list of the migration namespaces via
+[[yii\console\controllers\MigrateController::migrationNamespaces|migrationNamespaces]]. Using of the namespaces for
+migration classes allows you usage of the several source locations for the migrations. For example:
```php
return [
@@ -906,14 +905,36 @@ return [
'migrationNamespaces' => [
'app\migrations', // Common migrations for the whole application
'module\migrations', // Migrations for the specific project's module
- 'yii\rbac\migrations', // Migrations for the specific extension
+ 'some\extension\migrations', // Migrations for the specific extension
],
],
],
];
```
-If you want them to be applied and tracked down completely separated from each other, you can configure multiple
+> Note: migrations applied from different namespaces will create a **single** migration history, e.g. you might be
+ unable to apply or revert migrations from particular namespace only.
+
+While operating namespaced migrations: creating new, reverting and so on, you should specify full namespace before
+migration name. Note that backslash (`\`) symbol is usually considered a special character in the shell, so you need
+to escape it properly to avoid shell errors or incorrect behavior. For example:
+
+```
+yii migrate/create 'app\\migrations\\createUserTable'
+```
+
+> Note: migrations specified via [[yii\console\controllers\MigrateController::migrationPath|migrationPath]] can not
+ contain a namespace, namespaced migration can be applied only via [[yii\console\controllers\MigrateController::migrationNamespaces]]
+ property.
+
+
+### Separated Migrations
+
+Sometimes using single migration history for all project migrations is not desirable. For example: you may install some
+'blog' extension, which contains fully separated functionality and contain its own migrations, which should not affect
+the ones dedicated to main project functionality.
+
+If you want several migrations to be applied and tracked down completely separated from each other, you can configure multiple
migration commands which will use different namespaces and migration history tables:
```php
@@ -934,7 +955,7 @@ return [
// Migrations for the specific extension
'migrate-rbac' => [
'class' => 'yii\console\controllers\MigrateController',
- 'migrationNamespaces' => ['yii\rbac\migrations'],
+ 'migrationPath' => '@yii/rbac/migrations',
'migrationTable' => 'migration_rbac',
],
],
diff --git a/docs/guide/helper-array.md b/docs/guide/helper-array.md
index cbfbde38bd..1b0d9a30bc 100644
--- a/docs/guide/helper-array.md
+++ b/docs/guide/helper-array.md
@@ -398,7 +398,7 @@ Each mapping array contains a set of mappings. Each mapping could be:
- A key-value pair of desired array key name and model column name to take value from.
- A key-value pair of desired array key name and a callback which returns value.
-The result of conversion above will be:
+The result of conversion above for single model will be:
```php
diff --git a/docs/guide/images/start-gii-crud-preview.png b/docs/guide/images/start-gii-crud-preview.png
index 85c2355f2e..a8912e2829 100644
Binary files a/docs/guide/images/start-gii-crud-preview.png and b/docs/guide/images/start-gii-crud-preview.png differ
diff --git a/docs/guide/images/start-gii-crud.png b/docs/guide/images/start-gii-crud.png
index 77c1ada18a..948e6cd131 100644
Binary files a/docs/guide/images/start-gii-crud.png and b/docs/guide/images/start-gii-crud.png differ
diff --git a/docs/guide/images/start-gii-model-preview.png b/docs/guide/images/start-gii-model-preview.png
index 080be64b1f..3b6eb9f488 100644
Binary files a/docs/guide/images/start-gii-model-preview.png and b/docs/guide/images/start-gii-model-preview.png differ
diff --git a/docs/guide/images/start-gii-model.png b/docs/guide/images/start-gii-model.png
index 59c16a477e..9c506dee00 100644
Binary files a/docs/guide/images/start-gii-model.png and b/docs/guide/images/start-gii-model.png differ
diff --git a/docs/guide/input-forms.md b/docs/guide/input-forms.md
index 3fc2046121..2a93340a5e 100644
--- a/docs/guide/input-forms.md
+++ b/docs/guide/input-forms.md
@@ -141,6 +141,7 @@ $items = [
```
or by retrieval from the DB:
+
```php
$items = Category::find()
->select(['id', 'label'])
diff --git a/docs/guide/input-validation.md b/docs/guide/input-validation.md
index b02078b551..0828c70efc 100644
--- a/docs/guide/input-validation.md
+++ b/docs/guide/input-validation.md
@@ -331,7 +331,8 @@ the method/function is:
/**
* @param string $attribute the attribute currently being validated
* @param mixed $params the value of the "params" given in the rule
- * @param \yii\validators\InlineValidator related InlineValidator instance
+ * @param \yii\validators\InlineValidator related InlineValidator instance.
+ * This parameter is available since version 2.0.11.
*/
function ($attribute, $params, $validator)
```
@@ -562,266 +563,7 @@ As a result, we will not see error message near form fields. To display it, we c
= $form->errorSummary($model) ?>
```
-### Custom validator
-
-If passing one attribute is not acceptable for you (for example it can be hard to choose which one is more relevant or
-you consider it misleading in rules), the more advanced solution is to implement `CustomValidator` with support for
-validating multiple attributes at once.
-
-By default if multiple attributes are used for validation, the loop will be used to apply the same validation to each
-of them. Let's use a separate trait and override [[yii\base\Validator:validateAttributes()]]:
-
-```php
-attributes) || in_array('!' . $attribute, $this->attributes)) {
- $newAttributes[] = $attribute;
- }
- }
- $attributes = $newAttributes;
- } else {
- $attributes = [];
- foreach ($this->attributes as $attribute) {
- $attributes[] = $attribute[0] === '!' ? substr($attribute, 1) : $attribute;
- }
- }
-
- foreach ($attributes as $attribute) {
- $skip = $this->skipOnError && $model->hasErrors($attribute)
- || $this->skipOnEmpty && $this->isEmpty($model->$attribute);
- if ($skip) {
- // Skip validation if at least one attribute is empty or already has error
- // (according skipOnError and skipOnEmpty options must be set to true
- return;
- }
- }
-
- if ($this->batch) {
- // Validate all attributes at once
- if ($this->when === null || call_user_func($this->when, $model, $attribute)) {
- // Pass array with all attributes instead of one attribute
- $this->validateAttribute($model, $attributes);
- }
- } else {
- // Validate each attribute separately using the same validation logic
- foreach ($attributes as $attribute) {
- if ($this->when === null || call_user_func($this->when, $model, $attribute)) {
- $this->validateAttribute($model, $attribute);
- }
- }
- }
- }
-}
-```
-
-Then we need to create custom validator and use the created trait:
-
-```php
-hasMethod($type)) {
- // method-based validator
- // The following line is changed to use our CustomInlineValidator
- $params['class'] = __NAMESPACE__ . '\CustomInlineValidator';
- $params['method'] = $type;
- } else {
- if (isset(static::$builtInValidators[$type])) {
- $type = static::$builtInValidators[$type];
- }
- if (is_array($type)) {
- $params = array_merge($type, $params);
- } else {
- $params['class'] = $type;
- }
- }
-
- return Yii::createObject($params);
-}
-```
-
-And finally to support our custom validator in model we can create the trait and override
-[[\yii\base\Model::createValidators()]] like this:
-
-```php
-rules() as $rule) {
- if ($rule instanceof Validator) {
- $validators->append($rule);
- } elseif (is_array($rule) && isset($rule[0], $rule[1])) { // attributes, validator type
- // The following line is changed in order to use our CustomValidator
- $validator = CustomValidator::createValidator($rule[1], $this, (array) $rule[0], array_slice($rule, 2));
- $validators->append($validator);
- } else {
- throw new InvalidConfigException('Invalid validation rule: a rule must specify both attribute names and validator type.');
- }
- }
- return $validators;
- }
-}
-```
-
-Now we can implement custom validator by extending from `CustomValidator`:
-
-```php
-personalSalary + $this->spouseSalary;
- // Double the minimal adult funds if spouse salary is specified
- $minAdultFunds = $this->spouseSalary ? self::MIN_ADULT_FUNDS * 2 : self::MIN_ADULT_FUNDS;
- $childFunds = $totalSalary - $minAdultFunds;
- if ($childFunds / $this->childrenCount < self::MIN_CHILD_FUNDS) {
- $this->addError('*', 'Your salary is not enough for children.');
- }
- }
-}
-```
-
-Because `$attribute` contains the list of all related attributes, we can use loop in case of adding errors for all
-attributes is needed:
-
-```php
-foreach ($attribute as $singleAttribute) {
- $this->addError($attribute, 'Your salary is not enough for children.');
-}
-```
-
-Now it's possible to specify all related attributes in according validation rule:
-
-```php
-[
- ['personalSalary', 'spouseSalary', 'childrenCount'],
- \app\validators\ChildrenFundsValidator::className(),
- 'batch' => `true`,
- 'when' => function ($model) {
- return $model->childrenCount > 0;
- }
-],
-```
-
-For inline validation the rule will be:
-
-```php
-[
- ['personalSalary', 'spouseSalary', 'childrenCount'],
- 'validateChildrenFunds',
- 'batch' => `true`,
- 'when' => function ($model) {
- return $model->childrenCount > 0;
- }
-],
-```
-
-And here is according validation method:
-
-```php
-public function validateChildrenFunds($attribute, $params)
-{
- // $attribute here is not a single attribute, it's an array containing all related attributes
- $totalSalary = $this->personalSalary + $this->spouseSalary;
- // Double the minimal adult funds if spouse salary is specified
- $minAdultFunds = $this->spouseSalary ? self::MIN_ADULT_FUNDS * 2 : self::MIN_ADULT_FUNDS;
- $childFunds = $totalSalary - $minAdultFunds;
- if ($childFunds / $this->childrenCount < self::MIN_CHILD_FUNDS) {
- $this->addError('childrenCount', 'Your salary is not enough for children.');
- }
-}
-```
-
-The advantages of this approach:
-
-- It better reflects all attributes that participate in validation (the rules become more readable);
-- It respects the options [[yii\validators\Validator::skipOnError]] and [[yii\validators\Validator::skipOnEmpty]] for
-**each** used attribute (not only for that you decided to choose as more relevant).
-
-If you have problems with implementing client validation, you can:
-
-- combine [[yii\widgets\ActiveForm::enableAjaxValidation|enableClientValidation]] and
-[[yii\widgets\ActiveForm::enableAjaxValidation|enableAjaxValidation]] options, so multiple attributes will be validated
-with AJAX without page reload;
-- implement validation outside of [[yii\validators\Validator::clientValidateAttribute]] because it's designed to work
-with single attribute.
-
+> Note: Creating validator which validates multiple attributes at once is well described in the [community cookbook](https://github.com/samdark/yii2-cookbook/blob/master/book/forms-validator-multiple-attributes.md).
## Client-Side Validation
diff --git a/docs/guide/intro-upgrade-from-v1.md b/docs/guide/intro-upgrade-from-v1.md
index 6cb6f12f78..bce8f3c997 100644
--- a/docs/guide/intro-upgrade-from-v1.md
+++ b/docs/guide/intro-upgrade-from-v1.md
@@ -536,5 +536,5 @@ Using Yii 1.1 and 2.x together
------------------------------
If you have legacy Yii 1.1 code that you want to use together with Yii 2.0, please refer to
-the [Using Yii 1.1 and 2.0 Together](tutorial-yii-integration.md) section.
+the [Using Yii 1.1 and 2.0 Together](tutorial-yii-integration.md#using-both-yii2-yii1) section.
diff --git a/docs/guide/output-client-scripts.md b/docs/guide/output-client-scripts.md
index 35abe574f6..18f9e4413a 100644
--- a/docs/guide/output-client-scripts.md
+++ b/docs/guide/output-client-scripts.md
@@ -1,70 +1,84 @@
Working with Client Scripts
===========================
-> Note: This section is under development.
+Modern web applications, additionally to static HTML pages that are
+rendered and sent to the browser, contain JavaScript that is used
+to modify the page in the browser by manipulating existing elements or
+loading new content via AJAX.
+This section describes methods provided by Yii for adding JavaScript and CSS to a website as well as dynamically adjusting these.
-### Registering scripts
+## Registering scripts
-With the [[yii\web\View]] object you can register scripts. There are two dedicated methods for it:
-[[yii\web\View::registerJs()|registerJs()]] for inline scripts and
-[[yii\web\View::registerJsFile()|registerJsFile()]] for external scripts.
-Inline scripts are useful for configuration and dynamically generated code.
-The method for adding these can be used as follows:
+When working with the [[yii\web\View]] object you can dynamically register frontend scripts.
+There are two dedicated methods for this:
+
+- [[yii\web\View::registerJs()|registerJs()]] for inline scripts
+- [[yii\web\View::registerJsFile()|registerJsFile()]] for external scripts
+
+### Registering inline scripts
+
+Inline scripts are useful for configuration, dynamically generated code and small snippets created by reusable frontend code contained in [widgets](structure-widgets.md).
+The [[yii\web\View::registerJs()|registerJs()]] method for adding these can be used as follows:
```php
-$this->registerJs("var options = ".json_encode($options).";", View::POS_END, 'my-options');
+$this->registerJs(
+ "$('#myButton').on('click', function() { alert('Button clicked!'); });",
+ View::POS_READY,
+ 'my-button-handler'
+);
```
-The first argument is the actual JS code we want to insert into the page. The second argument
-determines where script should be inserted into the page. Possible values are:
+The first argument is the actual JS code we want to insert into the page.
+It will be wrapped into a `