Browse Source

Merge branch 'master' into 2.1

# Conflicts:
#	composer.json
#	docs/guide-ja/output-client-scripts.md
#	framework/caching/XCache.php
#	tests/framework/validators/UniqueValidatorTest.php
#	tests/framework/web/UrlManagerTest.php
tags/3.0.0-alpha1
Alexander Makarov 8 years ago
parent
commit
0aca17dcfb
No known key found for this signature in database
GPG Key ID: 3617B79C6A325E4A
  1. 8
      .gitattributes
  2. 22
      build/controllers/ReleaseController.php
  3. 1
      composer.json
  4. 16
      docs/guide-ja/README.md
  5. 2
      docs/guide-ja/concept-components.md
  6. 58
      docs/guide-ja/db-migrations.md
  7. 2
      docs/guide-ja/intro-yii.md
  8. 220
      docs/guide-ja/output-client-scripts.md
  9. 2
      docs/guide-ja/output-data-providers.md
  10. 40
      docs/guide-ja/output-data-widgets.md
  11. 2
      docs/guide-ja/output-formatting.md
  12. 2
      docs/guide-ja/rest-authentication.md
  13. 7
      docs/guide-ja/rest-quick-start.md
  14. 2
      docs/guide-ja/rest-rate-limiting.md
  15. 37
      docs/guide-ja/rest-resources.md
  16. 2
      docs/guide-ja/rest-routing.md
  17. 8
      docs/guide-ja/runtime-handling-errors.md
  18. 5
      docs/guide-ja/runtime-responses.md
  19. 183
      docs/guide-ja/runtime-routing.md
  20. 4
      docs/guide-ja/runtime-sessions-cookies.md
  21. 4
      docs/guide-ja/security-authorization.md
  22. 43
      docs/guide-ja/security-best-practices.md
  23. 2
      docs/guide-ja/start-forms.md
  24. 2
      docs/guide-ja/start-gii.md
  25. 4
      docs/guide-ja/start-installation.md
  26. 107
      docs/guide-ja/structure-assets.md
  27. 2
      docs/guide-ja/structure-controllers.md
  28. 2
      docs/guide-ja/structure-filters.md
  29. 4
      docs/guide-ja/structure-models.md
  30. 2
      docs/guide-ja/structure-modules.md
  31. 2
      docs/guide-ja/structure-views.md
  32. 4
      docs/guide-ja/test-overview.md
  33. 99
      docs/guide-ja/tutorial-core-validators.md
  34. 19
      docs/guide-ja/tutorial-mailing.md
  35. 4
      docs/guide-ja/tutorial-performance-tuning.md
  36. 2
      docs/guide-ru/README.md
  37. 2
      docs/guide-ru/concept-di-container.md
  38. 2
      docs/guide-ru/db-active-record.md
  39. 2
      docs/guide/db-active-record.md
  40. 20
      docs/guide/db-migrations.md
  41. 8
      docs/guide/output-client-scripts.md
  42. 10
      docs/guide/output-data-widgets.md
  43. 2
      docs/guide/runtime-routing.md
  44. 2
      docs/guide/runtime-sessions-cookies.md
  45. 10
      docs/guide/structure-assets.md
  46. 4
      docs/guide/tutorial-core-validators.md
  47. 11
      docs/internals/git-workflow.md
  48. 2
      framework/BaseYii.php
  49. 55
      framework/CHANGELOG.md
  50. 404
      framework/assets/yii.js
  51. 1
      framework/base/Application.php
  52. 2
      framework/base/Controller.php
  53. 3
      framework/base/Module.php
  54. 101
      framework/base/Widget.php
  55. 30
      framework/base/WidgetEvent.php
  56. 2
      framework/caching/Dependency.php
  57. 2
      framework/caching/ExpressionDependency.php
  58. 2
      framework/caching/MemCacheServer.php
  59. 2
      framework/caching/WinCache.php
  60. 4
      framework/classes.php
  61. 1
      framework/console/UnknownCommandException.php
  62. 133
      framework/console/controllers/MessageController.php
  63. 4
      framework/data/BaseDataProvider.php
  64. 10
      framework/data/Pagination.php
  65. 2
      framework/db/ActiveRelationTrait.php
  66. 2
      framework/db/ColumnSchema.php
  67. 4
      framework/db/Command.php
  68. 7
      framework/db/Connection.php
  69. 64
      framework/db/QueryBuilder.php
  70. 2
      framework/db/QueryInterface.php
  71. 4
      framework/db/QueryTrait.php
  72. 1
      framework/db/Schema.php
  73. 4
      framework/db/Transaction.php
  74. 42
      framework/db/mysql/QueryBuilder.php
  75. 42
      framework/db/oci/QueryBuilder.php
  76. 9
      framework/db/pgsql/QueryBuilder.php
  77. 10
      framework/di/Container.php
  78. 12
      framework/filters/AccessRule.php
  79. 14
      framework/grid/ActionColumn.php
  80. 2
      framework/helpers/BaseHtml.php
  81. 2
      framework/helpers/BaseStringHelper.php
  82. 3
      framework/log/Logger.php
  83. 1
      framework/log/SyslogTarget.php
  84. 3
      framework/messages/de/yii.php
  85. 3
      framework/messages/el/yii.php
  86. 3
      framework/messages/fa/yii.php
  87. 3
      framework/messages/ja/yii.php
  88. 3
      framework/messages/ru/yii.php
  89. 3
      framework/messages/sk/yii.php
  90. 2
      framework/rbac/CheckAccessInterface.php
  91. 2
      framework/rest/DeleteAction.php
  92. 4
      framework/rest/IndexAction.php
  93. 12
      framework/rest/UrlRule.php
  94. 2
      framework/rest/ViewAction.php
  95. 2
      framework/test/FixtureTrait.php
  96. 2
      framework/validators/ExistValidator.php
  97. 36
      framework/validators/UniqueValidator.php
  98. 12
      framework/web/CompositeUrlRule.php
  99. 2
      framework/web/ErrorAction.php
  100. 2
      framework/web/RangeNotSatisfiableHttpException.php
  101. Some files were not shown because too many files have changed in this diff Show More

8
.gitattributes vendored

@ -22,17 +22,15 @@
*.gif binary
*.ttf binary
# Ignore all test and documentation for archive
# Ignore some meta files when creating an archive of this repository
# We do not ignore any content, because this repo represents the
# `yiisoft/yii2-dev` package, which is expected to ship all tests and docs.
/.github export-ignore
/.editorconfig export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.scrutinizer.yml export-ignore
/.travis.yml export-ignore
/phpunit.xml.dist export-ignore
/tests export-ignore
/docs export-ignore
/build export-ignore
# Avoid merge conflicts in CHANGELOG
# https://about.gitlab.com/2015/02/10/gitlab-reduced-merge-conflicts-by-90-percent-with-changelog-placeholders/

22
build/controllers/ReleaseController.php

@ -212,13 +212,15 @@ class ReleaseController extends Controller
$this->stdout("\n");
$this->stdout("Before you make a release briefly go over the changes and check if you spot obvious mistakes:\n\n", Console::BOLD);
$gitDir = reset($what) === 'framework' ? 'framework/' : '';
$gitVersion = $versions[reset($what)];
if (strncmp('app-', reset($what), 4) !== 0) {
$this->stdout("- no accidentally added CHANGELOG lines for other versions than this one?\n");
$this->stdout("- no accidentally added CHANGELOG lines for other versions than this one?\n\n git diff $gitVersion.. ${gitDir}CHANGELOG.md\n\n");
$this->stdout("- are all new `@since` tags for this relase version?\n");
}
$this->stdout("- other issues with code changes?\n\n git diff -w $gitVersion.. ${gitDir}\n\n");
$travisUrl = reset($what) === 'framework' ? '' : '-'.reset($what);
$this->stdout("- are unit tests passing on travis? https://travis-ci.org/yiisoft/yii2$travisUrl/builds\n");
$this->stdout("- other issues with code changes?\n");
$this->stdout("- also make sure the milestone on github is complete and no issues or PRs are left open.\n\n");
$this->printWhatUrls($what, $versions);
$this->stdout("\n");
@ -527,6 +529,12 @@ class ReleaseController extends Controller
$this->stdout("\n\nThe following steps are left for you to do manually:\n\n");
$nextVersion2 = $this->getNextVersions($nextVersion, self::PATCH); // TODO support other versions
$this->stdout("- wait for your changes to be propagated to the repo and create a tag $version on https://github.com/yiisoft/yii2-framework\n\n");
$this->stdout(" git clone git@github.com:yiisoft/yii2-framework.git\n");
$this->stdout(" cd yii2-framework/\n");
$this->stdout(" export RELEASECOMMIT=$(git log --oneline |grep $version |grep -Po \"^[0-9a-f]+\")\n");
$this->stdout(" git tag -s $version -m \"version $version\" \$RELEASECOMMIT\n");
$this->stdout(" git tag --verify $version\n");
$this->stdout(" git push --tags\n\n");
$this->stdout("- close the $version milestone on github and open new ones for {$nextVersion['framework']} and {$nextVersion2['framework']}: https://github.com/yiisoft/yii2/milestones\n");
$this->stdout("- create a release on github.\n");
$this->stdout("- release news and announcement.\n");
@ -861,7 +869,13 @@ class ReleaseController extends Controller
if ($state === 'changelog' && isset($lines[$l+1]) && strncmp($lines[$l+1], '---', 3) === 0) {
$state = 'end';
}
${$state}[] = $line;
// add continued lines to the last item to keep them together
if (!empty(${$state}) && trim($line !== '') && strpos($line, '- ') !== 0) {
end(${$state});
${$state}[key(${$state})] .= "\n" . $line;
} else {
${$state}[] = $line;
}
}
return [$start, $changelog, $end];
}
@ -879,7 +893,7 @@ class ReleaseController extends Controller
$i = 0;
ArrayHelper::multisort($changelog, function($line) use (&$i) {
if (preg_match('/^- (Chg|Enh|Bug|New)( #\d+(, #\d+)*)?: .+$/', $line, $m)) {
if (preg_match('/^- (Chg|Enh|Bug|New)( #\d+(, #\d+)*)?: .+/', $line, $m)) {
$o = ['Bug' => 'C', 'Enh' => 'D', 'Chg' => 'E', 'New' => 'F'];
return $o[$m[1]] . ' ' . (!empty($m[2]) ? $m[2] : 'AAAA' . $i++);
}

1
composer.json

@ -76,6 +76,7 @@
"ezyang/htmlpurifier": "~4.6",
"cebe/markdown": "~1.0.0 | ~1.1.0",
"bower-asset/jquery": "2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable",
"bower-asset/jquery.inputmask": "~3.2.2 | ~3.3.3",
"bower-asset/punycode": "1.3.*",
"bower-asset/yii2-pjax": "~2.0.1"
},

16
docs/guide-ja/README.md

@ -178,14 +178,14 @@ RESTful ウェブサービス
ウィジェット
------------
* GridView: **未定** デモページへリンク
* ListView: **未定** デモページへリンク
* DetailView: **未定** デモページへリンク
* ActiveForm: **未定** デモページへリンク
* Pjax: **未定** デモページへリンク
* Menu: **未定** デモページへリンク
* LinkPager: **未定** デモページへリンク
* LinkSorter: **未定** デモページへリンク
* [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-ja/README.md)
* [jQuery UI ウィジェット](https://github.com/yiisoft/yii2-jui/blob/master/docs/guide-ja/README.md)

2
docs/guide-ja/concept-components.md

@ -9,7 +9,7 @@
* [ビヘイビア](concept-behaviors.md)
個々にでも、組み合わせでも、これらの機能は Yii のクラスのカスタマイズ性と使いやすさをとても高めてくれます。たとえば、[[yii\jui\DatePicker|日付選択]] を行うユーザインターフェース·コンポーネントは、
対話型の日付選択UIを生成するとき、[ビュー](structure-view.md) で次のように使用することができます:
対話型の日付選択UIを生成するとき、[ビュー](structure-views.md) で次のように使用することができます:
```php
use yii\jui\DatePicker;

58
docs/guide-ja/db-migrations.md

@ -183,7 +183,7 @@ class m150101_185401_create_news_table extends Migration
### テーブルの作成
```php
```
yii migrate/create create_post_table
```
@ -217,7 +217,7 @@ class m150811_220037_create_post_table extends Migration
テーブルのフィールドも直接に生成したい場合は、`--fields` オプションでフィールドを指定します。
```php
```
yii migrate/create create_post_table --fields="title:string,body:text"
```
@ -254,7 +254,7 @@ class m150811_220037_create_post_table extends Migration
さらに多くのフィールド・パラメータを指定することも出来ます。
```php
```
yii migrate/create create_post_table --fields="title:string(12):notNull:unique,body:text"
```
@ -296,7 +296,7 @@ class m150811_220037_create_post_table extends Migration
バージョン 2.0.8 からは、`foreignKey` キーワードを使って外部キーを生成することができます。
```php
```
yii migrate/create create_post_table --fields="author_id:integer:notNull:foreignKey(user),category_id:integer:defaultValue(1):foreignKey,title:string,body:text"
```
@ -417,7 +417,7 @@ class m160328_040430_create_post_table extends Migration
### テーブルを削除する
```php
```
yii migrate/create drop_post_table --fields="title:string(12):notNull:unique,body:text"
```
@ -448,7 +448,7 @@ class m150811_220037_drop_post_table extends Migration
カラムを追加するためには、次のようにします。
```php
```
yii migrate/create add_position_column_to_post_table --fields="position:integer"
```
@ -469,11 +469,17 @@ class m150811_220037_add_position_column_to_post_table extends Migration
}
```
次のようにして複数のカラムを指定することも出来ます。
```
yii migrate/create add_xxx_column_yyy_column_to_zzz_table --fields="xxx:integer,yyy:text"
```
### カラムを削除する
マイグレーションの名前が `drop_xxx_column_from_yyy_table` の形式である場合、ファイルの内容は、必要となる `addColumn``dropColumn` を含むことになります。
```php
```
yii migrate/create drop_position_column_from_post_table --fields="position:integer"
```
@ -498,7 +504,7 @@ class m150811_220037_drop_position_column_from_post_table extends Migration
マイグレーションの名前が `create_junction_table_for_xxx_and_yyy_tables` の形式である場合は、中間テーブルを作成するのに必要となるコードが生成されます。
```php
```
yii migrate/create create_junction_table_for_post_and_tag_tables --fields="created_at:dateTime"
```
@ -869,11 +875,12 @@ return [
もう、`migrationTable` のコマンドラインオプションを使ってテーブルを指定する必要はなくなります。
### Namespaced Migrations <span id="namespaced-migrations"></span>
### 名前空間を持つマイグレーション <span id="namespaced-migrations"></span>
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:
2.0.10 以降では、マイグレーションのクラスに名前空間を適用することが出来ます。
マイグレーションの名前空間のリストをを [[yii\console\controllers\MigrateController::migrationNamespaces|migrationNamespaces]] によって指定することが出来ます。
マイグレーションのクラスに名前空間を使うと、マイグレーションのソースについて、複数の配置場所を使用することが出来ます。
例えば、
```php
return [
@ -881,36 +888,35 @@ return [
'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
'app\migrations', // アプリケーション全体のための共通のマイグレーション
'module\migrations', // プロジェクトの特定のモジュールのためのマイグレーション
               'some\extension\migrations', // 特定のエクステンションのためのマイグレーション
],
],
],
];
```
> 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.
> Note: 異なる名前空間に属するマイグレーションを適用しても、**単一の** マイグレーション履歴が生成されます。
> つまり、特定の名前空間に属するマイグレーションだけを適用したり元に戻したりすることは出来ません。
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.
> Note: [[yii\console\controllers\MigrateController::migrationPath|migrationPath]] によって指定されたマイグレーションは、名前空間を持つことが出来ません。
名前空間を持つマイグレーションは [[yii\console\controllers\MigrateController::migrationNamespaces]] プロパティを通じてのみ適用可能です。
### 分離されたマイグレーション <span id="separated-migrations"></span>
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.
プロジェクトのマイグレーション全体に単一のマイグレーション履歴を使用することが望ましくない場合もあります。
例えば、完全に独立した機能性とそれ自身のためのマイグレーションを持つような 'blog' エクステンションをインストールする場合には、
メインのプロジェクトの機能専用のマイグレーションに影響を与えたくないでしょう。
これらをお互いに完全に分離して適用かつ追跡したい場合は、別々の名前空間とマイグレーション履歴テーブルを使う
複数のマイグレーションコマンドを構成することが出来ます。

2
docs/guide-ja/intro-yii.md

@ -46,7 +46,7 @@ Yii は現在、利用可能な二つのメジャーバージョン、すなわ
必要条件と前提条件
------------------
Yii 2.0 は PHP 5.4.0 以上を必要とします。
Yii 2.0 は PHP 5.4.0 以上を必要とし、PHP 7 の最新バージョンで最高の力を発揮します。
個々の機能に対する詳細な必要条件は、全ての Yii リリースに含まれている必要条件チェッカを走らせることによって知ることが出来ます。
Yii を使うためには、オブジェクト指向プログラミング (OOP) の基本的な知識が必要です。

220
docs/guide-ja/output-client-scripts.md

@ -1,98 +1,216 @@
クライアントスクリプトを扱う
============================
> Note: この節はまだ執筆中です。
今日のウェブアプリケーションでは、静的な HTML ページがレンダリングされてブラウザに送信されるだけでなく、
JavaScript によって、既存の要素を操作したり、新しいコンテントを AJAX でロードしたりして、ブラウザに表示されるページを修正します。
この節では、JavaScript と CSS をウェブサイトに追加したり、それらを動的に調整するために Yii によって提供されているメソッドを説明します。
### スクリプトを登録する
## スクリプトを登録する <span id="register-scripts"></span>
[[yii\web\View]] オブジェクトに対してスクリプトを登録することが出来ます。
[[yii\web\View]] オブジェクトを扱う際には、フロントエンドスクリプトを動的に登録することが出来ます。
このための専用のメソッドが二つあります。
すなわち、インラインスクリプトのための [[yii\web\View::registerJs()|registerJs()]] と、外部スクリプトのための [[yii\web\View::registerJsFile()|registerJsFile()]] です。
インラインスクリプトは、設定のためや、動的に生成されるコードのために有用なものです。
次のようにして、これらを追加するメソッドを使うことが出来ます。
- インラインスクリプトのための [[yii\web\View::registerJs()|registerJs()]]
- 外部スクリプトのための [[yii\web\View::registerJsFile()|registerJsFile()]]
### インラインスクリプトを登録する <span id="inline-scripts"></span>
インラインスクリプトは、設定や、動的に生成されるコードのために有用なものです。
また、[ウィジェット](structure-widgets.md) に含まれる再利用可能なフロントエンドコードによって生成されるコード断片もインラインスクリプトです。
インラインスクリプトを追加するためのメソッド [[yii\web\View::registerJs()|registerJs()]] は、次のようにして使うことが出来ます。
```php
$this->registerJs("var options = ".json_encode($options).";", View::POS_END, 'my-options');
$this->registerJs(
"$('#myButton').on('click', function() { alert('ボタンがクリックされました'); });",
View::POS_READY,
'my-button-handler'
);
```
最初の引数は、ページに挿入したい実際の JS コードです。
二番目の引数は、スクリプトがページのどの場所に挿入されるべきかを決定します。
最初の引数は、ページに挿入したい実際の JS コードです。これが `<script>` タグに包まれて挿入されます。
二番目の引数は、スクリプトがページのどの位置に挿入されるべきかを決定します。
取りうる値は以下のとおりです。
- [[yii\web\View::POS_HEAD|View::POS_HEAD]] - head セクション。
- [[yii\web\View::POS_BEGIN|View::POS_BEGIN]] - 開始の `<body>` の直後。
- [[yii\web\View::POS_END|View::POS_END]] - 終了の `</body>` の直前。
- [[yii\web\View::POS_READY|View::POS_READY]] - ドキュメントの `ready` イベントで実行するコード。これを指定すると、[[yii\web\JqueryAsset|jQuery]] が自動的に登録されます。
- [[yii\web\View::POS_LOAD|View::POS_LOAD]] - ドキュメントの `load` イベントで実行するコード。これを指定すると、[[yii\web\JqueryAsset|jQuery]] が自動的に登録されます。
最後の引数は、スクリプトのユニークな ID です。これによってコードブロックを一意に特定し、同じ ID のスクリプトが既にある場合は、新しいものを追加するのでなく、それを置き換えます。
- [[yii\web\View::POS_READY|View::POS_READY]] - [ドキュメントの `ready` イベント](http://learn.jquery.com/using-jquery-core/document-ready/) でコードを実行するための指定。
これを指定すると、[[yii\web\JqueryAsset|jQuery]] が自動的に登録され、コードは適切な jQuery コードの中に包まれます。
これがデフォルトの位置指定です。
- [[yii\web\View::POS_LOAD|View::POS_LOAD]] - [ドキュメントの `load` イベント](http://learn.jquery.com/using-jquery-core/document-ready/) でコードを実行するための指定。
上記と同じく、これを指定すると、[[yii\web\JqueryAsset|jQuery]] が自動的に登録されます。
最後の引数は、スクリプトのコードブロックを一意に特定するために使われるスクリプトのユニークな ID です。
同じ ID のスクリプトが既にある場合は、新しいものを追加するのでなく、それを置き換えます。
ID を指定しない場合は、JS コードそれ自身が ID として扱われます。
この ID によって、同じコードが複数回登録されるのを防止します。
### スクリプトファイルを登録する <span id="script-files"></span>
[[yii\web\View::registerJsFile()|registerJsFile()]] の引数は、[[yii\web\View::registerCssFile()|registerCssFile()]] の引数と同様なものです。
以下に示す例では、`main.js` ファイルを、[[yii\web\JqueryAsset]] への依存関係とともに、登録します。
これは、`main.js` ファイルは `jquery.js` の後に追加される、ということを意味します。
このような依存関係の仕様が無ければ、`main.js` と `jquery.js` の間の相対的な順序は未定義となり、コードは動作しなくなるでしょう。
外部スクリプトは次のようにして追加することが出来ます。
```php
$this->registerJsFile('http://example.com/js/main.js', ['depends' => [\yii\web\JqueryAsset::class]]);
$this->registerJsFile(
'@web/js/main.js',
['depends' => [\yii\web\JqueryAsset::class]]
);
```
これによって、アプリケーションの [base URL](concept-aliases.md#predefined-aliases) の下に配置されている `/js/main.js` スクリプトを読み込むタグが追加されます。
ただし、外部 JS ファイルを登録するのには、 [[yii\web\View::registerJsFile()|registerJsFile()]] を使わずに、[アセットバンドル](structure-assets.md) を使うことが強く推奨されます。
なぜなら、そうする方が、柔軟性も高く、依存関係の構成も粒度を細かく出来るからです。
また、アセットバンドルを使えば、複数の JS ファイルを結合して圧縮すること
(アクセスの多いウェブサイトではそうすることが望まれます) が可能になります。
## CSS を登録する <span id="register-css"></span>
Javascript と同様に、[[yii\web\View::registerCss()|registerCss()]]
または [[yii\web\View::registerCssFile()|registerCssFile()]] を使って CSS を登録することが出来ます。
前者は CSS のコードブロックを登録し、後者は外部 CSS ファイルを登録するものです。
### インライン CSS を登録する <span id="inline-css"></span>
```php
$this->registerCss("body { background: #f00; }");
```
[[yii\web\View::registerJsFile()|registerJsFile()]] の引数は [[yii\web\View::registerCssFile()|registerCssFile()]] のそれと同じです。
上記の例では、`main.js` ファイルを `JqueryAsset` に依存するものとして登録しています。
これは、`main.js` ファイルが `jquery.js` の後に追加されるようになることを意味します。
この依存関係を指定しない場合は、`main.js` と `jquery.js` の相対的な順序は未定義となります。
上記のコードによって、結果として、下記の出力がページの `<head>` セクションに追加されます。
[[yii\web\View::registerCssFile()|registerCssFile()]] と同じように、外部 JS ファイルを登録するのに [[yii\web\View::registerJsFile()|registerJsFile()]] を使わずに、[アセットバンドル](structure-assets.md) を使うことが強く推奨されます。
```html
<style>
body { background: #f00; }
</style>
```
`style` タグに追加の属性を指定したい場合は、名前-値 の配列を二番目の引数として渡します。
最後の引数は、スタイルのブロックを一意に特定するために使われるユニークな ID です。
同じスタイルがコードの別の箇所で重複して登録されたとしても、このスタイルのブロックが一度だけ追加されることを保証するものです。
### アセットバンドルを登録する
### CSS ファイルを登録する <span id="css-files"></span>
既に述べたように、CSS と JavaScript を直接に使う代りにアセットバンドルを使うことが望まれます。
アセットバンドルを定義する方法の詳細は、ガイドの [アセットマネージャ](structure-assets.md) の節で知ることが出来ます。
既に定義されているアセットバンドルを使うことについては、次のように非常に簡明です。
CSS ファイルは次のようにして登録することが出来ます。
```php
$this->registerCssFile("@web/css/themes/black-and-white.css", [
'depends' => [\yii\bootstrap\BootstrapAsset::className()],
'media' => 'print',
], 'css-print-theme');
```
上記のコードは `/css/themes/black-and-white.css` という CSS ファイルに対するリンクをページの `<head>` セクションに追加します。
* 最初の引数が、登録される CSS ファイルを指定します。
この例における `@web` in this example is an [アプリケーションのベース URL に対するエイリアス](concept-aliases.md#predefined-aliases) です。
* 二番目の引数は、結果として出力される `<link>` タグの HTML 属性を指定するものです。
ただし、`depends` というオプションは特別な処理を受けます。
これは、この CSS ファイルが依存するアセットバンドルを指定するものです。
この例の場合は、[[yii\bootstrap\BootstrapAsset|BootstrapAsset]] が依存するアセットバンドルです。
これは、この CSS ファイルが [[yii\bootstrap\BootstrapAsset|BootstrapAsset]] に属する CSS ファイルの*後に*追加されることを意味します。
* 最後の引数はこの CSS ファイルを特定する ID を指定するものです。
省略された場合は、CSS ファイルの URL が代りに ID として使用されます。
外部 CSS ファイルを登録するのには、 [[yii\web\View::registerCssFile()|registerCssFile()]] を使わずに、[アセットバンドル](structure-assets.md) を使うことが強く推奨されます。
アセットバンドルを使えば、複数の CSS ファイルを結合して圧縮すること
(アクセスの多いウェブサイトではそうすることが望まれます) が可能になります。
また、アプリケーションの全てのアセットの依存関係を一ヶ所で構成することが出来るため、
より大きな柔軟性を得ることが出来ます。
## アセットバンドルを登録する <span id="asset-bundles"></span>
既に述べたように、CSS ファイルと JavaScript ファイルを直接に登録する代りにアセットバンドルを使うことが推奨されます。
アセットバンドルを定義する方法の詳細は、ガイドの [アセット](structure-assets.md) の節で知ることが出来ます。
既に定義されているアセットバンドルの使い方は、次のように非常に単純明快です。
```php
\frontend\assets\AppAsset::register($this);
```
上記のコードでは、ビューファイルのコンテキストにおいて、`AppAsset` バンドルが (`$this` で表される) 現在のビューに対して登録されています。
ウィジェットの中からアセットバンドルを登録するときは、ウィジェットの [[yii\base\Widget::$view|$view]]
を代りに渡します (`$this->view`)。
## 動的な Javascript を生成する <span id="dynamic-js"></span>
### CSS を登録する
ビューファイルでは、HTML コードが直接に書き出されのではなく、ビューの変数に依存して、PHP のコードによって生成されることがよくあります。
生成された HTML を Javascript によって操作するためには、JS コードも同様に動的な部分を含まなければなりません。
例えば、jQuery セレクタの ID などがそうです。
、ビューの変数にIn view files often the HTML code is not written out directl
PHP の変数を JS コードに挿入するためには、変数の値を適切にエスケープする必要があります。
JS コードを専用の JS ファイルの中に置くのではなく、HTML に挿入する場合は特にそうです。
Yii は、この目的のために、[[yii\helpers\Json|Json]] ヘルパの [[yii\helpers\Json::htmlEncode()|htmlEncode()]] メソッドを提供しています。
その使用方法は、以下の例の中で示されています。
[[yii\web\View::registerCss()|registerCss()]] または [[yii\web\View::registerCssFile()|registerCssFile()]] を使って CSS を登録することが出来ます。
前者は CSS のコードブロックを登録し、後者は外部 CSS ファイルを登録します。
例えば、
### グローバルな JavaScript の構成情報を登録する <span id="js-configuration"></span>
この例では、配列を使って、グローバルな構成情報のパラメータをアプリケーションの
PHP のパートから JS のフロントエンドコードに渡します。
```php
$this->registerCss("body { background: #f00; }");
$options = [
'appName' => Yii::$app->name,
'baseUrl' => Yii::$app->request->baseUrl,
'language' => Yii::$app->language,
// ...
];
$this->registerJs(
"var yiiOptions = ".\yii\helpers\Json::htmlEncode($options).";",
View::POS_HEAD,
'yiiOptions'
);
```
上記のコードは、以下の内容をページの head セクションに追加する結果となります。
上記のコードは、次のような JavaScript の変数定義を含む `<script>` タグを登録します。
```html
<style>
body { background: #f00; }
</style>
```javascript
var yiiOptions = {"appName":"My Yii Application","baseUrl":"/basic/web","language":"en"};
```
`style` タグに追加のプロパティを指定したい場合は、三番目の引数として「名前-値」のペアの配列を渡します。
`style` タグが一つだけになることを保証する必要がある場合は、メタタグの説明で言及したように、4番目の引数を使います。
このようにすれば、あなたの Javascript コードで、これらの構成情報に `yiiOptions.baseUrl``yiiOptions.language`
のようにしてアクセスすることが出来るようになります。.
### 翻訳されたメッセージを渡す <span id="translated-messages"></span>
あなたの JavaScript が何らかのイベントに反応してメッセージを表示する必要がある、という状況に遭遇するかも知れません。
複数の言語で動作するアプリケーションでは、この文字列は、現在のアプリケーシの言語に翻訳されなければなりません。
これを達成する一つの方法は、Yii によって提供されている [メッセージ翻訳機能] (tutorial-i18n.md#message-translation)
を使って、その結果を JavaScript コードに渡すことです。
```php
$this->registerCssFile("http://example.com/css/themes/black-and-white.css", [
'depends' => [BootstrapAsset::class],
'media' => 'print',
], 'css-print-theme');
$message = \yii\helpers\Json::htmlEncode(
\Yii::t('app', 'Button clicked!')
);
$this->registerJs(<<<JS
$('#myButton').on('click', function() { alert( $message ); });",
JS
);
```
上記のコードは、ページの head セクションに CSS ファイルへのリンクを追加します。
上記のサンプルコードは、可読性を高めるために、PHP の [ヒアドキュメント構文](http://php.net/manual/ja/language.types.string.php#language.types.string.syntax.heredoc) を使っています。
また、ヒアドキュメントは、たいていの IDE で、より良い構文ハイライトが可能にしてくれるので、
インライン JavaScript、特に一行に収まらないものを書くときに推奨される方法です。
変数 `$message` は PHP で生成され、[[yii\helpers\Json::htmlEncode|Json::htmlEncode]] のおかげで、適切な JS 構文の文字列を含むものになります。
それを JavaScript コードに挿入して、`alert()` の関数呼び出しに動的な文字列を渡すことが出来ます。
> Note: ヒアドキュメントを使う場合は、JS コード中の変数名に注意してください。
> `$` で始まる変数は、PHP の変数として解釈され、その値によって置き換えられる可能性があります。
> ただし、`$(` または `$.` という形式の jQuery 関数は PHP 変数として解釈される心配は無く、安全に使うことが出来ます。
## `yii.js` スクリプト <span id="yii.js"></span>
* 最初の引数が登録されるべき CSS ファイルを指定します。
* 二番目の引数は、結果として生成される `<link>` タグの HTML 属性を指定するものです。
ただし、`depends` オプションは特別な処理を受けます。
このオプションは、この CSS ファイルが依存するアセットバンドルを指定するものです。
この例では、依存するアセットバンドルは [[yii\bootstrap\BootstrapAsset|BootstrapAsset]] です。
これは、この CSS ファイルが、[[yii\bootstrap\BootstrapAsset|BootstrapAsset]] に含まれる CSS ファイルの *後* に追加されることを意味します。
* 最後の引数は、この CSS ファイルを特定するための ID を指定するものです。
指定されていない場合は、CSS ファイルの URL が代りに ID として使用されます。
> Note: このセクションはまだ書かれていません。
> このセクションは、`yii.js` によって提供される以下の機能についての説明を含むはずのものです。
>
> - Yii JavaScript モジュール
> - CSRF パラメータの処理
> - `data-confirm` ハンドラ
> - `data-method` ハンドラ
> - スクリプトのフィルタリング
> - リダイレクトの処理
外部 CSS ファイルを登録するためには、[[yii\web\View::registerCssFile()|registerCssFile()]] を使うのではなく、[アセットバンドル](structure-assets.md) を使うことが強く推奨されます。
アセットバンドルを使うと、複数の CSS ファイルを結合して圧縮することが可能になります。
トラフィックの多いウェブサイトではそうすることが望まれます。

2
docs/guide-ja/output-data-providers.md

@ -34,7 +34,7 @@ $totalCount = $provider->getTotalCount();
データプロバイダのページネーションと並べ替えの振る舞いを指定するためには、その [[yii\data\BaseDataProvider::pagination|pagination]] と [[yii\data\BaseDataProvider::sort|sort]] のプロパティを構成します。
二つのプロパティは、それぞれ、[[yii\data\Pagination]] と [[yii\data\Sort]] の構成情報に対応します。
これらを false に設定して、ページネーションや並べ替えの機能を無効にすることも出来ます。
これらを `false` に設定して、ページネーションや並べ替えの機能を無効にすることも出来ます。
[データウィジェット](output-data-widgets.md)、例えば [[yii\grid\GridView]] は、`dataProvider` という名前のプロパティを持っており、これにデータプロバイダのインスタンスを受け取らせて、それが提供するデータを表示させることが出来ます。
例えば、

40
docs/guide-ja/output-data-widgets.md

@ -6,7 +6,7 @@ Yii はデータを表示するために使うことが出来る一連の [ウ
それに対して、[ListView](#list-view) と [GridView](#grid-view) は、複数のデータレコードをリストまたはテーブルで表示することが出来るもので、ページネーション、並べ替え、フィルタリングなどの機能を提供するものです。
DetailView
DetailView <a name="detail-view"></a>
----------
DetailView は単一のデータ [[yii\widgets\DetailView::$model|モデル]] の詳細を表示します。
@ -23,19 +23,42 @@ DetailView は [[yii\widgets\DetailView::$attributes]] プロパティを使っ
echo DetailView::widget([
'model' => $model,
'attributes' => [
'title', // title 属性 (平文テキストで)
'description:html', // description 属性は HTML としてフォーマットされる
[ // モデルの所有者の名前
'title', // title 属性 (平文テキストで)
'description:html', // description 属性は HTML としてフォーマットされる
[ // モデルの所有者の名前
'label' => '所有者',
'value' => $model->owner->name,
'contentOptions' => ['class' => 'bg-red'], // 値のタグをカスタマイズする HTML 属性
'captionOptions' => ['tooltip' => 'Tooltip'], // ラベルのタグをカスタマイズする HTML 属性
],
'created_at:datetime', // 作成日は datetime としてフォーマットされる
'created_at:datetime', // 作成日は datetime としてフォーマットされる
],
]);
```
[[yii\widgets\GridView|GridView]] が一組のモデルを処理するのとは異なって、
[[yii\widgets\DetailView|DetailView]] は一つのモデルしか処理しないということを覚えておいてください。
表示すべきモデルはビューの変数としてアクセスできる `$model` 一つだけですから、たいていの場合、クロージャを使用する必要はありません。
ListView
しかし、クロージャが役に立つ場合もあります。例えば、`visible` が指定されており、それが `false` と評価される場合には
`value` の計算を避けたい場合です。
```php
echo DetailView::widget([
'model' => $model,
'attributes' => [
[
'attribute' => 'owner',
'value' => function ($model) {
return $model->owner->name;
},
'visible' => \Yii::$app->user->can('posts.owner.view'),
],
],
]);
```
ListView <a name="list-view"></a>
--------
[[yii\widgets\ListView|ListView]] ウィジェットは、[データプロバイダ](output-data-providers.md) からのデータを表示するのに使用されます。
@ -267,7 +290,7 @@ echo GridView::widget([
コールバックのシグニチャは [[yii\grid\ActionColumn::createUrl()]] のそれと同じでなければなりません。
このプロパティが設定されていないときは、ボタンの URL は [[yii\grid\ActionColumn::createUrl()]] を使って生成されます。
- [[yii\grid\ActionColumn::visibleButtons|visibleButtons]] は、各ボタンの可視性の条件を定義する配列です。
配列のキーはボタンの名前 (波括弧を除く) であり、値は真偽値 true/false または無名関数です。
配列のキーはボタンの名前 (波括弧を除く) であり、値は真偽値 `true`/`false` または無名関数です。
ボタンの名前がこの配列の中で指定されていない場合は、デフォルトで、ボタンが表示されます。
コールバックは次のシグニチャを使わなければなりません。
@ -338,7 +361,8 @@ echo GridView::widget([
データをフィルタリングするためには、GridView は検索基準を表す [モデル](structure-models.md) を必要とします。
検索基準は、通常は、グリッドビューのテーブルのフィルタのフィールドから取得されます。
[アクティブレコード](db-active-record.md) を使用している場合は、必要な機能を提供する検索用のモデルクラスを作成するのが一般的なプラクティスです (あなたに代って [Gii](start-gii.md) が生成してくれます)。
このクラスは、検索のためのバリデーション規則を定義し、検索基準に従って修正されたクエリを持つデータプロバイダを返す `search()` メソッドを提供するものです。
このクラスが、グリッドビューのテーブルに表示されるフィルタコントロールのための検証規則を定義し、
検索基準に従って修正されたクエリを持つデータプロバイダを返す `search()` メソッドを提供します。
`Post` モデルに対して検索機能を追加するために、次の例のようにして、`PostSearch` モデルを作成することが出来ます。

2
docs/guide-ja/output-formatting.md

@ -21,7 +21,7 @@ echo $formatter->asEmail('cebe@example.com');
echo $formatter->asBoolean(true);
// it also handles display of null values:
// 出力: (Not set)
// 出力: (not set)
echo $formatter->asDate(null);
```

2
docs/guide-ja/rest-authentication.md

@ -26,7 +26,7 @@ Yii は上記の全ての認証方法をサポートしています。新しい
3. [[yii\web\User::identityClass|ユーザアイデンティティクラス]] において [[yii\web\IdentityInterface::findIdentityByAccessToken()]] を実装します。
ステップ 1 は必須ではありませんが、ステートレスであるべき RESTful API のために推奨されます。
[[yii\web\User::enableSession|enableSession]] が false である場合、ユーザの認証ステータスがセッションを使ってリクエストをまたいで存続することはありません。
[[yii\web\User::enableSession|enableSession]] が `false` である場合、ユーザの認証ステータスがセッションを使ってリクエストをまたいで存続することはありません。
その代りに、すべてのリクエストに対して認証が実行されます。このことは、ステップ 2 と 3 によって達成されます。
> Tip: RESTful API をアプリケーションの形式で開発する場合は、アプリケーションの構成情報で `user` アプリケーションコンポーネント(structure-application-components.md) の [[yii\web\User::enableSession|enableSession]] プロパティを構成することが出来ます。

7
docs/guide-ja/rest-quick-start.md

@ -62,6 +62,10 @@ as `app\models\User`, the controller knows which model can be used for fetching
上記の構成情報は、主として、`user` コントローラの URL 規則を追加して、ユーザのデータが綺麗な URL と意味のある HTTP 動詞によってアクセスおよび操作できるようにするものです。
> Info: Yii はコントローラの名前を自動的に複数形にしてエンドポイントとして使用します (下の「試してみる」(#trying-it-out) を参照してください)。
> この振る舞いは [[yii\rest\UrlRule::$pluralize]] プロパティを使って構成することが可能です。
## JSON の入力を可能にする <span id="enabling-json-input"></span>
API が JSON 形式で入力データを受け取ることが出来るように、`request` [アプリケーションコンポーネント](structure-application-components.md) の [[yii\web\Request::$parsers|parsers]] プロパティを構成して、JSON 入力のために [[yii\web\JsonParser]] を使うようにします。
@ -93,9 +97,6 @@ API が JSON 形式で入力データを受け取ることが出来るように
* `OPTIONS /users`: エンドポイント `/users` に関してサポートされている動詞を示す
* `OPTIONS /users/123`: エンドポイント `/users/123` に関してサポートされている動詞を示す
> Info: Yii はコントローラの名前を自動的に複数形にしてエンドポイントとして使用します。
> この振る舞いは [[yii\rest\UrlRule::$pluralize]] プロパティを使って構成することが可能です。
作成した API は、次のように、`curl` コマンドでアクセスすることが出来ます。
```

2
docs/guide-ja/rest-rate-limiting.md

@ -58,4 +58,4 @@ public function behaviors()
* `X-Rate-Limit-Remaining` - 現在の期間において残っている許可されているリクエスト数
* `X-Rate-Limit-Reset` - 許可されているリクエストの最大数にリセットされるまで待たなければならない秒数
これらのヘッダは、上記のコード例で示されているように、[[yii\filters\RateLimiter::enableRateLimitHeaders]] を false に設定することで無効にすることが出来ます。
これらのヘッダは、上記のコード例で示されているように、[[yii\filters\RateLimiter::enableRateLimitHeaders]] を `false` に設定することで無効にすることが出来ます。

37
docs/guide-ja/rest-resources.md

@ -93,7 +93,7 @@ public function fields()
### `extraFields()` をオーバーライドする<span id="overriding-extra-fields"></span>
デフォルトでは、[[yii\base\Model::extraFields()]] は何も返さず、[[yii\db\ActiveRecord::extraFields()]] は DB から取得されたリレーションの名前を返します。
デフォルトでは、[[yii\base\Model::extraFields()]] は空の配列を返し、[[yii\db\ActiveRecord::extraFields()]] は DB から取得されたリレーションの名前を返します。
`extraFields()` によって返されるデータの形式は `fields()` のそれと同じです。
通常、`extraFields()` は、主として、値がオブジェクトであるフィールドを指定するのに使用されます。
@ -140,23 +140,41 @@ HATEOAS のキーポイントは、リソースデータが API によって提
例えば、
```php
use yii\db\ActiveRecord;
use yii\web\Link;
use yii\base\Model;
use yii\web\Link; // JSON ハイパーメディア API 言語に定義されているリンクオブジェクトを表す
use yii\web\Linkable;
use yii\helpers\Url;
class User extends ActiveRecord implements Linkable
class UserResource extends Model implements Linkable
{
public $id;
public $email;
//...
public function fields()
{
return ['id', 'email'];
}
public function extraFields()
{
return ['profile'];
}
public function getLinks()
{
return [
Link::REL_SELF => Url::to(['user/view', 'id' => $this->id], true),
'edit' => Url::to(['user/view', 'id' => $this->id], true),
'profile' => Url::to(['user/profile/view', 'id' => $this->id], true),
'index' => Url::to(['users'], true),
];
}
}
```
`User` オブジェクトがレスポンスで返されるとき、レスポンスはそのユーザに関連するリンクを表現する `_links` 要素を含むことになります。
`UserResource` オブジェクトがレスポンスで返されるとき、レスポンスはそのユーザに関連するリンクを表現する `_links` 要素を含むことになります。
例えば、
```
@ -167,6 +185,15 @@ class User extends ActiveRecord implements Linkable
"_links" => {
"self": {
"href": "https://example.com/users/100"
},
"edit": {
"href": "https://example.com/users/100"
},
"profile": {
"href": "https://example.com/users/profile/100"
},
"index": {
"href": "https://example.com/users"
}
}
}

2
docs/guide-ja/rest-routing.md

@ -72,7 +72,7 @@
エンドポイントの URL ではコントローラ ID `user``users` という複数形で出現していることに気が付いたかもしれません。
これは、[[yii\rest\UrlRule]] が子 URL 規則を作るときに、コントローラの ID を自動的に複数形にするためです。
この振る舞いは [[yii\rest\UrlRule::pluralize]] を false に設定することで無効にすることが出来ます。
この振る舞いは [[yii\rest\UrlRule::pluralize]] を `false` に設定することで無効にすることが出来ます。
> Info: コントローラ ID の複数形化は [[yii\helpers\Inflector::pluralize()]] によって行われます。
このメソッドは特殊な複数形の規則を考慮します。

8
docs/guide-ja/runtime-handling-errors.md

@ -10,7 +10,7 @@ Yii が内蔵している [[yii\web\ErrorHandler|エラーハンドラ]] は、
* さまざまなエラーレスポンス形式をサポートしています。
[[yii\web\ErrorHandler|エラーハンドラ]] はデフォルトで有効になっています。
アプリケーションの [エントリスクリプト](structure-entry-scripts.md) において、定数 `YII_ENABLE_ERROR_HANDLER` を false と定義することによって、これを無効にすることが出来ます。
アプリケーションの [エントリスクリプト](structure-entry-scripts.md) において、定数 `YII_ENABLE_ERROR_HANDLER``false` と定義することによって、これを無効にすることが出来ます。
## エラーハンドラを使用する <span id="using-error-handler"></span>
@ -59,8 +59,8 @@ throw new NotFoundHttpException();
## エラー表示をカスタマイズする <span id="customizing-error-display"></span>
[[yii\web\ErrorHandler|エラーハンドラ]] は、定数 `YII_DEBUG` の値に従って、エラー表示を調整します。
`YII_DEBUG` が true である (デバッグモードである) 場合は、エラーハンドラは、デバッグがより容易になるように、例外とともに、詳細なコールスタック情報とソースコード行を表示します。
そして、`YII_DEBUG` が false のときは、アプリケーションに関する公開できない情報の開示を防ぐために、エラーメッセージだけが表示されます。
`YII_DEBUG``true` である (デバッグモードである) 場合は、エラーハンドラは、デバッグがより容易になるように、例外とともに、詳細なコールスタック情報とソースコード行を表示します。
そして、`YII_DEBUG` が `false` のときは、アプリケーションに関する公開できない情報の開示を防ぐために、エラーメッセージだけが表示されます。
> Info: 例外が [[yii\base\UserException]] の子孫である場合は、`YII_DEBUG` の値の如何にかかわらず、コールスタックは表示されません。
これは、この種の例外はユーザの誤操作によって引き起こされるものであり、開発者は何も修正する必要がないと考えられるからです。
@ -68,7 +68,7 @@ throw new NotFoundHttpException();
デフォルトでは、[[yii\web\ErrorHandler|エラーハンドラ]] は二つの [ビュー](structure-views.md) を使ってエラーを表示します。
* `@yii/views/errorHandler/error.php`: エラーがコールスタック情報なしで表示されるべき場合に使用されます。
`YII_DEBUG` が false の場合、これが表示される唯一のビューとなります。
`YII_DEBUG``false` の場合、これが表示される唯一のビューとなります。
* `@yii/views/errorHandler/exception.php`: エラーがコールスタック情報と共に表示されるべき場合に使用されます。
エラー表示をカスタマイズするために、エラーハンドラの [[yii\web\ErrorHandler::errorView|errorView]] および [[yii\web\ErrorHandler::exceptionView|exceptionView]] プロパティを構成して、自分自身のビューを使用することが出来ます。

5
docs/guide-ja/runtime-responses.md

@ -191,8 +191,9 @@ public function actionOld()
そして、クライアントサイドで、このヘッダの値を読み、それに応じてブラウザをリダイレクトする JavaScript を書くことが出来ます。
> Info: Yii には `yii.js` という JavaScript ファイルが付属しています。
これは、よく使われる一連の JavaScript 機能を提供するもので、その中には `X-Redirect` ヘッダに基づくブラウザのリダイレクトも含まれています。
従って、あなたが ([[yii\web\YiiAsset]] アセットバンドルを登録して) この JavaScript ファイルを使うつもりなら、AJAX のリダイレクトをサポートするためには、何も書く必要がなくなります。
これは、よく使われる一連の JavaScript 機能を提供するもので、その中には `X-Redirect` ヘッダに基づくブラウザのリダイレクトも含まれています。
従って、あなたが ([[yii\web\YiiAsset]] アセットバンドルを登録して) この JavaScript ファイルを使うつもりなら、AJAX のリダイレクトをサポートするためには、何も書く必要がなくなります。
`yii.js` に関する更なる情報は [クライアントスクリプトの節](output-client-scripts.md#yii.js) にあります。
## ファイルを送信する <span id="sending-files"></span>

183
docs/guide-ja/runtime-routing.md

@ -34,14 +34,17 @@ $url = Url::to(['post/view', 'id' => 100]);
## URL 形式 <span id="url-formats"></span>
[[yii\web\UrlManager|URL マネージャ]] は二つの URL 形式、すなわち、デフォルトの URL 形式と、綺麗な URL 形式をサポートします。
[[yii\web\UrlManager|URL マネージャ]] は二つの URL 形式をサポートします。すなわち、
デフォルトの URL 形式は、`r` というクエリパラメータを使用してルートを表し、通常のクエリパラメータを使用してルートに結び付けられたクエリパラメータを表します。
- デフォルトの URL 形式と、
- 綺麗な URL (プリティ URL) の 形式。
デフォルトの URL 形式は、`r` という [[yii\web\UrlManager::$routeParam|クエリパラメータ]] を使用してルートを表し、通常のクエリパラメータを使用してルートに結び付けられたクエリパラメータを表します。
例えば、`/index.php?r=post/view&id=100` という URL は、`post/view` というルートと、`id` というクエリパラメータが 100 であることを表します。
デフォルトの URL 形式は、[[yii\web\UrlManager|URL マネージャ]] についての構成を何も必要とせず、ウェブサーバの設定がどのようなものでも動作します。
綺麗な URL 形式は、エントリスクリプトの名前に続く追加のパスを使用して、ルートとそれに結び付けられたクエリパラメータを表します。
例えば、`/index.php/post/100` という URL の追加のパスは `/post/100` ですが、適切な [[yii\web\UrlManager::rules|URL 規則]] があれば、この URL が `post/view` というルートと `id` というクエリパラメータが 100 であることを表すことが出来ます。
例えば、`/index.php/post/100` という URL の追加のパスは `/post/100` ですが、適切な [[yii\web\UrlManager::rules|URL 規則]] があれば、この追加のパスが `post/view` というルートと `id` のクエリパラメータ `100` を表すものとすることが出来ます。
綺麗な URL 形式を使用するためには、URL をどのように表現すべきかという実際の要求に従って、一連の [[yii\web\UrlManager::rules|URL 規則]] を設計する必要があります。
この二つの URL 形式は、[[yii\web\UrlManager|URL マネージャ]] の [[yii\web\UrlManager::enablePrettyUrl|enablePrettyUrl]] プロパティを ON/OFF することによって、他のアプリケーションコードを少しも変えることなく、切り替えることが出来ます。
@ -49,8 +52,10 @@ $url = Url::to(['post/view', 'id' => 100]);
## ルーティング <span id="routing"></span>
ルーティングは二つのステップを含みます。最初のステップでは、入ってくるリクエストが解析されて、ルートとそれに結び付けられたクエリパラメータに分解されます。
そして、第二のステップでは、解析されたルートに対応する [コントローラアクション](structure-controllers.md#actions) がリクエストを処理するために生成されます。
ルーティングは二つのステップを含みます。
- まず、入ってくるリクエストが解析されて、ルートとそれに結び付けられたクエリパラメータに分解されます。
- そして、解析されたルートに対応する [コントローラアクション](structure-controllers.md#actions) がリクエストを処理するために生成されます。
デフォルトの URL 形式を使っている場合は、リクエストからルートを解析することは、`r` という名前の `GET` クエリパラメータを取得するだけの簡単なことです。
@ -117,7 +122,7 @@ $url = Url::to(['post/view', 'id' => 100]);
`catchAll` プロパティは配列を取り、最初の要素はルートを指定し、残りの要素 (「名前-値」のペア) は [アクションのパラメータ](structure-controllers.md#action-parameters) を指定するものでなければなりません。
> Info: このプロパティを有効にすると、開発環境でデバッグパネルが動作しなくなります。
> Info: このプロパティを有効にすると、開発環境で [デバッグツールバー](https://github.com/yiisoft/yii2-debug/blob/master/docs/guide-ja/README.md)が 動作しなくなります。
## URL を生成する <span id="creating-urls"></span>
@ -173,14 +178,14 @@ echo Url::to(['post/index']);
// 絶対ルート: /index.php?r=post%2Findex
echo Url::to(['/post/index']);
// /index.php?r=post%2Findex エイリアス "@posts" が "/post/index" と定義されていると仮定
// "/post/index" と定義されているエイリアス "@posts"を使用: /index.php?r=post%2Findex
echo Url::to(['@posts']);
```
[[yii\helpers\Url::to()]] メソッドは、[[yii\web\UrlManager|URL マネージャ]] の [[yii\web\UrlManager::createUrl()|createUrl()]] メソッド、および、[[yii\web\UrlManager::createAbsoluteUrl()|createAbsoluteUrl()]] を呼び出すことによって実装されています。
次に続くいくつかの項では、[[yii\web\UrlManager|URL マネージャ]] を構成して、生成される URL の形式をカスタマイズする方法を説明します。
[[yii\helpers\Url::to()]] メソッドは、特定のルートとの関係を持たない URL の生成もサポートしています。
[[yii\helpers\Url::to()]] メソッドは、特定のルートとの関係を持た**ない** URL の生成もサポートしています。
その場合、最初のパラメータには、配列を渡す代りに文字列を渡さなければなりません。例えば、
```php
@ -242,7 +247,7 @@ echo Url::previous();
その他のプロパティはオプションですが、上記で示されている構成が最もよく用いられているものです。
* [[yii\web\UrlManager::showScriptName|showScriptName]]: このプロパティは、生成される URL にエントリスクリプトを含めるべきかどうかを決定します。
例えば、このプロパティを false にすると、`/index.php/post/100` という URL を生成する代りに、`/post/100` という URL を生成することが出来ます。
例えば、このプロパティを `false` にすると、`/index.php/post/100` という URL を生成する代りに、`/post/100` という URL を生成することが出来ます。
* [[yii\web\UrlManager::enableStrictParsing|enableStrictParsing]]: このプロパティは、厳密なリクエスト解析を有効にするかどうかを決定します。
厳密な解析が有効にされた場合、リクエストされた URL が有効なリクエストとして扱われるためには、それが [[yii\web\UrlManager::rules|rules]] の少なくとも一つに合致しなければなりません。
そうでなければ、[[yii\web\NotFoundHttpException]] が投げられます。
@ -250,13 +255,13 @@ echo Url::previous();
* [[yii\web\UrlManager::rules|rules]]: このプロパティが URL を解析および生成するための一連の規則を含みます。
このプロパティが、アプリケーションの固有の要求を満たす形式を持つ URL を生成するために、あなたが主として使うプロパティです。
> Note: 生成された URL からエントリスクリプト名を隠すためには、[[yii\web\UrlManager::showScriptName|showScriptName]] を false に設定するだけでなく、ウェブサーバを構成して、リクエストされた URL が PHP スクリプトを明示的に指定していない場合でも、正しい PHP スクリプトを特定出来るようにする必要があります。
もしあなたが Apache ウェブサーバを使うつもりなら、[インストール](start-installation.md#recommended-apache-configuration) の節で説明されている推奨設定を参照することが出来ます。
> Note: 生成された URL からエントリスクリプト名を隠すためには、[[yii\web\UrlManager::showScriptName|showScriptName]] を `false` に設定するだけでなく、ウェブサーバを構成して、リクエストされた URL が PHP スクリプトを明示的に指定していない場合でも、正しい PHP スクリプトを特定出来るようにする必要があります。
もしあなたが Apache または nginx ウェブサーバを使うつもりなら、[インストール](start-installation.md#recommended-apache-configuration) の節で説明されている推奨設定を参照することが出来ます。
### URL 規則 <span id="url-rules"></span>
URL 規則は [[yii\web\UrlRule]] またはその子クラスのインスタンスです。
URL 規則は [[yii\web\UrlRuleInterface]] を実装するクラス、通常は、[[yii\web\UrlRule]] クラスです。
すべての URL 規則は、URL のパス情報の部分との照合に使われるパターン、ルート、そして、いくつかのクエリパラメータから構成されます。
URL 規則は、パターンがリクエストされた URL と合致する場合に、リクエストの解析に使用することが出来ます。
また、URL 規則は、ルートとクエリパラメータ名が与えられたものと合致する場合に、URL の生成に使用することが出来ます。
@ -266,15 +271,15 @@ URL 規則は、パターンがリクエストされた URL と合致する場
そして、その合致する規則を使って URL を解析して、ルートとそれに結び付けられたパラメータを得ます。
同じように、URL を生成するためには、[[yii\web\UrlManager|URL マネージャ]] は、与えられたルートとパラメータに合致する最初の規則を探して、それを使って URL を生成します。
[[yii\web\UrlManager::rules]] は、パターンをキーとし、それに対応するルートを値とする配列として構成することが出来ます。
[[yii\web\UrlManager::rules]] は、 [[yii\web\UrlRule::$pattern|パターン]] をキーとし、それに対応する [[yii\web\UrlRule::$route|ルート]] を値とする配列として構成することが出来ます。
「パターン - ルート」のペアが、それぞれ、URL 規則を構成します。
例えば、次の [[yii\web\UrlManager::rules|rules]] の構成は、二つの URL 規則を宣言するものです。
最初の規則は `posts` という URL に合致し、それを `post/index` というルートにマップします。
第二の規則は `post/(\d+)` という正規表現にマッチする URL に合致し、それを `post/view` というルートと `id` という名前のパラメータにマップします。
```php
[
'posts' => 'post/index',
'rules' => [
'posts' => 'post/index',
'post/<id:\d+>' => 'post/view',
]
```
@ -288,9 +293,8 @@ URL 規則は、「パターン - ルート」のペアとして宣言する以
例えば、
```php
[
'rules' => [
// ... 他の URL 規則 ...
[
'pattern' => 'posts',
'route' => 'post/index',
@ -300,15 +304,16 @@ URL 規則は、「パターン - ルート」のペアとして宣言する以
```
URL 規則の構成情報で `class` を指定しない場合は、デフォルトとして、[[yii\web\UrlRule]] が使われます。
このクラスが、[[yii\web\UrlManager::$ruleConfig]] でデフォルト値として定義されています。
### 名前付きパラメータ <span id="named-parameters"></span>
URL 規則は、パターンの中で `<ParamName:RgExp>` の形式で指定される、いくつかの名前付きクエリパラメータと結び付けることが出来ます。
URL 規則は、パターンの中で `<ParamName:RgExp>` の形式で指定される、名前付きクエリパラメータと結び付けることが出来ます。
ここで、`ParamName` はパラメータ名を指定し、`RegExp` はパラメータの値との照合に使われるオプションの正規表現を指定するものです。
`RegExp` が指定されていない場合は、パラメータの値がスラッシュを含まない文字列であるべきことを意味します。
> Note: 正規表現はパラメータに対してのみ指定できます。パターンの残りの部分はプレーンテキストとして解釈されます。
> Note: 正規表現はパラメータの中でのみ使用できます。パターンの残りの部分はプレーンテキストとして解釈されます。
規則が URL の解析に使われるときには、URL の対応する部分に合致した値が、結び付けられたパラメータに入れられます。
そして、そのパラメータは、後に `request` アプリケーションコンポーネントによって、`$_GET` に入れられて利用できるようになります。
@ -317,7 +322,7 @@ URL 規則は、パターンの中で `<ParamName:RgExp>` の形式で指定さ
名前付きパラメータの動作を説明するためにいくつかの例を挙げましょう。次の三つの URL 規則を宣言したと仮定してください。
```php
[
'rules' => [
'posts/<year:\d{4}>/<category>' => 'post/index',
'posts' => 'post/index',
'post/<id:\d+>' => 'post/view',
@ -329,9 +334,10 @@ URL 規則は、パターンの中で `<ParamName:RgExp>` の形式で指定さ
- `/index.php/posts` は、二番目の規則を使って解析され、ルート `post/index` になります。
- `/index.php/posts/2014/php` は、最初の規則を使って解析され、ルートは `post/index`、`year` パラメータの値は 2014、そして、`category` パラメータの値は `php` となります。
- `/index.php/post/100` は、三番目の規則を使って解析され、ルートが `post/view`、`id` パラメータの値が 100 となります。
- `/index.php/posts/php` は、どのパターンにも合致しないため、[[yii\web\UrlManager::enableStrictParsing]] が true の場合は、[[yii\web\NotFoundHttpException]] を引き起こします。
[[yii\web\UrlManager::enableStrictParsing]] が false (これがデフォルト値です) の場合は、パス情報の部分である `posts/php` がルートとして返されることになります。
- `/index.php/posts/php` は、どのパターンにも合致しないため、[[yii\web\UrlManager::enableStrictParsing]] が `true` の場合は、[[yii\web\NotFoundHttpException]] を引き起こします。
[[yii\web\UrlManager::enableStrictParsing]] が `false` (これがデフォルト値です) の場合は、パス情報の部分である `posts/php` がルートとして返されることになります。
こうして解析されたルートに対応するアクションがあればそれが実行され、そうでなければ [[yii\web\NotFoundHttpException]] が投げられます。
規則が URL 生成に使われる場合は、
- `Url::to(['post/index'])` は、二番目の規則を使って、`/index.php/posts` を生成します。
@ -349,20 +355,23 @@ URL 規則のルートにはパラメータ名を埋め込むことが出来ま
例えば、以下の規則は `controller``action` というパラメータをルートに埋め込んでいます。
```php
[
'<controller:(post|comment)>/<id:\d+>/<action:(create|update|delete)>' => '<controller>/<action>',
'rules' => [
'<controller:(post|comment)>/create' => '<controller>/create',
'<controller:(post|comment)>/<id:\d+>/<action:(update|delete)>' => '<controller>/<action>',
'<controller:(post|comment)>/<id:\d+>' => '<controller>/view',
'<controller:(post|comment)>s' => '<controller>/index',
]
```
`/index.php/comment/100/create` という URL の解析には、最初の規則が適用され、`controller` パラメータには `comment`、`action` パラメータには `create` がセットされます。
こうして、`<controller>/<action>` というルートは、`comment/create` として解決されます。
`/index.php/comment/100/update` という URL の解析には、二番目の規則が適用され、`controller` パラメータには `comment`、`action` パラメータには `update` がセットされます。
こうして、`<controller>/<action>` というルートは、`comment/update` として解決されます。
同じように、`comment/index` というルートの URL を生成するためには、三番目の規則が適用されて、`index.php/comments` という URL が生成されます。
同じように、`comment/index` というルートの URL を生成するためには、最後の規則が適用されて、`index.php/comments` という URL が生成されます。
> Info: ルートをパラメータ化することによって、URL 規則の数を大幅に減らすことが可能になり、[[yii\web\UrlManager|URL マネージャ]] のパフォーマンスを目に見えて改善することが出来ます。
### デフォルトのパラメータ値 <span id="default-parameter-values"></span>
デフォルトでは、規則の中で宣言されたパラメータは必須となります。
リクエストされた URL が特定のパラメータを含まない場合や、特定のパラメータなしで URL を生成する場合には、規則は適用されません。
パラメータのどれかをオプション扱いにしたい場合は、規則の [[yii\web\UrlRule::defaults|defaults]] プロパティを構成することが出来ます。
@ -371,7 +380,7 @@ URL 規則のルートにはパラメータ名を埋め込むことが出来ま
次の規則の宣言においては、`page` と `tag` のパラメータは両方ともオプション扱いで、提供されなかった場合は、それぞれ、1 と空文字列を取ります。
```php
[
'rules' => [
// ... 他の規則 ...
[
'pattern' => 'posts/<page:\d+>/<tag>',
@ -398,7 +407,7 @@ URL 規則のパターンには、ウェブサーバ名を含むことが出来
例えば、次の規則は、`http://admin.example.com/login` という URL を `admin/user/login` のルートとして解析し、`http://www.example.com/login` を `site/login` として解析するものです。
```php
[
'rules' => [
'http://admin.example.com/login' => 'admin/user/login',
'http://www.example.com/login' => 'site/login',
]
@ -408,14 +417,16 @@ URL 規則のパターンには、ウェブサーバ名を含むことが出来
例えば、次の規則は `http://en.example.com/posts` という URL を解析して、`post/index` というルートと `language=en` というパラメータを取得するものです。
```php
[
'rules' => [
'http://<language:\w+>.example.com/posts' => 'post/index',
]
```
> Note: サーバ名を持つ規則は、エントリスクリプトのサブフォルダをパターンに含むべきではありません。
例えば、アプリケーションが `http://www.example.com/sandbox/blog` の下にある場合は、`http://www.example.com/sandbox/blog/posts` ではなく、`http://www.example.com/posts` というパターンを使うべきです。
こうすれば、アプリケーションをどのようなディレクトリに配置しても、アプリケーションのコードを変更する必要がなくなります。
> Note: サーバ名を持つ規則は、そのパターンに、エントリスクリプトのサブフォルダを**含まない**ようにすべきです。
例えば、アプリケーションのエントリスクリプトが `http://www.example.com/sandbox/blog/index.php` である場合は、
`http://www.example.com/sandbox/blog/posts` ではなく、`http://www.example.com/posts` というパターンを使うべきです。
こうすれば、アプリケーションをどのようなディレクトリに配置しても、URL 規則を変更する必要がなくなります。
Yii はアプリケーションのベース URL を自動的に検出します。
### URL 接尾辞 <span id="url-suffixes"></span>
@ -430,8 +441,7 @@ URL 規則のパターンには、ウェブサーバ名を含むことが出来
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => true,
// ...
'suffix' => '.html',
'rules' => [
// ...
@ -446,7 +456,7 @@ URL 規則のパターンには、ウェブサーバ名を含むことが出来
> Tip: URL が全てスラッシュで終るようにするためには、URL 接尾辞として `/` を設定することが出来ます。
> Note: URL 接尾辞を構成すると、リクエストされた URL が接尾辞を持たない場合は、認識できない URL であると見なされるようになります。
SEO の目的からも、これが推奨されるプラクティスです。
これは、異なる URL 上の重複コンテンツを防止するためのものであり、SEO (検索エンジン最適化) の見地からも推奨されるプラクティスです。
場合によっては、URL によって異なる接尾辞を使いたいことがあるでしょう。
その目的は、個々の URL 規則の [[yii\web\UrlRule::suffix|suffix]] プロパティを構成することによって達成できます。
@ -458,8 +468,7 @@ URL 規則にこのプロパティが設定されている場合は、それが
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => true,
// ...
'suffix' => '.html',
'rules' => [
// ...
@ -481,17 +490,17 @@ RESTful API を実装するときは、使用されている HTTP メソッド
これは、規則のパターンにサポートされている HTTP メソッドを前置することによって、簡単に達成することが出来ます。
一つの規則が複数の HTTP メソッドをサポートする場合は、メソッド名をカンマで区切ります。
例えば、次の三つの規則は、`post/<id:\d+>` という同一のパターンを持って、異なる HTTP メソッドをサポートするものです。
`PUT post/100` に対するリクエストは `post/create` と解析され、`GET post/100` に対するリクエストは `post/view` と解析されることになります。
`PUT post/100` に対するリクエストは `post/update` と解析され、`GET post/100` に対するリクエストは `post/view` と解析されることになります。
```php
[
'PUT,POST post/<id:\d+>' => 'post/create',
'rules' => [
'PUT,POST post/<id:\d+>' => 'post/update',
'DELETE post/<id:\d+>' => 'post/delete',
'post/<id:\d+>' => 'post/view',
]
```
> Note: URL 規則が HTTP メソッドをパターンに含む場合、その規則は解析目的にだけ使用されます。
> Note: URL 規則が HTTP メソッドをパターンに含む場合、指定されたメソッドに `GET` が入っていない限り、その規則は解析目的にだけ使用されます。
[[yii\web\UrlManager|URL マネージャ]] が URL 生成のために呼ばれたときは、その規則はスキップされます。
> Tip: RESTful API のルーティングを簡単にするために、Yii は特別な URL 規則クラス [[yii\rest\UrlRule]] を提供しています。
@ -499,33 +508,11 @@ RESTful API を実装するときは、使用されている HTTP メソッド
詳細については、RESTful API 開発についての [ルーティング](rest-routing.md) の節を参照してください。
### 規則をカスタマイズする <span id="customizing-rules"></span>
これまでの例では、URL 規則は主として「パターン - ルート」のペアの形で宣言されています。これが通常使用される短縮形式です。
特定のシナリオの下では、[[yii\web\UrlRule::suffix]] などのような、他のプロパティを構成して URL 規則をカスタマイズしたいこともあるでしょう。
完全な構成情報配列を使って規則を指定すれば、そうすることが出来ます。
次の例は、[URL 接尾辞](#url-suffixes) の項から抜き出したものです。
```php
[
// ... 他の URL 規則 ...
[
'pattern' => 'posts',
'route' => 'post/index',
'suffix' => '.json',
],
]
```
> Info: 規則の構成情報で `class` を指定しない場合は、デフォルトとして、[[yii\web\UrlRule]] クラスが使われます。
### 規則を動的に追加する <span id="adding-rules"></span>
URL 規則は [[yii\web\UrlManager|URL マネージャ]] に動的に追加することが出来ます。
このことは、再配布可能な [モジュール](structure-modules.md) が自分自身の URL 規則を管理する必要がある場合に、しばしば必要になります。
動的に追加された規則がルーティングのプロセスで効果を発揮するためには、その規則を [ブートストラップ](runtime-bootstrapping.md) の段階で追加しなければなりません。
動的に追加された規則がルーティングのプロセスで効果を発揮するためには、その規則をアプリケーションの [ブートストラップ](runtime-bootstrapping.md) の段階で追加しなければなりません。
これは、モジュールにとっては、次のように、[[yii\base\BootstrapInterface]] を実装して、[[yii\base\BootstrapInterface::bootstrap()|bootstrap()]] メソッドの中で規則を追加しなければならないことを意味します。
```php
@ -549,6 +536,8 @@ public function bootstrap($app)
この問題を解決するために、次のような URL 規則クラスを作成することが出来ます。
```php
<?php
namespace app\components;
use yii\web\UrlRuleInterface;
@ -566,7 +555,7 @@ class CarUrlRule extends Object implements UrlRuleInterface
return $params['manufacturer'];
}
}
return false; // この規則は適用されない
return false; // この規則は適用されない
}
public function parseRequest($manager, $request)
@ -575,10 +564,10 @@ class CarUrlRule extends Object implements UrlRuleInterface
if (preg_match('%^(\w+)(/(\w+))?$%', $pathInfo, $matches)) {
// $matches[1] と $matches[3] をチェックして、
// データベースの中の製造者とモデルに合致するかどうか調べる
// 合致すれば、$params['manufacturer'] および/または $params['model'] をセットし、
// ['car/index', $params] を返す
// 合致すれば、$params['manufacturer'] および/または $params['model']
// をセットし、['car/index', $params] を返す
}
return false; // この規則は適用されない
return false; // この規則は適用されない
}
}
```
@ -586,9 +575,8 @@ class CarUrlRule extends Object implements UrlRuleInterface
そして、[[yii\web\UrlManager::rules]] の構成情報で、新しい規則クラスを使います。
```php
[
'rules' => [
// ... 他の規則 ...
[
'class' => 'app\components\CarUrlRule',
// ... 他のプロパティを構成する ...
@ -597,6 +585,55 @@ class CarUrlRule extends Object implements UrlRuleInterface
```
## URL の正規化 <span id="url-normalization"></span>
バージョン 2.0.10 以降、[[yii\web\UrlManager|UrlManager]] で [[yii\web\UrlNormalizer|UrlNormalizer]] を使って、
同一 URL のバリエーション (例えば、末尾のスラッシュの有無) の問題を処理する出来るようになりました。
技術的には `http://example.com/path``http://example.com/path/` は別の URL ですから、
これらの両方に同一のコンテントを提供することは SEO ランキングを低下させる可能性があります。
デフォルトでは、URL ノーマライザは、連続したスラッシュを畳み、サフィックスが末尾のスラッシュを持っているかどうかに従って末尾のスラッシュを追加または削除し、
正規化された URL に [恒久的な移動](https://en.wikipedia.org/wiki/HTTP_301) を使ってリダイレクトします。
ノーマライザは、URL マネージャのためにグローバルに構成することも、各規則のために個別に構成することも出来ます。
各規則は、デフォルトでは、URL マネージャのノーマライザを使用します。
[[yii\web\UrlRule::$normalizer|UrlRule::$normalizer]] を `false` にすれば、特定の URL 規則について正規化を無効にすることが出来ます。
次に、[[yii\web\UrlNormalizer|UrlNormalizer]] の構成例を示します。
```php
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => true,
'suffix' => '.html',
'normalizer' => [
'class' => 'yii\web\UrlNormalizer',
// デバッグのために、恒久的移動のかわりに一時的リダイレクションを使う
'action' => UrlNormalizer::ACTION_REDIRECT_TEMPORARY,
],
'rules' => [
// ... 他の規則 ...
[
'pattern' => 'posts',
'route' => 'post/index',
'suffix' => '/',
'normalizer' => false, // この規則では正規化を無効にする
],
[
'pattern' => 'tags',
'route' => 'tag/index',
'normalizer' => [
// この規則では連続するスラッシュを畳まない
'collapseSlashes' => false,
],
],
],
]
```
> Note: デフォルトでは [[yii\web\UrlManager::$normalizer|UrlManager::$normalizer]] は無効になっています。
URL の正規化を有効にするためには、明示的に構成する必要があります。
## パフォーマンスに対する考慮 <span id="performance-consideration"></span>
複雑なウェブアプリケーションを開発するときは、リクエストの解析と URL 生成に要する時間を削減するために URL 規則を最適化することが重要になります。

4
docs/guide-ja/runtime-sessions-cookies.md

@ -288,7 +288,7 @@ unset($cookies['language']);
や [[yii\web\Cookie::expire|expire]] など、他のプロパティを定義して、利用可能なクッキー情報の全てを完全に表しています。
クッキーを準備するときに必要に応じてこれらのプロパティを構成してから、レスポンスのクッキーコレクションに追加することが出来ます。
> Note: セキュリティを向上させるために、[[yii\web\Cookie::httpOnly]] のデフォルト値は true に設定されています。
> Note: セキュリティを向上させるために、[[yii\web\Cookie::httpOnly]] のデフォルト値は `true` に設定されています。
これは、クライアントサイドスクリプトが保護されたクッキーにアクセスする危険を軽減するものです (ブラウザがサポートしていれば)。
詳細については、[httpOnly wiki article](https://www.owasp.org/index.php/HttpOnly) を読んでください。
@ -304,7 +304,7 @@ unset($cookies['language']);
これは、サードパーティのライブラリが、クッキー検証を含まない独自の方法でクッキーを操作することが出来るようにするするためです。
クッキー検証はデフォルトで有効になっています。
[[yii\web\Request::enableCookieValidation]] プロパティを false に設定することによって無効にすることが出来ますが、無効にしないことを強く推奨します。
[[yii\web\Request::enableCookieValidation]] プロパティを `false` に設定することによって無効にすることが出来ますが、無効にしないことを強く推奨します。
> Note: `$_COOKIE``setcookie()` によって直接に 読み出し/送信 されるクッキーは検証されません。

4
docs/guide-ja/security-authorization.md

@ -245,6 +245,10 @@ return [
`yii migrate --migrationPath=@yii/rbac/migrations`
異なる名前空間のマイグレーションを扱う方法の詳細については
[分離されたマイグレーション](db-migrations.md#separated-migrations) の節を参照して下さい。
これで `authManager``\Yii::$app->authManager` によってアクセスすることが出来るようになります。

43
docs/guide-ja/security-best-practices.md

@ -227,3 +227,46 @@ H5BP プロジェクトが提供する構成例を参考にすることも出来
- [Apache](https://github.com/h5bp/server-configs-apache).
- [IIS](https://github.com/h5bp/server-configs-iis).
- [Lighttpd](https://github.com/h5bp/server-configs-lighttpd).
サーバの構成をセキュアにする
----------------------------
この節の目的は、Yii ベースのウェブサイトをホストするサーバの構成を作成するときに、
考慮に入れなければならないリスクに照明を当てることにあります。
ここで触れられる問題点以外にも、セキュリティに関連して考慮すべき構成オプションがあるかもしれません。
この節の説明が完全であるとは考えないで下さい。
### `Host` ヘッダ攻撃を避ける
[[yii\web\UrlManager]] や [[yii\helpers\Url]] のクラスは、リンクを生成するために [[yii\web\Request::getHostInfo()|現在リクエストされているホスト名]] を使うことがあります。
って
ウェブサーバが `Host` ヘッダの値とは無関係に同じサイトとして応答するように構成されている場合は、
この情報は [HTTP リクエストを送信するユーザによって偽装され](https://www.acunetix.com/vulnerabilities/web/host-header-attack) て、信頼できないものになっている可能性があります。
そのような状況においては、ウェブサーバの構成を改修して、指定されたホスト名に対してのみ応答するようにするか、
または、`request` アプリケーションコンポーネントの [[yii\web\Request::setHostInfo()|hostInfo]] プロパティを設定して、ホスト名の値を設定ないしフィルタするか、
どちらかの対策を取るべきです。
サーバの構成についての詳細な情報は、ウェブサーバのドキュメントを参照して下さい。
- Apache 2: <http://httpd.apache.org/docs/trunk/vhosts/examples.html#defaultallports>
- Nginx: <https://www.nginx.com/resources/wiki/start/topics/examples/server_blocks/>
サーバの構成にアクセスする権限がない場合は、このような攻撃に対して防御するために、[[yii\filters\HostControl]] フィルタを設定することが出来ます。
```php
// ウェブアプリケーション構成ファイル
return [
'as hostControl' => [
'class' => 'yii\filters\HostControl',
'allowedHosts' => [
'example.com',
'*.example.com',
],
'fallbackHostInfo' => 'https://example.com',
],
// ...
];
```
> Note: 「ホストヘッダ攻撃」に対する保護のためには、常に、フィルタの使用よりもウェブサーバの構成を優先すべきです。
[[yii\filters\HostControl]] は、サーバの構成が出来ない場合にだけ使うべきものです。

2
docs/guide-ja/start-forms.md

@ -57,7 +57,7 @@ class EntryForm extends Model
* `email` のデータは構文的に有効なメールアドレスでなければならない
ユーザによって入力されたデータを `EntryForm` オブジェクトに投入した後、[[yii\base\Model::validate()|validate()]] を呼んでデータ検証ルーチンを始動することが出来ます。
データ検証が失敗すると [[yii\base\Model::hasErrors|hasErrors]] プロパティが true に設定されます。
データ検証が失敗すると [[yii\base\Model::hasErrors|hasErrors]] プロパティが `true` に設定されます。
そして、[[yii\base\Model::getErrors|errors]] を通じて、どのような検証エラーが発生したかを知ることが出来ます。

2
docs/guide-ja/start-gii.md

@ -33,7 +33,7 @@ if (YII_ENV_DEV) {
上記の構成情報は、[開発環境](concept-configurations.md#environment-constants) において、アプリケーションは `gii` という名前のモジュールをインクルードすべきこと、そして `gii` は [[yii\gii\Module]] というクラスであることを記述しています。
アプリケーションの [エントリスクリプト](structure-entry-scripts.md) である `web/index.php` をチェックすると、次の行があることに気付くでしょう。
これは本質的には `YII_ENV_DEV` を true に設定するものです。
これは本質的には `YII_ENV_DEV``true` に設定するものです。
```php
defined('YII_ENV') or define('YII_ENV', 'dev');

4
docs/guide-ja/start-installation.md

@ -50,7 +50,7 @@ Composer は `composer self-update` コマンドを実行してアップデー
> アクセス・トークンの構成の仕方については、[Github API トークンに関する Composer ドキュメント](https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens)
> の指示を参照して下さい。
### Yii をインストールする
### Yii をインストールする <span id="installing-from-composer"></span>
Composer がインストールされたら、ウェブからアクセスできるフォルダで下記のコマンドを実行することによって Yii をインストールすることが出来ます。
@ -150,7 +150,7 @@ http://localhost:8080/
```
Yii の最低必要条件を満たすように PHP のインストールを構成しなければなりません。
最も重要なことは、PHP 5.4 以上でなければならないということです。
最も重要なことは、PHP 5.4 以上でなければならないということです。最新の PHP 7 なら理想的です。
また、アプリケーションがデータベースを必要とする場合は、[PDO PHP 拡張](http://www.php.net/manual/ja/pdo.installation.php) および対応するデータベースドライバ (MySQL データベースのための `pdo_mysql` など) をインストールしなければなりません。

107
docs/guide-ja/structure-assets.md

@ -221,6 +221,49 @@ AppAsset::register($this); // $this はビューオブジェクトを表す
これらのタグの順序は、登録されたバンドル間の依存関係、および、[[yii\web\AssetBundle::css]] と [[yii\web\AssetBundle::js]] のプロパティのリストに挙げられたアセットの順序によって決定されます。
### 動的なアセットバンドル <span id="dynamic-asset-bundles"></span>
アセットバンドルは、通常の PHP クラスですので、内部のパラメータを動的に調整することに関係する追加のロジックを持つことが出来ます。
例えば、洗練された JavaScript ライブラリには、国際化の機能を、サポートする言語ごとに独立したソースファイルにパッケージして提供しているものもあります。
その場合、ライブラリの翻訳を動作させるためには、特定の '.js' ファイルをページに追加しなければなりません。
このことを [[yii\web\AssetBundle::init()]] メソッドをオーバーライドすることによって実現することが出来ます。
```php
namespace app\assets;
use yii\web\AssetBundle;
use Yii;
class SophisticatedAssetBundle extends AssetBundle
{
public $sourcePath = '/path/to/sophisticated/src';
public $js = [
'sophisticated.js' // 常に使用されるファイル
];
public function init()
{
parent::init();
$this->js[] = 'i18n/' . Yii::$app->language . '.js'; // 動的に追加されるファイル
}
}
```
個々のアセットバンドルは、 [[yii\web\AssetBundle::register()]] によって返されるインスタンスによって調整することも出来ます。
例えば、
```php
use app\assets\SophisticatedAssetBundle;
use Yii;
$bundle = SophisticatedAssetBundle::register(Yii::$app->view);
$bundle->js[] = 'i18n/' . Yii::$app->language . '.js'; // 動的に追加されるファイル
```
> Note: アセットバンドルの動的な調整はサポートされてはいますが、**推奨はされません**。
予期しない副作用を引き起こしやすいので、可能であれば避けるべきです。
### アセットバンドルをカスタマイズする <span id="customizing-asset-bundles"></span>
Yii は、[[yii\web\AssetManager]] によって実装されている `assetManager` という名前のアプリケーションコンポーネントを通じてアセットバンドルを管理します。
@ -280,6 +323,55 @@ return [
```
[[yii\web\AssetManager::bundles]] を `false` にセットすることによって、*全て* のバンドルを無効にすることも出来ます。
[[yii\web\AssetManager::bundles]] によってなされたカスタマイズはアセットバンドルの生成時、すなわち、オブジェクトのコンストラクタの段階で適用される、
ということを心に留めてください。
従って、[[yii\web\AssetManager::bundles]] のレベルで設定されたマッピングは、それ以後にバンドルのオブジェクトに対してなされる修正によって上書きされます。
具体的に言えば、[[yii\web\AssetBundle::init()]] メソッドの中での修正や、登録されたバンドルオブジェクトに対する修正は、`AssetManager` の構成よりも優先されます。
以下に、[[yii\web\AssetManager::bundles]] によって設定されたマッピングが効力を持たない例を示します。
```php
// プログラムのソースコード
namespace app\assets;
use yii\web\AssetBundle;
use Yii;
class LanguageAssetBundle extends AssetBundle
{
// ...
public function init()
{
parent::init();
$this->baseUrl = '@web/i18n/' . Yii::$app->language; // AssetManager` では処理出来ない!
}
}
// ...
$bundle = \app\assets\LargeFileAssetBundle::register(Yii::$app->view);
$bundle->baseUrl = YII_DEBUG ? '@web/large-files': '@web/large-files/minified'; // AssetManager` では処理出来ない!
// アプリケーション構成
return [
// ...
'components' => [
'assetManager' => [
'bundles' => [
'app\assets\LanguageAssetBundle' => [
'baseUrl' => 'http://some.cdn.com/files/i18n/en' // 効力を持たない!
],
'app\assets\LargeFileAssetBundle' => [
'baseUrl' => 'http://some.cdn.com/files/large-files' // 効力を持たない!
],
],
],
],
];
```
### アセットマッピング <span id="asset-mapping"></span>
@ -319,7 +411,7 @@ return [
この場所は、[[yii\web\AssetManager::basePath|basePath]] と [[yii\web\AssetManager::baseUrl|baseUrl]] のプロパティを構成してカスタマイズすることが出来ます。
ファイルをコピーすることでアセットを発行する代りに、OS とウェブサーバが許容するなら、シンボリックリンクを使うことを考慮しても良いでしょう。
この機能は [[yii\web\AssetManager::linkAssets|linkAssets]] を true にセットすることで有効にすることが出来ます。
この機能は [[yii\web\AssetManager::linkAssets|linkAssets]] を `true` にセットすることで有効にすることが出来ます。
```php
return [
@ -344,6 +436,7 @@ return [
- [[yii\web\YiiAsset]]: 主として `yii.js` ファイルをインクルードするためのバンドルです。
このファイルはモジュール化された JavaScript のコードを編成するメカニズムを実装しています。
また、`data-method` と `data-confirm` の属性に対する特別なサポートや、その他の有用な機能を提供します。
`yii.js` に関する詳細な情報は [クライアントスクリプトの節](output-client-scripts.md#yii.js) にあります。
- [[yii\web\JqueryAsset]]: jQuery の bower パッケージから `jquery.js` ファイルをインクルードします。
- [[yii\bootstrap\BootstrapAsset]]: Twitter Bootstrap フレームワークから CSS ファイルをインクルードします。
- [[yii\bootstrap\BootstrapPluginAsset]]: Bootstrap JavaScript プラグインをサポートするために、Twitter Bootstrap フレームワークから JavaScript ファイルをインクルードします。
@ -515,6 +608,10 @@ return [
つまり、アセットバンドルの構成情報配列は、本番モードのものは `assets-prod.php` に保存し、開発モードのものは `assets-dev.php` に保存するという訳です。
> Note: このアセット結合のメカニズムは、登録されるアセットバンドルのプロパティをオーバーライドできるという [[yii\web\AssetManager::bundles]] の機能に基づいています。
しかし、既に上で述べたように、この機能は、[[yii\web\AssetBundle::init()]] メソッドの中やバンドルが登録された後で実行されるアセットバンドルの修正をカバーしていません。
そのような動的なバンドルの使用は、アセット結合をする際には避けなければなりません。
### `asset` コマンドを使う <span id="using-asset-command"></span>
@ -541,6 +638,8 @@ return [
'jsCompressor' => 'java -jar compiler.jar --js {from} --js_output_file {to}',
// CSS ファイルの圧縮のためのコマンド/コールバックを調整。
'cssCompressor' => 'java -jar yuicompressor.jar --type css {from} -o {to}',
// 圧縮後にアセットのソースを削除するかどうか。
'deleteSource' => false,
// 圧縮するアセットバンドルのリスト。
'bundles' => [
// 'yii\web\YiiAsset',
@ -582,6 +681,12 @@ yii asset assets.php config/assets-prod.php
直前の項で説明したように、この生成された構成情報ファイルをアプリケーションの構成情報にインクルードすることが出来ます。
> Note: アプリケーションのアセットバンドルを [[yii\web\AssetManager::bundles]] または [[yii\web\AssetManager::assetMap]] によってカスタマイズしており、
そのカスタマイズを圧縮のソースファイルにも適用したい場合は、それらのオプションを `asset` コマンドの構成ファイルの `assetManager` のセクションに含めなければいけません。
> Note: 圧縮のソースを指定する場合は、パラメータが動的に (例えば `init()` メソッドの中や登録後に) 修正されるアセットバンドルを避けなければなりません。
なぜなら、パラメータの動的な修正は、圧縮後は正しく働かない可能性があるからです。
> Info: `asset` コマンドを使うことは、アセットの結合・圧縮のプロセスを自動化する唯一の選択肢ではありません。
優秀なタスク実行ツールである [grunt](http://gruntjs.com/) を使っても、同じ目的を達することが出来ます。

2
docs/guide-ja/structure-controllers.md

@ -397,7 +397,7 @@ class SiteController extends Controller
* アクション ID に合致するアクションメソッドが見つかった場合は、インラインアクションが作成される。
* 上記以外の場合は、[[yii\base\InvalidRouteException]] 例外が投げられる。
3. コントローラは、アプリケーション、(コントローラがモジュールに属する場合は) モジュール、そしてコントローラの `beforeAction()` メソッドをこの順で呼び出す。
* どれか一つの呼び出しが false を返した場合は、残りのまだ呼ばれていない `beforeAction()` メソッドはスキップされ、アクションの実行はキャンセルされる。
* どれか一つの呼び出しが `false` を返した場合は、残りのまだ呼ばれていない `beforeAction()` メソッドはスキップされ、アクションの実行はキャンセルされる。
* デフォルトでは、それぞれの `beforeAction()` メソッドは、ハンドラをアタッチすることが可能な `beforeAction` イベントをトリガする。
4. コントローラがアクションを実行する。
* アクションパラメータが解析されて、リクエストデータからデータが投入される。

2
docs/guide-ja/structure-filters.md

@ -60,7 +60,7 @@ public function behaviors()
新しいアクションフィルタを作成するためには、[[yii\base\ActionFilter]] を拡張して、[[yii\base\ActionFilter::beforeAction()|beforeAction()]] および/または [[yii\base\ActionFilter::afterAction()|afterAction()]] メソッドをオーバーライドします。
前者はアクションが走る前に実行され、後者は走った後に実行されます。
[[yii\base\ActionFilter::beforeAction()|beforeAction()]] の返り値が、アクションが実行されるべきか否かを決定します。
返り値が false である場合、このフィルタの後に続くフィルタはスキップされ、アクションは実行を中止されます。
返り値が `false` である場合、このフィルタの後に続くフィルタはスキップされ、アクションは実行を中止されます。
次の例は、アクションの実行時間をログに記録するフィルタを示すものです。

4
docs/guide-ja/structure-models.md

@ -37,7 +37,7 @@ echo $model->name;
```
また、配列の要素にアクセスするようして、属性にアクセスすることも出来ます。
これは、[[yii\base\Model]] が [ArrayAccess インターフェイス](http://php.net/manual/ja/class.arrayaccess.php) と [ArrayIterator クラス](http://jp2.php.net/manual/ja/class.arrayiterator.php) をサポートしている恩恵です。
これは、[[yii\base\Model]] が [ArrayAccess インターフェイス](http://php.net/manual/ja/class.arrayaccess.php) と [Traversable インターフェイス](http://jp2.php.net/manual/ja/class.traversable.php) をサポートしている恩恵です。
```php
$model = new \app\models\ContactForm;
@ -46,7 +46,7 @@ $model = new \app\models\ContactForm;
$model['name'] = 'example';
echo $model['name'];
// 属性に反復アクセスす
// モデルは foreach で中身をたどることが出来
foreach ($model as $name => $value) {
echo "$name: $value\n";
}

2
docs/guide-ja/structure-modules.md

@ -177,7 +177,7 @@ $module = MyModuleClass::getInstance();
ここで `MyModuleClass` は、当該モジュールクラスの名前を指すものです。
`getInstance()` メソッドは、現在リクエストされているモジュールクラスのインスタンスを返します。
モジュールがリクエストされていない場合は、このメソッドは null を返します。
モジュールがリクエストされていない場合は、このメソッドは `null` を返します。
モジュールクラスの新しいインスタンスを手動で作成しようとしてはいけないことに注意してください。
手動で作成したインスタンスは、リクエストに対するレスポンスとして Yii によって作成されたインスタンスとは別のものになります。

2
docs/guide-ja/structure-views.md

@ -596,7 +596,7 @@ $this->registerLinkTag([
これらのイベントに反応することによって、ビューにコンテントを注入したり、エンドユーザに送信される前にレンダリング結果を加工したりすることが出来ます。
- [[yii\base\View::EVENT_BEFORE_RENDER|EVENT_BEFORE_RENDER]]: コントローラでファイルをレンダリングする前にトリガされます。
このイベントのハンドラは、[[yii\base\ViewEvent::isValid]] を false にセットして、レンダリングのプロセスをキャンセルすることが出来ます。
このイベントのハンドラは、[[yii\base\ViewEvent::isValid]] を `false` にセットして、レンダリングのプロセスをキャンセルすることが出来ます。
- [[yii\base\View::EVENT_AFTER_RENDER|EVENT_AFTER_RENDER]]: ファイルのレンダリングの後、[[yii\base\View::afterRender()]] を呼ぶことによってトリガされます。
このイベントのハンドラは、レンダリング結果をプロパティ [[yii\base\ViewEvent::output]] を通じて取得して、それを修正してレンダリング結果を変更することが出来ます。
- [[yii\base\View::EVENT_BEGIN_PAGE|EVENT_BEGIN_PAGE]]: レイアウトの中で [[yii\base\View::beginPage()]] を呼ぶことによってトリガされます。

4
docs/guide-ja/test-overview.md

@ -3,11 +3,11 @@
テストはソフトウェア開発の重要な部分です。
気付いているか否かにかかわらず、私たちは継続的にテストをしています。
例えば、PHP でクラスを書くとき、私たちはステップごとにデバッグしたり、または単純に echo 文や die 文を使ったりして、実装が最初の計画通りに動作することを検証します。
例えば、PHP でクラスを書くとき、私たちはステップごとにデバッグしたり、または単純に `echo` 文や `die` 文を使ったりして、実装が最初の計画通りに動作することを検証します。
ウェブアプリケーションの場合は、何らかのテストデータをフォームに入力して、ページが期待通りにユーザと相互作用をすることを確認します。
テストを実行するプロセスを自動化して、何かを検証する必要があるときは、いつでも、それを代行してくれるコードを呼び出すだけでよいようにすることが出来ます。
結果が計画したものと合致することを検証するコードがテストと呼ばれ、それを作成して更に実行するプロセスがテスト自動化として知られています。
結果が計画したものと合致することを検証するコードが *テスト* と呼ばれ、それを作成して更に実行するプロセスが *テスト自動化* として知られています。
このテストの章の主題は、このテストの自動化です。

99
docs/guide-ja/tutorial-core-validators.md

@ -34,12 +34,12 @@ public function rules()
このバリデータは、入力値が真偽値であるかどうかをチェックします。
- `trueValue`: *true* を表す値。デフォルト値は `'1'`
- `falseValue`: *false* を表す値。デフォルト値は `'0'`
- `trueValue`: `true` を表す値。デフォルト値は `'1'`
- `falseValue`: `false` を表す値。デフォルト値は `'0'`
- `strict`: 入力値の型が `trueValue``falseValue` の型と一致しなければならないかどうか。デフォルト値は `false`
> Note: HTML フォームで送信されたデータ入力値は全て文字列であるため、通常は、[[yii\validators\BooleanValidator::strict|strict]] プロパティは false のままにすべきです。
> Note: HTML フォームで送信されたデータ入力値は全て文字列であるため、通常は、[[yii\validators\BooleanValidator::strict|strict]] プロパティは `false` のままにすべきです。
## [[yii\captcha\CaptchaValidator|captcha]] <span id="captcha"></span>
@ -52,9 +52,9 @@ public function rules()
このバリデータは、通常、[[yii\captcha\CaptchaAction]] および [[yii\captcha\Captcha]] と一緒に使われ、入力値が [[yii\captcha\Captcha|CAPTCHA]] ウィジェットによって表示された検証コードと同じであることを確認します。
- `caseSensitive`: 検証コードの比較で大文字と小文字を区別するかどうか。デフォルト値は false。
- `caseSensitive`: 検証コードの比較で大文字と小文字を区別するかどうか。デフォルト値は `false`
- `captchaAction`: CAPTCHA 画像を表示する [[yii\captcha\CaptchaAction|CAPTCHA アクション]] に対応する [ルート](structure-controllers.md#routes)。デフォルト値は `'site/captcha'`
- `skipOnEmpty`: 入力値が空のときに検証をスキップできるかどうか。デフォルト値は false で、入力が必須であることを意味します。
- `skipOnEmpty`: 入力値が空のときに検証をスキップできるかどうか。デフォルト値は `false` で、入力が必須であることを意味します。
## [[yii\validators\CompareValidator|compare]] <span id="compare"></span>
@ -64,8 +64,11 @@ public function rules()
// "password" 属性の値が "password_repeat" 属性の値と同じであるかどうか検証する
['password', 'compare'],
// 上記と同じだが、比較する属性を明示的に指定
['password', 'compare', 'compareAttribute' => 'password_repeat'],
// "age" が 30 以上であるかどうか検証する
['age', 'compare', 'compareValue' => 30, 'operator' => '>='],
['age', 'compare', 'compareValue' => 30, 'operator' => '>=', 'type' => 'number'],
]
```
@ -86,7 +89,9 @@ public function rules()
* `>=`: 検証される値が比較される値よりも大きいか等しいことを検証する。
* `<`: 検証される値が比較される値よりも小さいことを検証する。
* `<=`: 検証される値が比較される値よりも小さいか等しいことを検証する。
- `type`: デフォルトの比較タイプは '[[yii\validators\CompareValidator::TYPE_STRING|string]]' (文字列) であり、その場合、値は 1 バイトごとに比較されます。
数値を比較する場合は、必ず [[yii\validators\CompareValidator::$type|$type]] を '[[yii\validators\CompareValidator::TYPE_NUMBER|number]]' に設定して、数値としての比較を有効にして下さい。
### 日付の値を比較する
@ -111,9 +116,14 @@ compare バリデータは、文字列や数値を比較するためにしか使
## [[yii\validators\DateValidator|date]] <span id="date"></span>
[[yii\validators\DateValidator|date]] バリデータには 3 つの異なるショートカットがあります。
```php
[
[['from_date', 'to_date'], 'date'],
[['from_datetime', 'to_datetime'], 'datetime'],
[['some_time'], 'time'],
]
```
@ -133,6 +143,9 @@ compare バリデータは、文字列や数値を比較するためにしか使
バージョン 2.0.4 以降では、[[yii\validators\DateValidator::$timestampAttributeFormat|$timestampAttributeFormat]] と [[yii\validators\DateValidator::$timestampAttributeTimeZone|$timestampAttributeTimeZone]] を使って、この属性に対するフォーマットとタイムゾーンを指定することが出来ます。
`timestampAttribute` を使う場合、入力値が UNIX タイムスタンプに変換されること、そして、UNIX タイムスタンプは定義により UTC であることに注意して下さい。
すなわち、[[yii\validators\DateValidator::timeZone|入力のタイムゾーン]] から UTC への変換が実行されます。
- バージョン 2.0.4 以降では、タイムスタンプの [[yii\validators\DateValidator::$min|最小値]] または [[yii\validators\DateValidator::$max|最大値]] を指定することも出来ます。
入力が必須でない場合には、date バリデータに加えて、default バリデータ (デフォルト値フィルタ) を追加すれば、空の入力値が `null` として保存されることを保証することが出来ます。
@ -153,7 +166,7 @@ compare バリデータは、文字列や数値を比較するためにしか使
// 空のときは "country" を "USA" にする
['country', 'default', 'value' => 'USA'],
// 空のときは "from" と "to" に今日から三日後・六日後の日付にす
// 空のときは "from" と "to" に今日から三日後・六日後の日付を入れ
[['from', 'to'], 'default', 'value' => function ($model, $attribute) {
return date('Y-m-d', strtotime($attribute === 'to' ? '+3 days' : '+6 days'));
}],
@ -214,7 +227,7 @@ function foo($model, $attribute) {
配列の最初の要素がバリデータのクラス名かエイリアスを指定します。
配列の残りの「名前・値」のペアが、バリデータオブジェクトを構成するのに使われます。
- `allowMessageFromRule`: 埋め込まれた検証規則によって返されるエラーメッセージを使うかどうか。
デフォルト値は true です。これが false の場合は、`message` をエラーメッセージとして使います。
デフォルト値は `true` です。これが `false` の場合は、`message` をエラーメッセージとして使います。
> Note: 属性が配列でない場合は、検証が失敗したと見なされ、`message` がエラーメッセージとして返されます。
@ -230,12 +243,12 @@ function foo($model, $attribute) {
このバリデータは、入力値が有効なメールアドレスであるかどうかをチェックします。
- `allowName`: メールアドレスに表示名 (例えば、`John Smith <john.smith@example.com>`) を許容するか否か。デフォルト値は false。
- `allowName`: メールアドレスに表示名 (例えば、`John Smith <john.smith@example.com>`) を許容するか否か。デフォルト値は `false`
- `checkDNS`: メールのドメインが存在して A または MX レコードを持っているかどうかをチェックするか否か。
このチェックは、メールアドレスが実際には有効なものでも、一時的な DNS の問題によって失敗する場合があることに注意してください。
デフォルト値は false。
デフォルト値は `false`
- `enableIDN`: 検証のプロセスが IDN (国際化ドメイン名) を考慮に入れるか否か。
デフォルト値は false。
デフォルト値は `false`
IDN のバリデーションを使用するためには、`intl` PHP 拡張をインストールして有効化する必要があることに注意してください。そうしないと、例外が投げられます。
@ -287,9 +300,9 @@ function foo($model, $attribute) {
または、`function ($query)` というシグニチャを持つ無名関数でも構いません。
`$query` は関数の中で修正できる [[yii\db\Query|Query]] オブジェクトです。
- `allowArray`: 入力値が配列であることを許容するか否か。
デフォルト値は false。
このプロパティが true で入力値が配列であった場合は、配列の全ての要素がターゲットのカラムに存在しなければなりません。
`targetAttribute` を配列で指定して複数のカラムに対して検証しようとしている場合は、このプロパティを true に設定することが出来ないことに注意してください。
デフォルト値は `false`
このプロパティが `true` で入力値が配列であった場合は、配列の全ての要素がターゲットのカラムに存在しなければなりません。
`targetAttribute` を配列で指定して複数のカラムに対して検証しようとしている場合は、このプロパティを `true` に設定することが出来ないことに注意してください。
## [[yii\validators\FileValidator|file]] <span id="file"></span>
@ -307,24 +320,24 @@ function foo($model, $attribute) {
- `extensions`: アップロードを許可されるファイル名拡張子のリスト。
リストは、配列、または、空白かカンマで区切られたファイル名拡張子からなる文字列 (例えば、"gif, jpg") で指定することが出来ます。
拡張子名は大文字と小文字を区別しません。
デフォルト値は null であり、すべてのファイル名拡張子が許可されることを意味します。
デフォルト値は `null` であり、すべてのファイル名拡張子が許可されることを意味します。
- `mimeTypes`: アップロードを許可されるファイルの MIME タイプのリスト。
リストは、配列、または、空白かカンマで区切られたファイルの MIME タイプからなる文字列 (例えば、"image/jpeg, image/png") で指定することが出来ます。
特殊文字 `*` によるワイルドカードのマスクを使って、一群の MIME タイプに一致させることも出来ます。
例えば `image/*` は、`image/` で始まる全ての MIME タイプ (`image/jpeg`, `image/png` など) を通します。
MIME タイプ名は大文字と小文字を区別しません。
デフォルト値は null であり、すべての MIME タイプが許可されることを意味します。
デフォルト値は `null` であり、すべての MIME タイプが許可されることを意味します。
MIME タイプの詳細については、[一般的なメディアタイプ](http://en.wikipedia.org/wiki/Internet_media_type#List_of_common_media_types) を参照してください。
- `minSize`: アップロードされるファイルに要求される最小限のバイト数。
デフォルト値は null であり、下限値が無いことを意味します。
デフォルト値は `null` であり、下限値が無いことを意味します。
- `maxSize`: アップロードされるファイルに許可される最大限のバイト数。
デフォルト値は null であり、上限値が無いことを意味します。
デフォルト値は `null` であり、上限値が無いことを意味します。
- `maxFiles`: 指定された属性が保持しうる最大限のファイル数。
デフォルト値は 1 であり、入力値がアップロードされた一つだけのファイルでなければならないことを意味します。
この値が 2 以上である場合は、入力値は最大で `maxFiles` 数のアップロードされたファイルからなる配列でなければなりません。
- `checkExtensionByMimeType`: ファイルの MIME タイプでファイル拡張子をチェックするか否か。
MIME タイプのチェックから導かれる拡張子がアップロードされたファイルの拡張子と違う場合に、そのファイルは無効であると見なされます。
デフォルト値は true であり、そのようなチェックが行われることを意味します。
デフォルト値は `true` であり、そのようなチェックが行われることを意味します。
`FileValidator` は [[yii\web\UploadedFile]] と一緒に使用されます。
ファイルのアップロードおよびアップロードされたファイルの検証の実行に関する完全な説明は、[ファイルをアップロードする](input-file-upload.md) の節を参照してください。
@ -353,8 +366,8 @@ function foo($model, $attribute) {
関数のシグニチャは ``function ($value) { return $newValue; }` でなければなりません。
このプロパティは必須項目です。
- `skipOnArray`: 入力値が配列である場合にフィルタをスキップするか否か。
デフォルト値は false。
フィルタが配列の入力を処理できない場合は、このプロパティを true に設定しなければなりません。
デフォルト値は `false`
フィルタが配列の入力を処理できない場合は、このプロパティを `true` に設定しなければなりません。
そうしないと、何らかの PHP エラーが生じ得ます。
> Tip: 入力値をトリムしたい場合は、[trim](#trim) バリデータを直接使うことが出来ます。
@ -384,10 +397,10 @@ function foo($model, $attribute) {
これは [file](#file) バリデータを拡張するものであり、従って、そのプロパティの全てを継承しています。
それに加えて、画像の検証の目的に特化した次のプロパティをサポートしています。
- `minWidth`: 画像の幅の最小値。デフォルト値は null であり、下限値がないことを意味します。
- `maxWidth`: 画像の幅の最大値。デフォルト値は null であり、上限値がないことを意味します。
- `minHeight`: 画像の高さの最小値。デフォルト値は null であり、下限値がないことを意味します。
- `maxHeight`: 画像の高さの最大値。デフォルト値は null であり、上限値がないことを意味します。
- `minWidth`: 画像の幅の最小値。デフォルト値は `null` であり、下限値がないことを意味します。
- `maxWidth`: 画像の幅の最大値。デフォルト値は `null` であり、上限値がないことを意味します。
- `minHeight`: 画像の高さの最小値。デフォルト値は `null` であり、下限値がないことを意味します。
- `maxHeight`: 画像の高さの最大値。デフォルト値は `null` であり、上限値がないことを意味します。
## [[yii\validators\IpValidator|ip]] <span id="ip"></span>
@ -411,26 +424,26 @@ function foo($model, $attribute) {
バリデータは以下の構成オプションを持っています。
- `ipv4`: 検証の対象となる値が IPv4 アドレスであってよいか否か。デフォルト値は true。
- `ipv6`: 検証の対象となる値が IPv6 アドレスであってよいか否か。デフォルト値は true。
- `subnet`: アドレスが `192.168.10.0/24` のような CIDR サブネットを持つ IP であってよいか否か。whether the address can be an IP with CIDR subnet, like `192.168.10.0/24`
- `ipv4`: 検証の対象となる値が IPv4 アドレスであってよいか否か。デフォルト値は `true`
- `ipv6`: 検証の対象となる値が IPv6 アドレスであってよいか否か。デフォルト値は `true`
- `subnet`: アドレスが `192.168.10.0/24` のような CIDR サブネットを持つ IP であってよいか否か。
* `true` - サブネットが必要。CIDR の無いアドレスは却下されます
* `false` - アドレスは CIDR を伴ってはいけません
* `null` - CIDR は有っても無くても構いません
デフォルト値は false。
デフォルト値は `false`
- `normalize`: CIDR を持たないアドレスに、最も短い (IPv4 では 32、IPv6 では 128) CIDR プレフィクスを追加するか否か。
`subnet``false` 以外の場合にのみ動作します。
例えば、
* `10.0.1.5``10.0.1.5/32` に正規化され、
* `2008:db0::1``2008:db0::1/128` に正規化されます
デフォルト値は false。
デフォルト値は `false`
- `negation`: 検証の対象となるアドレスが先頭に否定文字 `!` を持つことが出来るか否か。
デフォルト値は false。
デフォルト値は `false`
- `expandIPv6`: IPv6 アドレスを完全な記法に展開するか否か。
例えば、`2008:db0::1` は `2008:0db0:0000:0000:0000:0000:0000:0001` に展開されます。
デフォルト値は false。
デフォルト値は `false`
- `ranges`: 許容または禁止される IPv4 または IPv6 の範囲の配列。
配列が空の場合、またはこのオプションが設定されていない場合は、全ての IP アドレスが許容されます。
@ -482,11 +495,11 @@ IPv4 アドレス `192.168.10.128` も、制約の前にリストされている
- `range`: 与えられた値のリスト。この中に、入力値がなければならない。
- `strict`: 入力値と所与の値の比較が厳密でなければならない (型と値の両方が同じでなければならない) かどうか。
デフォルト値は false。
- `not`: 検証結果を反転すべきか否か。デフォルト値は false。
このプロパティが true に設定されているときは、入力値が所与の値のリストにない場合に検証が成功したとされます。
デフォルト値は `false`
- `not`: 検証結果を反転すべきか否か。デフォルト値は `false`
このプロパティが `true` に設定されているときは、入力値が所与の値のリストにない場合に検証が成功したとされます。
- `allowArray`: 入力値が配列であることを許可するかどうか。
このプロパティが true であるときに、入力値が配列である場合は、配列の全ての要素が所与の値のリストにある必要があり、そうでなければ検証は失敗します。
このプロパティが `true` であるときに、入力値が配列である場合は、配列の全ての要素が所与の値のリストにある必要があり、そうでなければ検証は失敗します。
## [[yii\validators\NumberValidator|integer]] <span id="integer"></span>
@ -549,10 +562,10 @@ IPv4 アドレス `192.168.10.128` も、制約の前にリストされている
- `requiredValue`: 入力値として要求される値。
このプロパティが設定されていない場合は、入力値が空ではいけないことを意味します。
- `strict`: 値を検証するときに、データ型をチェックするかどうか。デフォルト値は false。
`requiredValue` が設定されていない場合、このプロパティが true であるときは、バリデータは入力値が厳密な意味で null であるかどうかをチェックします。
一方、このプロパティが false であるときは、値が空か否かの判断に緩い規則を使います。
`requiredValue` が設定されている場合、このプロパティが true であるときは、入力値と `requiredValue` を比較するときに型のチェックを行います。
- `strict`: 値を検証するときに、データ型をチェックするかどうか。デフォルト値は `false`
`requiredValue` が設定されていない場合、このプロパティが `true` であるときは、バリデータは入力値が厳密な意味で `null` であるかどうかをチェックします。
一方、このプロパティが `false` であるときは、値が空か否かの判断に緩い規則を使います。
`requiredValue` が設定されている場合、このプロパティが `true` であるときは、入力値と `requiredValue` を比較するときに型のチェックを行います。
> Info: 値が空であるか否かを決定する方法については、独立したトピックとして、[空の入力値を扱う](input-validation.md#handling-empty-inputs) の節でカバーされています。
@ -662,9 +675,9 @@ IPv4 アドレス `192.168.10.128` も、制約の前にリストされている
- `validSchemes`: 有効と見なされるべき URI スキームを指定する配列。
デフォルト値は `['http', 'https']` であり、`http` と `https` の URL がともに有効と見なされることを意味します。
- `defaultScheme`: 入力値がスキームの部分を持たないときに前置されるデフォルトの URI スキーム。
デフォルト値は null であり、入力値を修正しないことを意味します。
デフォルト値は `null` であり、入力値を修正しないことを意味します。
- `enableIDN`: バリデータが IDN (国際化ドメイン名) を考慮すべきか否か。
デフォルト値は false。
デフォルト値は `false`
IDN のバリデーションを使用するためには、`intl` PHP 拡張をインストールして有効化する必要があることに注意してください。
そうしないと、例外が投げられます。

19
docs/guide-ja/tutorial-mailing.md

@ -50,9 +50,9 @@ Yii::$app->mailer->compose()
```php
$message = Yii::$app->mailer->compose();
if (Yii::$app->user->isGuest) {
$message->setFrom('from@domain.com')
$message->setFrom('from@domain.com');
} else {
$message->setFrom(Yii::$app->user->identity->email)
$message->setFrom(Yii::$app->user->identity->email);
}
$message->setTo(Yii::$app->params['adminEmail'])
->setSubject('メッセージの題')
@ -60,9 +60,9 @@ $message->setTo(Yii::$app->params['adminEmail'])
->send();
```
> Note: すべての 'mailer' エクステンションは、二つの主要なクラス、すなわち、'Mailer' と 'Message' のセットとして提供されます。
'Mailer' は常に 'Message' のクラス名と仕様を知っています。
'Message' オブジェクトのインスタンスを直接に作成しようとしてはいけません。常に `compose()` メソッドを使って作成してください。
> Note: すべての `mailer` エクステンションは、二つの主要なクラス、すなわち、`Mailer` と `Message` のセットとして提供されます。
`Mailer` は常に `Message` のクラス名と仕様を知っています。
`Message` オブジェクトのインスタンスを直接に作成しようとしてはいけません。常に `compose()` メソッドを使って作成してください。
いくつかのメッセージを一度に送信することも出来ます。
@ -83,7 +83,7 @@ Yii::$app->mailer->sendMultiple($messages);
----------------------------
Yii は実際のメールメッセージを特別なビューファイルによって作成することを許容しています。
デフォルトでは、それらのファイルは '@app/mail' というパスに配置されなければなりません。
デフォルトでは、それらのファイルは `@app/mail` というパスに配置されなければなりません。
以下はメールビューファイルの内容の例です。
@ -92,7 +92,6 @@ Yii は実際のメールメッセージを特別なビューファイルによ
use yii\helpers\Html;
use yii\helpers\Url;
/* @var $this \yii\web\View ビューコンポーネントのインスタンス */
/* @var $message \yii\mail\BaseMessage 新しく作成されたメールメッセージのインスタンス */
@ -188,7 +187,7 @@ $message->attachContent('添付される内容', ['fileName' => 'attach.txt', 'c
--------------
`embed()` メソッドを使って、メッセージのコンテントに画像を埋め込むことが出来ます。
このメソッドは添付ファイルの ID を返しますので、それを 'img' タグで使わなければなりません。
このメソッドは添付ファイルの ID を返しますので、それを `img` タグで使わなければなりません。
このメソッドはビューファイルによってメッセージのコンテントを作成するときに簡単に使うことが出来ます。
```php
@ -210,7 +209,7 @@ Yii::$app->mailer->compose('embed-email', ['imageFileName' => '/path/to/image.jp
開発者は、実際にどのようなメールがアプリケーションによって送信されたか、その内容はどのようなものであったか、等をチェックしなければならないことが多くあります。
Yii は、そのようなチェックが出来ることを `yii\mail\BaseMailer::useFileTransport` によって保証しています。
このオプションを有効にすると、メールのメッセージデータが、通常のように送信される代りに、ローカルファイルに強制的に保存されます。
ファイルは、`yii\mail\BaseMailer::fileTransportPath`、デフォルトでは '@runtime/mail' の下に保存されます。
ファイルは、`yii\mail\BaseMailer::fileTransportPath`、デフォルトでは `@runtime/mail` の下に保存されます。
> Note: メッセージをファイルに保存するか、実際の受信者に送信するか、どちらかを選ぶことが出来ますが、両方を同時に実行することは出来ません。
@ -224,7 +223,7 @@ Yii は、そのようなチェックが出来ることを `yii\mail\BaseMailer:
------------------------------------------
あなた自身のカスタムメールソリューションを作成するためには、二つのクラスを作成する必要があります。
すなわち、一つは 'Mailer' であり、もう一つは 'Message' です。
すなわち、一つは `Mailer` であり、もう一つは `Message` です。
`yii\mail\BaseMailer``yii\mail\BaseMessage` をあなたのソリューションの基底クラスとして使うことが出来ます。
これらのクラスが、このガイドで説明された基本的なロジックを既に持っています。
しかし、それを使用することは強制されていません。

4
docs/guide-ja/tutorial-performance-tuning.md

@ -13,7 +13,7 @@ PHP 環境を正しく構成することは非常に重要です。
- 最新の安定した PHP バージョンを使うこと。
使用する PHP のメジャーリリースを上げると、顕著なパフォーマンスの改善がもたらされることがあります。
- [Opcache](http://php.net/opcache) (PHP 5.5 以降) または [APC](http://ru2.php.net/apc) (PHP 5.4 以前) を使って、バイトコードキャッシュを有効にすること。
- [Opcache](http://php.net/opcache) (PHP 5.5 以降) または [APC](http://php.net/apc) (PHP 5.4) を使って、バイトコードキャッシュを有効にすること。
バイトコードキャッシュによって、リクエストが入ってくるたびに PHP スクリプトを解析してインクルードする時間の浪費を避けることが出来ます。
- [`realpath()` キャッシュをチューニングする](https://github.com/samdark/realpath_cache_tuner).
@ -29,7 +29,7 @@ Yii は、`YII_DEBUG` という名前の定数の値を使って、デバッグ
defined('YII_DEBUG') or define('YII_DEBUG', false);
```
> Info: `YII_DEBUG` のデフォルト値は false です。
> Info: `YII_DEBUG` のデフォルト値は `false` です。
従って、アプリケーションコードの他のどこかでこのデフォルト値を変更していないと確信できるなら、単に上記の行を削除してデバッグモードを無効にしても構いません。
## キャッシュのテクニックを使う <span id="using-caching"></span>

2
docs/guide-ru/README.md

@ -188,7 +188,7 @@ All Rights Reserved.
* [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)
* [Виджеты Bootstrap](https://github.com/yiisoft/yii2-bootstrap/blob/master/docs/guide-ru/README.md)
* [Виджеты Jquery UI](https://github.com/yiisoft/yii2-jui/blob/master/docs/guide/README.md)

2
docs/guide-ru/concept-di-container.md

@ -162,7 +162,7 @@ $reader = $container->get('app\storage\DocumentsReader);
```
> Tip: Начиная с версии 2.0.11 контейнер может быть настроен в декларативном стиле через конфигурацию приложения.
Как это сделать ищите в подразделе [Конфигурация приложения](concept-service-locator.md#application-configurations)
Как это сделать ищите в подразделе [Конфигурация приложения](concept-configurations.md#Конфигурация-приложения-)
раздела [Конфигурации](concept-configurations.md).
Вроде всё работает, но если нам необходимо создать экземпляр класса `DocumentWriter`, придётся скопировать код,

2
docs/guide-ru/db-active-record.md

@ -488,7 +488,7 @@ $customer->loadDefaultValues();
Однако, механизм приведения типов имеет несколько ограничений:
* Числа с плавающей точкой не будут обработаны, а будут представленны как строки, в противном случае они могут потерять точность.
* Ковертация целых чисел завист от разрядности используемой операциооной системы. В частности: значения колонок, объявленных
* Конвертация целых чисел зависит от разрядности используемой операциооной системы. В частности: значения колонок, объявленных
как 'unsigned integer' или 'big integer' будут приведены к целому типу PHP только на 64-х разрядных системах, в то время
как на 32-х разрядных - они будут представленны как строки.

2
docs/guide/db-active-record.md

@ -1626,7 +1626,7 @@ class Customer extends \yii\db\ActiveRecord
return null; // this avoid calling a query searching for null primary keys
}
return $this->ordersAggregation[0]['counted'];
return empty($this->ordersAggregation) ? 0 : $this->ordersAggregation[0]['counted'];
}
/**

20
docs/guide/db-migrations.md

@ -191,7 +191,7 @@ In the following all variants of this feature are described.
### Create Table
```php
```
yii migrate/create create_post_table
```
@ -225,7 +225,7 @@ class m150811_220037_create_post_table extends Migration
To create table fields right away, specify them via `--fields` option.
```php
```
yii migrate/create create_post_table --fields="title:string,body:text"
```
@ -262,7 +262,7 @@ class m150811_220037_create_post_table extends Migration
You can specify more field parameters.
```php
```
yii migrate/create create_post_table --fields="title:string(12):notNull:unique,body:text"
```
@ -303,7 +303,7 @@ class m150811_220037_create_post_table extends Migration
Since 2.0.8 the generator supports foreign keys using the `foreignKey` keyword.
```php
```
yii migrate/create create_post_table --fields="author_id:integer:notNull:foreignKey(user),category_id:integer:defaultValue(1):foreignKey,title:string,body:text"
```
@ -426,7 +426,7 @@ If no schema exists, primary key isn't set or is composite, default name `id` wi
### Drop Table
```php
```
yii migrate/create drop_post_table --fields="title:string(12):notNull:unique,body:text"
```
@ -458,7 +458,7 @@ content would contain `addColumn` and `dropColumn` statements necessary.
To add column:
```php
```
yii migrate/create add_position_column_to_post_table --fields="position:integer"
```
@ -479,6 +479,12 @@ class m150811_220037_add_position_column_to_post_table extends Migration
}
```
You can specify multiple columns as follows:
```
yii migrate/create add_xxx_column_yyy_column_to_zzz_table --fields="xxx:integer,yyy:text"
```
### Drop Column
If the migration name is of the form `drop_xxx_column_from_yyy_table` then
@ -510,7 +516,7 @@ class m150811_220037_drop_position_column_from_post_table extends Migration
If the migration name is of the form `create_junction_table_for_xxx_and_yyy_tables` or `create_junction_xxx_and_yyy_tables`
then code necessary to create junction table will be generated.
```php
```
yii migrate/create create_junction_table_for_post_and_tag_tables --fields="created_at:dateTime"
```

8
docs/guide/output-client-scripts.md

@ -46,7 +46,7 @@ instead of adding a new one. If you don't provide it, the JS code itself will be
### Registering script files <span id="script-files"></span>
The arguments for [[yii\web\View::registerJsFile()|registerJsFile()]] are similar to those for
[[yii\web\View::registerCssFile()|registerCssFile()]]. In the above example,
[[yii\web\View::registerCssFile()|registerCssFile()]]. In the following example,
we register the `main.js` file with the dependency on the [[yii\web\JqueryAsset]]. It means that the `main.js` file
will be added AFTER `jquery.js`. Without such dependency specification, the relative order between
`main.js` and `jquery.js` would be undefined and the code would not work.
@ -67,7 +67,7 @@ multiple JS files, which is desirable for high traffic websites.
## Registering CSS <span id="register-css"></span>
Similar to Javascript, you can register CSS using
Similar to JavaScript, you can register CSS using
[[yii\web\View::registerCss()|registerCss()]] or
[[yii\web\View::registerCssFile()|registerCssFile()]].
The former registers a block of CSS code while the latter registers an external CSS file.
@ -170,7 +170,7 @@ variable definition, e.g.:
var yiiOptions = {"appName":"My Yii Application","baseUrl":"/basic/web","language":"en"};
```
In your Javascript code you can now access these like `yiiOptions.baseUrl` or `yiiOptions.language`.
In your JavaScript code you can now access these like `yiiOptions.baseUrl` or `yiiOptions.language`.
### Passing translated messages <span id="translated-messages"></span>
@ -189,7 +189,7 @@ JS
```
The above example code uses PHP
[Heredoc syntax](http://php.net/manual/de/language.types.string.php#language.types.string.syntax.heredoc) for better readability. This also enables better syntax highlighting in most IDEs so it is the
[Heredoc syntax](http://php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc) for better readability. This also enables better syntax highlighting in most IDEs so it is the
preferred way of writing inline JavaScript, especially useful for code that is longer than a single line. The variable `$message` is created in PHP and
thanks to [[yii\helpers\Json::htmlEncode|Json::htmlEncode]] it contains the
string in valid JS syntax, which can be inserted into the JavaScript code to place the dynamic string in the function call to `alert()`.

10
docs/guide/output-data-widgets.md

@ -29,8 +29,8 @@ echo DetailView::widget([
[ // the owner name of the model
'label' => 'Owner',
'value' => $model->owner->name,
'contentOptions' => ['class' => 'bg-red'], // to HTML customize attributes of value tag
'captionOptions' => ['tooltip' => 'Tooltip'], // to HTML customize attributes of label tag
'contentOptions' => ['class' => 'bg-red'], // HTML attributes to customize value tag
'captionOptions' => ['tooltip' => 'Tooltip'], // HTML attributes to customize label tag
],
'created_at:datetime', // creation date formatted as datetime
],
@ -38,8 +38,8 @@ echo DetailView::widget([
```
Remember that unlike [[yii\widgets\GridView|GridView]] which processes a set of models,
[[yii\widgets\DetailView|DetailView]] processes just one. So most of the times there is no need for using closure since
`$model` is the only one model for display and available in view as variable.
[[yii\widgets\DetailView|DetailView]] processes just one. So most of the time there is no need for using closure since
`$model` is the only one model for display and available in view as a variable.
However some cases can make using of closure useful. For example when `visible` is specified and you want to prevent
`value` calculations in case it evaluates to `false`:
@ -600,7 +600,7 @@ $query->andFilterWhere(['LIKE', 'author.name', $this->getAttribute('author.name'
> $query->andFilterWhere(['LIKE', 'au.name', $this->getAttribute('author.name')]);
> ```
>
> The same is `true` for the sorting definition:
> The same is true for the sorting definition:
>
> ```php
> $dataProvider->sort->attributes['author.name'] = [

2
docs/guide/runtime-routing.md

@ -43,7 +43,7 @@ The [[yii\web\UrlManager|URL manager]] supports two URL formats:
- the default URL format;
- the pretty URL format.
The default URL format uses a query parameter named `r` to represent the route and normal query parameters
The default URL format uses a [[yii\web\UrlManager::$routeParam|query parameter]] named `r` to represent the route and normal query parameters
to represent the query parameters associated with the route. For example, the URL `/index.php?r=post/view&id=100` represents
the route `post/view` and the `id` query parameter `100`. The default URL format does not require any configuration of
the [[yii\web\UrlManager|URL manager]] and works in any Web server setup.

2
docs/guide/runtime-sessions-cookies.md

@ -200,7 +200,7 @@ $session->setFlash('postDeleted', 'You have successfully deleted your post.');
echo $session->getFlash('postDeleted');
// Request #3
// $result will be `false` since the flash message was automatically deleted
// $result will be false since the flash message was automatically deleted
$result = $session->hasFlash('postDeleted');
```

10
docs/guide/structure-assets.md

@ -349,9 +349,9 @@ return [
You can also disable *all* asset bundles by setting [[yii\web\AssetManager::bundles]] as `false`.
Keep in mind that customization made via [[yii\web\AssetManager::bundles]] applied at the creation of the asset bundle, e.g.
at object constructor stage. Thus any adjustments, which are made to the bundle object after that, will override the mapping,
which has been setup at [[yii\web\AssetManager::bundles]] level. In particular: adjustments made inside [[yii\web\AssetBundle::init()]]
Keep in mind that customization made via [[yii\web\AssetManager::bundles]] is applied at the creation of the asset bundle, e.g.
at object constructor stage. Thus any adjustments made to the bundle object after that will override the mapping setup at [[yii\web\AssetManager::bundles]] level.
In particular: adjustments made inside [[yii\web\AssetBundle::init()]]
method or over the registered bundle object will take precedence over `AssetManager` configuration.
Here are the examples, where mapping set via [[yii\web\AssetManager::bundles]] makes no effect:
@ -676,7 +676,7 @@ return [
That is, the asset bundle configuration array is saved in `assets-prod.php` for production mode, and
`assets-dev.php` for non-production mode.
> Note: this asset combining mechanism is based on ability of [[yii\web\AssetManager::bundles]] to override the properties
> Note: this asset combining mechanism is based on the ability of [[yii\web\AssetManager::bundles]] to override the properties
of the registered asset bundles. However, as it already has been said above, this ability does not cover asset bundle
adjustments, which are performed at [[yii\web\AssetBundle::init()]] method or after bundle is registered. You should
avoid usage of such dynamic bundles during the asset combining.
@ -761,7 +761,7 @@ the last subsection.
[[yii\web\AssetManager::assetMap]] and want this customization to be applied for the compression source files,
you should include these options to the `assetManager` section inside asset command configuration file.
> Note: while specifying the compression source, you should avoid usage of the asset bundles, which parameters may be
> Note: while specifying the compression source, you should avoid the use of asset bundles whose parameters may be
adjusted dynamically (e.g. at `init()` method or after registration), since they may work incorrectly after compression.

4
docs/guide/tutorial-core-validators.md

@ -26,7 +26,7 @@ In the following, we will describe the main usage and properties of every core v
// checks if "selected" is either 0 or 1, regardless of data type
['selected', 'boolean'],
// checks if "deleted" is of boolean type, either `true` or `false`
// checks if "deleted" is of boolean type, either true or false
['deleted', 'boolean', 'trueValue' => true, 'falseValue' => false, 'strict' => true],
]
```
@ -175,7 +175,7 @@ or `1970-01-01` in the input field of a date picker.
```php
[
// set "age" to be `null` if it is empty
// set "age" to be null if it is empty
['age', 'default', 'value' => null],
// set "country" to be "USA" if it is empty

11
docs/internals/git-workflow.md

@ -47,11 +47,12 @@ If you are going to work with JavaScript:
> Note: JavaScript tests depend on [jsdom](https://github.com/tmpvar/jsdom) library which requires Node.js 4 or newer.
Using of Node.js 6 or 7 is more preferable.
- run `php build/build dev/app basic` to clone the basic app and install composer dependencies for the basic app.
- run `php build/build dev/app basic <fork>` to clone the basic app and install composer dependencies for the basic app.
`<fork>` is URL of your repository fork such as `git@github.com:my_nickname/yii2-app-basic.git`. If you are core framework contributor you may skip specifying fork.
This command will install foreign composer packages as normal but will link the yii2 repo to
the currently checked out repo, so you have one instance of all the code installed.
Do the same for the advanced app if needed: `php build/build dev/app advanced`.
Do the same for the advanced app if needed: `php build/build dev/app advanced <fork>`.
This command will also be used to update dependencies, it runs `composer update` internally.
@ -84,14 +85,14 @@ additional arguments).
To work on extensions you have to clone the extension repository. We have created a command that can do this for you:
```
php build/build dev/ext <extension-name>
php build/build dev/ext <extension-name> <fork>
```
where `<extension-name>` is the name of the extension, e.g. `redis`.
where `<extension-name>` is the name of the extension, e.g. `redis` and `<fork>` is URL of your extension fork such as `git@github.com:my_nickname/yii2-redis.git`. If you are core framework contributor you may skip specifying fork.
If you want to test the extension in one of the application templates, just add it to the `composer.json` of the application as you would
normally do e.g. add `"yiisoft/yii2-redis": "~2.0.0"` to the `require` section of the basic app.
Running `php build/build dev/app basic` will install the extension and its dependencies and create
Running `php build/build dev/app basic <fork>` will install the extension and its dependencies and create
a symlink to `extensions/redis` so you are not working in the composer vendor dir but in the yii2 repository directly.
> Note: The default git repository Urls clone from github via SSH, you may add the `--useHttp` flag to the `build` command

2
framework/BaseYii.php

@ -93,7 +93,7 @@ class BaseYii
*/
public static function getVersion()
{
return '2.0.11-dev';
return '2.0.12-dev';
}
/**

55
framework/CHANGELOG.md

@ -20,6 +20,20 @@ Yii Framework 2 Change Log
- Chg: Moved masked input field widget into separate extension https://github.com/yiisoft/yii2-maskedinput (samdark)
2.0.11 under development
2.0.12 under development
--------------------------
- no changes in this release.
2.0.11.1 February 02, 2017
------------------------
- Bug #11502: Fixed `yii\console\controllers\MessageController` to properly populate missing languages in case of extraction with "db" format (bizley)
- Bug #13489: Fixed button names in ActionColumn to contain proper `Yii::t()` tags and restored missing translations for `el`, `fa`, `ja`, `ru`, and `sk` (cebe, softark)
2.0.11 February 01, 2017
------------------------
- Bug #4113: Error page stacktrace was generating links to private methods which are not part of the API docs (samdark)
@ -30,9 +44,13 @@ Yii Framework 2 Change Log
- Bug #10488: Fixed incorrect behavior of `yii\validation\NumberValidator` when used with locales where decimal separator is comma (quantum13, samdark, rob006)
- Bug #11122: Fixed can not use `orderBy` with aggregate functions like `count` (Ni-san)
- Bug #11771: Fixed semantics of `yii\di\ServiceLocator::__isset()` to match the behavior of `__get()` which fixes inconsistent behavior on newer PHP versions (cebe)
- Bug #12133: Fixed `getDbTargets()` function in `yii\log\migrations\m141106_185632_log_init` that would create a log table correctly (bumstik)
- Bug #12213: Fixed `yii\db\ActiveRecord::unlinkAll()` to respect `onCondition()` of the relational query (silverfire)
- Bug #12345: Fixed `Formatter::asCurrency()` for proper decimal formatting (Oxyaction)
- Bug #12599: Fixed MSSQL fail to work with `nvarbinary`. Enhanced SQL scripts compatibility with older versions (samdark)
- Bug #12681: Changed `data` column type from `text` to `blob` to handle null-byte (`\0`) in serialized RBAC rule properly (silverfire)
- Bug #12703: Fixed `StringHelper::truncateHtml()` non functional when dom PHP extension is disabled (samdark)
- Bug #12713: Fixed `yii\caching\FileDependency` to clear stat cache before reading filemtime (SG5)
- Bug #12714: Fixed `yii\validation\EmailValidator` to prevent false-positives checks when property `checkDns` is set to `true` (silverfire)
- Bug #12735: Fixed `yii\console\controllers\MigrateController` creating multiple primary keys for field `bigPrimaryKey:unsigned` (SG5)
- Bug #12791: Fixed `yii\behaviors\AttributeTypecastBehavior` unable to automatically detect `attributeTypes`, triggering PHP Fatal Error (klimov-paul)
@ -64,9 +82,14 @@ Yii Framework 2 Change Log
- Bug #13231: Fixed `destroy` method in `yii.gridView.js` which did not work as expected (arogachev)
- Bug #13232: Event handlers were not detached with changed selector in `yii.gridView.js` (arogachev)
- Bug #13277: Fixed invalid parsing of `--` ("End of Options" special argument) in CLI (rugabarbo)
- Bug #13287: Fixed translating "and" separator in `UniqueValidator` error message (jetexe)
- Bug #13300: Allow pjax with "data-pjax" with no value in `yii.js` (arogachev)
- Bug #13307: Preventing of race conditions in script filter in `yii.js` works incorrectly (arogachev)
- Bug #13309: Fixes incorrect console width/height detecting with using Stty on Mac (nowm)
- Bug #13310: Handle relative and absolute URLs coincidence in CSS filter in `yii.js` (arogachev)
- Bug #13312: `skipOuterContainers` option was incorrectly passed to pjax in `handleAction` in `yii.js` (arogachev)
- Bug #13326: Fixed wrong background color generation in `BaseConsole::renderColoredString()` (nowm, silverfire)
- Bug #12133: Fixed `getDbTargets()` function in `yii\log\migrations\m141106_185632_log_init` that would create a log table correctly (bumstik)
- Bug #13401: Fixed lack of escaping of request dump at exception screens (samdark)
- Bug #13416: Fixed `yii\web\MultipartFormDataParser` adds an extra newline to every value (klimov-paul)
- Enh #475: Added Bash and Zsh completion support for the `./yii` command (cebe, silverfire)
- Enh #6242: Access to validator in inline validation (arogachev)
@ -74,30 +97,38 @@ Yii Framework 2 Change Log
- Enh #6809: Added `yii\caching\Cache::$defaultDuration` property, allowing to set custom default cache duration (sdkiller)
- Enh #7333: Improved error message for `yii\di\Instance::ensure()` when a component does not exist (cebe)
- Enh #7420: Attributes for prompt generated with `renderSelectOptions` of `\yii\helpers\Html` helper (arogachev)
- Enh #7435: Added `EVENT_BEFORE_RUN`, `EVENT_AFTER_RUN` and corresponding methods to `yii\base\Widget` (petrabarus)
- Enh #7820: Add `or` relation for `targetAttribute` in `yii\validators\UniqueValidator` (developeruz)
- Enh #8293: `yii\db\Query` can be passed to `insert` method in `yii\db\QueryBuilder` (voroks)
- Enh #9053: Added`yii\grid\RadioButtonColumn` (darwinisgod)
- Enh #9162: Added support of closures in `value` for attributes in `yii\widgets\DetailView` (arogachev)
- Enh #10896: Select only primary key when counting records in UniqueValidator (developeruz)
- Enh #10970: Allow omit specifying empty default params on URL creation (rob006)
- Enh #11037: `yii.js` and `yii.validation.js` use `Regexp.test()` instead of `String.match()` (arogachev, nkovacs)
- Enh #11163: Added separate method for client-side validation options `yii\validators\Validator::getClientOptions()` (arogachev)
- Enh #11464: Populate foreign key names from schema (joaoppereira)
- Enh #11697: Added `filterHaving()`, `andFilterHaving()` and `orFilterHaving()` to `yii\db\Query` (nicdnepr, samdark)
- Enh #11756: Added type mapping for `varbinary` data type in MySQL DBMS (silverfire)
- Enh #11758: Implemented Dependency Injection Container configuration using Application configuration array (silverfire)
- Enh #11929: Changed `type` column type from `int` to `smallInt` in RBAC migrations (silverfire)
- Enh #11959: Added `yii\caching\Cache::getOrSet()` method (silverfire)
- Enh #12000: Added EVENT_INIT to widget (user57376)
- Enh #12015: Changed visibility `yii\db\ActiveQueryTrait::createModels()` from private to protected (ArekX, dynasource)
- Enh #12145: Added `beforeCacheResponse` and `afterRestoreResponse` to `yii\filters\PageCache` to be more easily extendable (sergeymakinen)
- Enh #12390: Avoid creating queries with false where condition (`0=1`) when fetching relational data (klimov-paul)
- Enh #12399: Added `ActiveField::addAriaAttributes` property for `aria-required` and `aria-invalid` attributes rendering (Oxyaction, samdark)
- Enh #12419: Added ability to remove root tag and object tags for `yii\web\XmlResponseFormatter` (mhthnz, samdark)
- Enh #12612: Query conditions added with `yii\db\Query::andWhere()` now get appended to the existing conditions if they were already being joined with the `and` operator (brandonkelly)
- Enh #12619: Added catch `Throwable` in `yii\base\ErrorHandler::handleException()`, transactions and simlar places where consistency must be kept after exception (rob006, cebe)
- Enh #12659: Suggest alternatives when console command was not found (mdmunir, cebe)
- Enh #12691: Added support for protocol-relative URLs in `yii\web\UrlRule::$pattern` (erickskrauch)
- Enh #12710: Added `beforeItem` and `afterItem` to `yii\widgets\ListView` (mdmunir, silverfire)
- Enh #12725: Enhanced `yii\widgets\Menu` to allow item option `active` be a Closure (voskobovich, silverfire)
- Enh #12726: `yii\base\Application::$version` converted to `yii\base\Module::$version` virtual property, allowing to specify version as a PHP callback (klimov-paul)
- Enh #12732: Added `is_dir()` validation to `yii\helpers\BaseFileHelper::findFiles()` method (zalatov, silverfire)
- Enh #12738: Added support for creating protocol-relative URLs in `UrlManager::createAbsoluteUrl()` and `Url` helper methods (rob006)
- Enh #12748: Migration generator now tries to fetch reference column name for foreignKey from schema if it's not set explicitly (MKiselev)
- Enh #12750: `yii\widgets\ListView::itemOptions` can be a closure now (webdevsega, silverfire)
- Enh #12758: Added the ability to use instances of `\yii\db\Query` class as values in the `\yii\db\QueryBuilder::insert()` method (PowerGamer1)
- Enh #12771: Skip \yii\rbac\PhpManager::checkAccessRecursive and \yii\rbac\DbManager::checkAccessRecursive if role assignments are empty (Ni-san)
- Enh #12790: Added `scrollToErrorOffset` option for `yii\widgets\ActiveForm` which adds ability to specify offset in pixels when scrolling to error (mg-code)
- Enh #12798: Changed `yii\cache\Dependency::getHasChanged()` (deprecated, to be removed in 2.1) to `yii\cache\Dependency::isChanged()` (dynasource)
@ -113,28 +144,27 @@ Yii Framework 2 Change Log
- Enh #13050: Added `yii\filters\HostControl` allowing protection against 'host header' attacks (klimov-paul, rob006)
- Enh #13074: Improved `yii\log\SyslogTarget` with `$options` to be able to change the default `openlog` options (timbeks)
- Enh #13122: Optimized query for information about foreign keys in `yii\db\oci` (zlakomanoff)
- Enh #13134: Added logging URL rules (bashkarev)
- Enh #13202: Refactor validateAttribute method in UniqueValidator (developeruz)
- Enh #13219: Enhancements for `yii\db\Connection` (Vovan-VE)
- Enh #13219: Enhancements for `yii\db\Connection` (Vovan-VE)
- Added `shuffleMasters` option which adds ability to disable shuffling of masters connections.
- Added `getMaster()` getter and `master` property for getting currently active master connection.
- Extracted `openFromPoolSequentially()` protected method from `openFromPool()` protected method.
- Enh #13264: Added `yii\widgets\InputWidget::$field` field, allowing access to the related `yii\widget\ActiveField` instance (klimov-paul)
- Enh #13266: Added `yii\validators\EachValidator::$stopOnFirstError` allowing addition of more than one error (klimov-paul)
- Enh #13268: Added logging of memory usage (bashkarev)
- Enh #13417: Allow customizing `yii\data\ActiveDataProvider` in `yii\rest\IndexAction` (leandrogehlen)
- Enh #13453: Select only primary key when counting records in UniqueValidator (developeruz)
- Enh: Added constants for specifying `yii\validators\CompareValidator::$type` (cebe)
- Enh: Refactored `yii\web\ErrorAction` to make it reusable (silverfire)
- Enh: Added support for field `yii\console\controllers\BaseMigrateController::$migrationNamespaces` setup from CLI (schmunk42)
- Bug #13287: Fixed translating "and" separator in `UniqueValidator` error message (jetexe)
- Enh #11464: Populate foreign key names from schema (joaoppereira)
- Bug #13401: Fixed lack of escaping of request dump at exception screens (samdark)
- Enh #13417: Allow customizing `yii\data\ActiveDataProvider` in `yii\rest\IndexAction` (leandrogehlen)
- Bug #12599: Fixed MSSQL fail to work with `nvarbinary`. Enhanced SQL scripts compatibility with older versions (samdark)
- Chg #11906: Updated `yii\widgets\MaskedInput` inputmask dependency to `~3.3.3` (samdark)
2.0.10 October 20, 2016
-----------------------
- Bug #7670: Added `yii\web\UrlNormalizer` for normalizing requests with and without trailing slashes (rob006, cronfy, klimov-paul)
- Bug #12345 Fixed `Formatter::asCurrency()` for proper decimal formatting (Oxyaction)
- Bug #7670: Added `UrlNormalizer` for normalizing requests with and without trailing slashes (rob006, cronfy, klimov-paul)
- Bug #9027: Fixed descendant class of `yii\web\UploadedFile` returns parent instances in case invoked after it (andrewnester)
- Bug #9277: Fixed `yii\console\controllers\AssetController` looses custom options of 'target' bundles (petrabarus, klimov-paul)
@ -181,7 +211,6 @@ Yii Framework 2 Change Log
- Bug #12605: Make 'safe' validator work on write-only properties (arthibald, CeBe)
- Bug #12629: Fixed `yii\widgets\ActiveField::widget()` to call `adjustLabelFor()` for `InputWidget` descendants (coderlex)
- Bug #12649: Fixed consistency of `indexBy` handling for `yii\db\Query::column()` (silverfire)
- Bug #12713: Fixed `yii\caching\FileDependency` to clear stat cache before reading filemtime (SG5)
- Enh #384: Added ability to run migration from several locations via `yii\console\controllers\BaseMigrateController::$migrationNamespaces` (klimov-paul)
- Enh #6996: Added `yii\web\MultipartFormDataParser`, which allows proper processing of 'multipart/form-data' encoded non POST requests (klimov-paul)
- Enh #8719: Add support for HTML5 attributes on submitbutton (formaction/formmethod...) for ActiveForm (VirtualRJ)
@ -216,13 +245,11 @@ Yii Framework 2 Change Log
- Enh #12440: Added `yii\base\Event::offAll()` method allowing clear all registered class-level event handlers (klimov-paul)
- Enh #12499: When AJAX validation in enabled, `yii.activeForm.js` will run it forcefully on form submit to display all possible errors (silverfire)
- Enh #12580: Make `yii.js` comply with strict and non-strict javascript mode to allow concatenation with external code (mikehaertl)
- Enh #12612: Query conditions added with `yii\db\Query::andWhere()` now get appended to the existing conditions if they were already being joined with the `and` operator (brandonkelly)
- Enh #12664: Added support for wildcards for `optional` at `yii\filters\auth\AuthMethod` (mg-code)
- Enh #12744: Added `afterInit` event to `yii.activeForm.js` (werew01f)
- Enh #12710: Added `beforeItem` and `afterItem` to `yii\widgets\ListView` (mdmunir, silverfire)
- Enh #12727: Enhanced `yii\widgets\Menu` to allow item option `active` be a Closure (voskobovich, silverfire)
- Enh: Method `yii\console\controllers\AssetController::getAssetManager()` automatically enables `yii\web\AssetManager::forceCopy` in case it is not explicitly specified (pana1990, klimov-paul)
2.0.9 July 11, 2016
-------------------
@ -283,7 +310,6 @@ Yii Framework 2 Change Log
- Enh #11857: `yii\filters\AccessRule::$verbs` can now be configured in upper and lowercase (DrDeath72, samdark)
- Chg #11364: Updated jQuery dependency to include versions `1.12.*` (cebe)
- Chg #11683: Fixed fixture command to work with short syntax. `yii fixture "*, -User"` should be used instead of `yii fixture "*" -User` (Faryshta, samdark)
- Chg #11906: Updated `yii\widgets\MaskedInput` inputmask dependency to `~3.3.3` (samdark)
2.0.8 April 28, 2016
@ -1741,3 +1767,4 @@ Yii Framework 2 Change Log
- [Smarty View Renderer](https://github.com/yiisoft/yii2-smarty)
- [Twig View Renderer](https://github.com/yiisoft/yii2-twig)

404
framework/assets/yii.js

@ -17,13 +17,13 @@
* A module may be structured as follows:
*
* ```javascript
* yii.sample = (function($) {
* window.yii.sample = (function($) {
* var pub = {
* // whether this module is currently active. If false, init() will not be called for this module
* // it will also not be called for all its child modules. If this property is undefined, it means true.
* isActive: true,
* init: function() {
* // ... module initialization code go here ...
* // ... module initialization code goes here ...
* },
*
* // ... other public functions and properties go here ...
@ -32,7 +32,7 @@
* // ... private functions and properties go here ...
*
* return pub;
* })(jQuery);
* })(window.jQuery);
* ```
*
* Using this structure, you can define public and private functions/properties for a module.
@ -46,9 +46,9 @@ window.yii = (function ($) {
/**
* List of JS or CSS URLs that can be loaded multiple times via AJAX requests.
* Each item may be represented as either an absolute URL or a relative one.
* Each item may contain a wildcart matching character `*`, that means one or more
* Each item may contain a wildcard matching character `*`, that means one or more
* any characters on the position. For example:
* - `/css/*.js` will match any file ending with `.js` in the `css` directory of the current web site
* - `/css/*.css` will match any file ending with `.css` in the `css` directory of the current web site
* - `http*://cdn.example.com/*` will match any files on domain `cdn.example.com`, loaded with HTTP or HTTPS
* - `/js/myCustomScript.js?realm=*` will match file `/js/myCustomScript.js` with defined `realm` parameter
*/
@ -56,7 +56,8 @@ window.yii = (function ($) {
/**
* The selector for clickable elements that need to support confirmation and form submission.
*/
clickableSelector: 'a, button, input[type="submit"], input[type="button"], input[type="reset"], input[type="image"]',
clickableSelector: 'a, button, input[type="submit"], input[type="button"], input[type="reset"], ' +
'input[type="image"]',
/**
* The selector for changeable elements that need to support confirmation and form submission.
*/
@ -107,7 +108,7 @@ window.yii = (function ($) {
* @param cancel a callback to be called when the user cancels the confirmation
*/
confirm: function (message, ok, cancel) {
if (confirm(message)) {
if (window.confirm(message)) {
!ok || ok();
} else {
!cancel || cancel();
@ -143,74 +144,70 @@ window.yii = (function ($) {
* 'name2' => 'value2',
* ],
* ],
* ];
* ]);
* ```
*
* @param $e the jQuery representation of the element
* @param event Related event
*/
handleAction: function ($e, event) {
var $form = $e.attr('data-form') ? $('#' + $e.attr('data-form')) : $e.closest('form'),
method = !$e.data('method') && $form ? $form.attr('method') : $e.data('method'),
action = $e.attr('href'),
isValidAction = action && action !== '#',
params = $e.data('params'),
pjax = $e.data('pjax') || 0,
usePjax = pjax !== 0 && $.support.pjax,
pjaxPushState = !!$e.data('pjax-push-state'),
pjaxReplaceState = !!$e.data('pjax-replace-state'),
pjaxTimeout = $e.data('pjax-timeout'),
pjaxScrollTo = $e.data('pjax-scrollto'),
pjaxPushRedirect = $e.data('pjax-push-redirect'),
pjaxReplaceRedirect = $e.data('pjax-replace-redirect'),
pjaxSkipOuterContainers = $e.data('pjax-skip-outer-containers'),
areValidParams = params && $.isPlainObject(params),
pjax = $e.data('pjax'),
usePjax = pjax !== undefined && pjax !== 0 && $.support.pjax,
pjaxContainer,
pjaxOptions = {};
if (usePjax) {
if ($e.data('pjax-container')) {
pjaxContainer = $e.data('pjax-container');
} else {
pjaxContainer = $e.closest('[data-pjax-container=""]');
}
// default to body if pjax container not found
pjaxContainer = $e.data('pjax-container') || $e.closest('[data-pjax-container]');
if (!pjaxContainer.length) {
pjaxContainer = $('body');
}
pjaxOptions = {
container: pjaxContainer,
push: pjaxPushState,
replace: pjaxReplaceState,
scrollTo: pjaxScrollTo,
pushRedirect: pjaxPushRedirect,
replaceRedirect: pjaxReplaceRedirect,
pjaxSkipOuterContainers: pjaxSkipOuterContainers,
timeout: pjaxTimeout,
push: !!$e.data('pjax-push-state'),
replace: !!$e.data('pjax-replace-state'),
scrollTo: $e.data('pjax-scrollto'),
pushRedirect: $e.data('pjax-push-redirect'),
replaceRedirect: $e.data('pjax-replace-redirect'),
skipOuterContainers: $e.data('pjax-skip-outer-containers'),
timeout: $e.data('pjax-timeout'),
originalEvent: event,
originalTarget: $e
}
};
}
if (method === undefined) {
if (action && action != '#') {
if (usePjax) {
$.pjax.click(event, pjaxOptions);
} else {
window.location = action;
}
if (isValidAction) {
usePjax ? $.pjax.click(event, pjaxOptions) : window.location.assign(action);
} else if ($e.is(':submit') && $form.length) {
if (usePjax) {
$form.on('submit',function(e){
$form.on('submit', function (e) {
$.pjax.submit(e, pjaxOptions);
})
});
}
$form.trigger('submit');
}
return;
}
var newForm = !$form.length;
if (newForm) {
if (!action || !/(^\/|:\/\/)/.test(action)) {
action = window.location.href;
var oldMethod,
oldAction,
newForm = !$form.length;
if (!newForm) {
oldMethod = $form.attr('method');
$form.attr('method', method);
if (isValidAction) {
oldAction = $form.attr('action');
$form.attr('action', action);
}
} else {
if (!isValidAction) {
action = pub.getCurrentUrl();
}
$form = $('<form/>', {method: method, action: action});
var target = $e.attr('target');
@ -219,9 +216,10 @@ window.yii = (function ($) {
}
if (!/(get|post)/i.test(method)) {
$form.append($('<input/>', {name: '_method', value: method, type: 'hidden'}));
method = 'POST';
method = 'post';
$form.attr('method', method);
}
if (!/(get|head|options)/i.test(method)) {
if (/post/i.test(method)) {
var csrfParam = pub.getCsrfParam();
if (csrfParam) {
$form.append($('<input/>', {name: csrfParam, value: pub.getCsrfToken(), type: 'hidden'}));
@ -232,49 +230,41 @@ window.yii = (function ($) {
var activeFormData = $form.data('yiiActiveForm');
if (activeFormData) {
// remember who triggers the form submission. This is used by yii.activeForm.js
// Remember the element triggered the form submission. This is used by yii.activeForm.js.
activeFormData.submitObject = $e;
}
// temporarily add hidden inputs according to data-params
if (params && $.isPlainObject(params)) {
$.each(params, function (idx, obj) {
$form.append($('<input/>').attr({name: idx, value: obj, type: 'hidden'}));
if (areValidParams) {
$.each(params, function (name, value) {
$form.append($('<input/>').attr({name: name, value: value, type: 'hidden'}));
});
}
var oldMethod = $form.attr('method');
$form.attr('method', method);
var oldAction = null;
if (action && action != '#') {
oldAction = $form.attr('action');
$form.attr('action', action);
}
if (usePjax) {
$form.on('submit',function(e){
$form.on('submit', function (e) {
$.pjax.submit(e, pjaxOptions);
})
});
}
$form.trigger('submit');
$.when($form.data('yiiSubmitFinalizePromise')).then(
function () {
if (oldAction != null) {
$form.attr('action', oldAction);
}
$form.attr('method', oldMethod);
// remove the temporarily added hidden inputs
if (params && $.isPlainObject(params)) {
$.each(params, function (idx, obj) {
$('input[name="' + idx + '"]', $form).remove();
});
}
$.when($form.data('yiiSubmitFinalizePromise')).then(function () {
if (newForm) {
$form.remove();
return;
}
if (newForm) {
$form.remove();
}
if (oldAction !== undefined) {
$form.attr('action', oldAction);
}
$form.attr('method', oldMethod);
if (areValidParams) {
$.each(params, function (name) {
$('input[name="' + name + '"]', $form).remove();
});
}
);
});
},
getQueryParams: function (url) {
@ -284,67 +274,183 @@ window.yii = (function ($) {
}
var pairs = url.substring(pos + 1).split('#')[0].split('&'),
params = {},
pair,
i;
params = {};
for (i = 0; i < pairs.length; i++) {
pair = pairs[i].split('=');
for (var i = 0, len = pairs.length; i < len; i++) {
var pair = pairs[i].split('=');
var name = decodeURIComponent(pair[0].replace(/\+/g, '%20'));
var value = decodeURIComponent(pair[1].replace(/\+/g, '%20'));
if (name.length) {
if (params[name] !== undefined) {
if (!$.isArray(params[name])) {
params[name] = [params[name]];
}
params[name].push(value || '');
} else {
params[name] = value || '';
if (!name.length) {
continue;
}
if (params[name] === undefined) {
params[name] = value || '';
} else {
if (!$.isArray(params[name])) {
params[name] = [params[name]];
}
params[name].push(value || '');
}
}
return params;
},
initModule: function (module) {
if (module.isActive === undefined || module.isActive) {
if ($.isFunction(module.init)) {
module.init();
}
$.each(module, function () {
if ($.isPlainObject(this)) {
pub.initModule(this);
}
});
if (module.isActive !== undefined && !module.isActive) {
return;
}
if ($.isFunction(module.init)) {
module.init();
}
$.each(module, function () {
if ($.isPlainObject(this)) {
pub.initModule(this);
}
});
},
init: function () {
initCsrfHandler();
initRedirectHandler();
initScriptFilter();
initAssetFilters();
initDataMethods();
},
/**
* Returns the URL of the current page without params and trailing slash. Separated and made public for testing.
* @returns {string}
*/
getBaseCurrentUrl: function () {
return window.location.protocol + '//' + window.location.host;
},
/**
* Returns the URL of the current page. Used for testing, you can always call `window.location.href` manually
* instead.
* @returns {string}
*/
getCurrentUrl: function () {
return window.location.href;
}
};
function initCsrfHandler() {
// automatically send CSRF token for all AJAX requests
$.ajaxPrefilter(function (options, originalOptions, xhr) {
if (!options.crossDomain && pub.getCsrfParam()) {
xhr.setRequestHeader('X-CSRF-Token', pub.getCsrfToken());
}
});
pub.refreshCsrfToken();
}
function initRedirectHandler() {
// handle AJAX redirection
$(document).ajaxComplete(function (event, xhr, settings) {
$(document).ajaxComplete(function (event, xhr) {
var url = xhr && xhr.getResponseHeader('X-Redirect');
if (url) {
window.location = url;
window.location.assign(url);
}
});
}
function initCsrfHandler() {
// automatically send CSRF token for all AJAX requests
$.ajaxPrefilter(function (options, originalOptions, xhr) {
if (!options.crossDomain && pub.getCsrfParam()) {
xhr.setRequestHeader('X-CSRF-Token', pub.getCsrfToken());
function initAssetFilters() {
/**
* Used for storing loaded scripts and information about loading each script if it's in the process of loading.
* A single script can have one of the following values:
*
* - `undefined` - script was not loaded at all before or was loaded with error last time.
* - `true` (boolean) - script was successfully loaded.
* - object - script is currently loading.
*
* In case of a value being an object the properties are:
* - `xhrList` - represents a queue of XHR requests sent to the same URL (related with this script) in the same
* small period of time.
* - `xhrDone` - boolean, acts like a locking mechanism. When one of the XHR requests in the queue is
* successfully completed, it will abort the rest of concurrent requests to the same URL until cleanup is done
* to prevent possible errors and race conditions.
* @type {{}}
*/
var loadedScripts = {};
$('script[src]').each(function () {
var url = getAbsoluteUrl(this.src);
loadedScripts[url] = true;
});
$.ajaxPrefilter('script', function (options, originalOptions, xhr) {
if (options.dataType == 'jsonp') {
return;
}
var url = getAbsoluteUrl(options.url),
forbiddenRepeatedLoad = loadedScripts[url] === true && !isReloadableAsset(url),
cleanupRunning = loadedScripts[url] !== undefined && loadedScripts[url]['xhrDone'] === true;
if (forbiddenRepeatedLoad || cleanupRunning) {
xhr.abort();
return;
}
if (loadedScripts[url] === undefined || loadedScripts[url] === true) {
loadedScripts[url] = {
xhrList: [],
xhrDone: false
};
}
xhr.done(function (data, textStatus, jqXHR) {
// If multiple requests were successfully loaded, perform cleanup only once
if (loadedScripts[jqXHR.yiiUrl]['xhrDone'] === true) {
return;
}
loadedScripts[jqXHR.yiiUrl]['xhrDone'] = true;
for (var i = 0, len = loadedScripts[jqXHR.yiiUrl]['xhrList'].length; i < len; i++) {
var singleXhr = loadedScripts[jqXHR.yiiUrl]['xhrList'][i];
if (singleXhr && singleXhr.readyState !== XMLHttpRequest.DONE) {
singleXhr.abort();
}
}
loadedScripts[jqXHR.yiiUrl] = true;
}).fail(function (jqXHR, textStatus) {
if (textStatus === 'abort') {
return;
}
delete loadedScripts[jqXHR.yiiUrl]['xhrList'][jqXHR.yiiIndex];
var allFailed = true;
for (var i = 0, len = loadedScripts[jqXHR.yiiUrl]['xhrList'].length; i < len; i++) {
if (loadedScripts[jqXHR.yiiUrl]['xhrList'][i]) {
allFailed = false;
}
}
if (allFailed) {
delete loadedScripts[jqXHR.yiiUrl];
}
});
// Use prefix for custom XHR properties to avoid possible conflicts with existing properties
xhr.yiiIndex = loadedScripts[url]['xhrList'].length;
xhr.yiiUrl = url;
loadedScripts[url]['xhrList'][xhr.yiiIndex] = xhr;
});
$(document).ajaxComplete(function () {
var styleSheets = [];
$('link[rel=stylesheet]').each(function () {
var url = getAbsoluteUrl(this.href);
if (isReloadableAsset(url)) {
return;
}
$.inArray(url, styleSheets) === -1 ? styleSheets.push(url) : $(this).remove();
});
});
pub.refreshCsrfToken();
}
function initDataMethods() {
@ -374,13 +480,9 @@ window.yii = (function ($) {
.on('change.yii', pub.changeableSelector, handler);
}
function isReloadable(url) {
var hostInfo = getHostInfo();
function isReloadableAsset(url) {
for (var i = 0; i < pub.reloadableScripts.length; i++) {
var rule = pub.reloadableScripts[i];
rule = rule.charAt(0) === '/' ? hostInfo + rule : rule;
var rule = getAbsoluteUrl(pub.reloadableScripts[i]);
var match = new RegExp("^" + escapeRegExp(rule).split('\\*').join('.*') + "$").test(url);
if (match === true) {
return true;
@ -395,76 +497,18 @@ window.yii = (function ($) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}
function getHostInfo() {
return location.protocol + '//' + location.host;
}
function initScriptFilter() {
var hostInfo = getHostInfo();
var loadedScripts = {};
var scripts = $('script[src]').map(function () {
return this.src.charAt(0) === '/' ? hostInfo + this.src : this.src;
}).toArray();
for (var i = 0, len = scripts.length; i < len; i++) {
loadedScripts[scripts[i]] = true;
}
$.ajaxPrefilter('script', function (options, originalOptions, xhr) {
if (options.dataType == 'jsonp') {
return;
}
var url = options.url.charAt(0) === '/' ? hostInfo + options.url : options.url;
if (url in loadedScripts) {
var item = loadedScripts[url];
// If the concurrent XHR request is running and URL is not reloadable
if (item !== true && !isReloadable(url)) {
// Abort the current XHR request when previous finished successfully
item.done(function () {
if (xhr && xhr.readyState !== 4) {
xhr.abort();
}
});
// Or abort previous XHR if the current one is loaded faster
xhr.done(function () {
if (item && item.readyState !== 4) {
item.abort();
}
});
} else if (!isReloadable(url)) {
xhr.abort();
}
} else {
loadedScripts[url] = xhr.done(function () {
loadedScripts[url] = true;
}).fail(function () {
delete loadedScripts[url];
});
}
});
$(document).ajaxComplete(function (event, xhr, settings) {
var styleSheets = [];
$('link[rel=stylesheet]').each(function () {
if (isReloadable(this.href)) {
return;
}
if ($.inArray(this.href, styleSheets) == -1) {
styleSheets.push(this.href)
} else {
$(this).remove();
}
})
});
/**
* Returns absolute URL based on the given URL
* @param {string} url Initial URL
* @returns {string}
*/
function getAbsoluteUrl(url) {
return url.charAt(0) === '/' ? pub.getBaseCurrentUrl() + url : url;
}
return pub;
})(jQuery);
})(window.jQuery);
jQuery(function () {
yii.initModule(yii);
window.jQuery(function () {
window.yii.initModule(window.yii);
});

1
framework/base/Application.php

@ -21,6 +21,7 @@ use Yii;
* @property string $basePath The root directory of the application.
* @property \yii\caching\Cache $cache The cache application component. Null if the component is not enabled.
* This property is read-only.
* @property array $container Values given in terms of name-value pairs. This property is write-only.
* @property \yii\db\Connection $db The database connection. This property is read-only.
* @property \yii\web\ErrorHandler|\yii\console\ErrorHandler $errorHandler The error handler application
* component. This property is read-only.

2
framework/base/Controller.php

@ -43,7 +43,7 @@ class Controller extends Component implements ViewContextInterface
*/
public $id;
/**
* @var Module $module the module that this controller belongs to.
* @var Module the module that this controller belongs to.
*/
public $module;
/**

3
framework/base/Module.php

@ -32,8 +32,9 @@ use yii\di\ServiceLocator;
* @property string $layoutPath The root directory of layout files. Defaults to "[[viewPath]]/layouts".
* @property array $modules The modules (indexed by their IDs).
* @property string $uniqueId The unique ID of the module. This property is read-only.
* @property string $version The version of this module. Note that the type of this property differs in getter
* and setter. See [[getVersion()]] and [[setVersion()]] for details.
* @property string $viewPath The root directory of view files. Defaults to "[[basePath]]/views".
* @property string|callable $version The version of this module.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0

101
framework/base/Widget.php

@ -27,6 +27,23 @@ use ReflectionClass;
class Widget extends Component implements ViewContextInterface
{
/**
* @event Event an event that is triggered when the widget is initialized via [[init()]].
* @since 2.0.11
*/
const EVENT_INIT = 'init';
/**
* @event WidgetEvent an event raised right before executing a widget.
* You may set [[WidgetEvent::isValid]] to be false to cancel the widget execution.
* @since 2.0.11
*/
const EVENT_BEFORE_RUN = 'beforeRun';
/**
* @event WidgetEvent an event raised right after executing a widget.
* @since 2.0.11
*/
const EVENT_AFTER_RUN = 'afterRun';
/**
* @var int a counter used to generate [[id]] for widgets.
* @internal
*/
@ -45,6 +62,17 @@ class Widget extends Component implements ViewContextInterface
/**
* Initializes the object.
* This method is called at the end of the constructor.
* The default implementation will trigger an [[EVENT_INIT]] event.
*/
public function init()
{
parent::init();
$this->trigger(self::EVENT_INIT);
}
/**
* Begins a widget.
* This method creates an instance of the calling class. It will apply the configuration
* to the created instance. A matching [[end()]] call should be called later.
@ -76,7 +104,12 @@ class Widget extends Component implements ViewContextInterface
if (!empty(static::$stack)) {
$widget = array_pop(static::$stack);
if (get_class($widget) === get_called_class()) {
echo $widget->run();
/* @var $widget Widget */
if ($widget->beforeRun()) {
$result = $widget->run();
$result = $widget->afterRun($result);
echo $result;
}
return $widget;
} else {
throw new InvalidCallException('Expecting end() of ' . get_class($widget) . ', found ' . get_called_class());
@ -101,7 +134,11 @@ class Widget extends Component implements ViewContextInterface
/* @var $widget Widget */
$config['class'] = get_called_class();
$widget = Yii::createObject($config);
$out = $widget->run();
$out = '';
if ($widget->beforeRun()) {
$result = $widget->run();
$out = $widget->afterRun($result);
}
} catch (\Exception $e) {
// close the output buffer opened above if it has not been closed already
if (ob_get_level() > 0) {
@ -220,4 +257,64 @@ class Widget extends Component implements ViewContextInterface
return dirname($class->getFileName()) . DIRECTORY_SEPARATOR . 'views';
}
/**
* This method is invoked right before the widget is executed.
*
* The method will trigger the [[EVENT_BEFORE_RUN]] event. The return value of the method
* will determine whether the widget should continue to run.
*
* When overriding this method, make sure you call the parent implementation like the following:
*
* ```php
* public function beforeRun()
* {
* if (!parent::beforeRun()) {
* return false;
* }
*
* // your custom code here
*
* return true; // or false to not run the widget
* }
* ```
*
* @return bool whether the widget should continue to be executed.
* @since 2.0.11
*/
public function beforeRun()
{
$event = new WidgetEvent();
$this->trigger(self::EVENT_BEFORE_RUN, $event);
return $event->isValid;
}
/**
* This method is invoked right after a widget is executed.
*
* The method will trigger the [[EVENT_AFTER_RUN]] event. The return value of the method
* will be used as the widget return value.
*
* If you override this method, your code should look like the following:
*
* ```php
* public function afterRun($result)
* {
* $result = parent::afterRun($result);
* // your custom code here
* return $result;
* }
* ```
*
* @param mixed $result the widget return result.
* @return mixed the processed widget result.
* @since 2.0.11
*/
public function afterRun($result)
{
$event = new WidgetEvent();
$event->result = $result;
$this->trigger(self::EVENT_AFTER_RUN, $event);
return $event->result;
}
}

30
framework/base/WidgetEvent.php

@ -0,0 +1,30 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\base;
/**
* WidgetEvent represents the event parameter used for a widget event.
*
* By setting the [[isValid]] property, one may control whether to continue running the widget.
*
* @author Petra Barus <petra.barus@gmail.com>
* @since 2.0.11
*/
class WidgetEvent extends Event
{
/**
* @var mixed the widget result. Event handlers may modify this property to change the widget result.
*/
public $result;
/**
* @var boolean whether to continue running the widget. Event handlers of
* [[Widget::EVENT_BEFORE_RUN]] may set this property to decide whether
* to continue running the current widget.
*/
public $isValid = true;
}

2
framework/caching/Dependency.php

@ -14,7 +14,7 @@ namespace yii\caching;
* the actual dependency data.
*
* For more details and usage information on Cache, see the [guide article on caching](guide:caching-overview).
*
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/

2
framework/caching/ExpressionDependency.php

@ -18,7 +18,7 @@ namespace yii\caching;
* please refer to the [php manual](http://www.php.net/manual/en/language.expressions.php).
*
* For more details and usage information on Cache, see the [guide article on caching](guide:caching-overview).
*
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/

2
framework/caching/MemCacheServer.php

@ -14,7 +14,7 @@ namespace yii\caching;
* of each configuration property.
*
* For more details and usage information on Cache, see the [guide article on caching](guide:caching-overview).
*
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/

2
framework/caching/WinCache.php

@ -16,7 +16,7 @@ namespace yii\caching;
* See [[Cache]] manual for common cache operations that are supported by WinCache.
*
* For more details and usage information on Cache, see the [guide article on caching](guide:caching-overview).
*
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/

4
framework/classes.php

@ -54,6 +54,7 @@ return [
'yii\base\ViewNotFoundException' => YII2_PATH . '/base/ViewNotFoundException.php',
'yii\base\ViewRenderer' => YII2_PATH . '/base/ViewRenderer.php',
'yii\base\Widget' => YII2_PATH . '/base/Widget.php',
'yii\base\WidgetEvent' => YII2_PATH . '/base/WidgetEvent.php',
'yii\behaviors\AttributeBehavior' => YII2_PATH . '/behaviors/AttributeBehavior.php',
'yii\behaviors\AttributeTypecastBehavior' => YII2_PATH . '/behaviors/AttributeTypecastBehavior.php',
'yii\behaviors\BlameableBehavior' => YII2_PATH . '/behaviors/BlameableBehavior.php',
@ -140,6 +141,7 @@ return [
'yii\filters\AccessRule' => YII2_PATH . '/filters/AccessRule.php',
'yii\filters\ContentNegotiator' => YII2_PATH . '/filters/ContentNegotiator.php',
'yii\filters\Cors' => YII2_PATH . '/filters/Cors.php',
'yii\filters\HostControl' => YII2_PATH . '/filters/HostControl.php',
'yii\filters\HttpCache' => YII2_PATH . '/filters/HttpCache.php',
'yii\filters\PageCache' => YII2_PATH . '/filters/PageCache.php',
'yii\filters\RateLimitInterface' => YII2_PATH . '/filters/RateLimitInterface.php',
@ -157,6 +159,7 @@ return [
'yii\grid\DataColumn' => YII2_PATH . '/grid/DataColumn.php',
'yii\grid\GridView' => YII2_PATH . '/grid/GridView.php',
'yii\grid\GridViewAsset' => YII2_PATH . '/grid/GridViewAsset.php',
'yii\grid\RadioButtonColumn' => YII2_PATH . '/grid/RadioButtonColumn.php',
'yii\grid\SerialColumn' => YII2_PATH . '/grid/SerialColumn.php',
'yii\helpers\ArrayHelper' => YII2_PATH . '/helpers/ArrayHelper.php',
'yii\helpers\BaseArrayHelper' => YII2_PATH . '/helpers/BaseArrayHelper.php',
@ -297,6 +300,7 @@ return [
'yii\web\MultipartFormDataParser' => YII2_PATH . '/web/MultipartFormDataParser.php',
'yii\web\NotAcceptableHttpException' => YII2_PATH . '/web/NotAcceptableHttpException.php',
'yii\web\NotFoundHttpException' => YII2_PATH . '/web/NotFoundHttpException.php',
'yii\web\RangeNotSatisfiableHttpException' => YII2_PATH . '/web/RangeNotSatisfiableHttpException.php',
'yii\web\Request' => YII2_PATH . '/web/Request.php',
'yii\web\RequestParserInterface' => YII2_PATH . '/web/RequestParserInterface.php',
'yii\web\Response' => YII2_PATH . '/web/Response.php',

1
framework/console/UnknownCommandException.php

@ -21,6 +21,7 @@ class UnknownCommandException extends Exception
* @var string the name of the command that could not be recognized.
*/
public $command;
/**
* @var Application
*/

133
framework/console/controllers/MessageController.php

@ -8,8 +8,10 @@
namespace yii\console\controllers;
use Yii;
use yii\console\Controller;
use yii\console\Exception;
use yii\db\Connection;
use yii\db\Query;
use yii\di\Instance;
use yii\helpers\Console;
use yii\helpers\FileHelper;
use yii\helpers\VarDumper;
@ -35,7 +37,7 @@ use yii\i18n\GettextPoFile;
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class MessageController extends Controller
class MessageController extends \yii\console\Controller
{
/**
* @var string controller default action ID.
@ -105,7 +107,7 @@ class MessageController extends Controller
*/
public $only = ['*.php'];
/**
* @var string generated file format. Can be "php", "db" or "po".
* @var string generated file format. Can be "php", "db", "po" or "pot".
*/
public $format = 'php';
/**
@ -217,13 +219,13 @@ return $array;
EOD;
if (file_put_contents($filePath, $content) !== false) {
$this->stdout("Configuration file created: '{$filePath}'.\n\n", Console::FG_GREEN);
return self::EXIT_CODE_NORMAL;
} else {
if (file_put_contents($filePath, $content) === false) {
$this->stdout("Configuration file was NOT created: '{$filePath}'.\n\n", Console::FG_RED);
return self::EXIT_CODE_ERROR;
}
$this->stdout("Configuration file created: '{$filePath}'.\n\n", Console::FG_GREEN);
return self::EXIT_CODE_NORMAL;
}
/**
@ -240,18 +242,20 @@ EOD;
public function actionConfigTemplate($filePath)
{
$filePath = Yii::getAlias($filePath);
if (file_exists($filePath)) {
if (!$this->confirm("File '{$filePath}' already exists. Do you wish to overwrite it?")) {
return self::EXIT_CODE_NORMAL;
}
}
if (copy(Yii::getAlias('@yii/views/messageConfig.php'), $filePath)) {
$this->stdout("Configuration file template created at '{$filePath}'.\n\n", Console::FG_GREEN);
return self::EXIT_CODE_NORMAL;
} else {
if (!copy(Yii::getAlias('@yii/views/messageConfig.php'), $filePath)) {
$this->stdout("Configuration file template was NOT created at '{$filePath}'.\n\n", Console::FG_RED);
return self::EXIT_CODE_ERROR;
}
$this->stdout("Configuration file template created at '{$filePath}'.\n\n", Console::FG_GREEN);
return self::EXIT_CODE_NORMAL;
}
/**
@ -272,9 +276,8 @@ EOD;
$configFile = Yii::getAlias($configFile);
if (!is_file($configFile)) {
throw new Exception("The configuration file does not exist: $configFile");
} else {
$configFileContent = require($configFile);
}
$configFileContent = require($configFile);
}
$config = array_merge(
@ -297,7 +300,8 @@ EOD;
if (in_array($config['format'], ['php', 'po', 'pot'])) {
if (!isset($config['messagePath'])) {
throw new Exception('The configuration file must specify "messagePath".');
} elseif (!is_dir($config['messagePath'])) {
}
if (!is_dir($config['messagePath'])) {
throw new Exception("The message path {$config['messagePath']} is not a valid directory.");
}
}
@ -311,24 +315,24 @@ EOD;
foreach ($files as $file) {
$messages = array_merge_recursive($messages, $this->extractMessages($file, $config['translator'], $config['ignoreCategories']));
}
$catalog = isset($config['catalog']) ? $config['catalog'] : 'messages';
if (in_array($config['format'], ['php', 'po'])) {
foreach ($config['languages'] as $language) {
$dir = $config['messagePath'] . DIRECTORY_SEPARATOR . $language;
if (!is_dir($dir)) {
@mkdir($dir);
if (!is_dir($dir) && !@mkdir($dir)) {
throw new Exception("Directory '{$dir}' can not be created.");
}
if ($config['format'] === 'po') {
$catalog = isset($config['catalog']) ? $config['catalog'] : 'messages';
$this->saveMessagesToPO($messages, $dir, $config['overwrite'], $config['removeUnused'], $config['sort'], $catalog, $config['markUnused']);
} else {
$this->saveMessagesToPHP($messages, $dir, $config['overwrite'], $config['removeUnused'], $config['sort'], $config['markUnused']);
}
}
} elseif ($config['format'] === 'db') {
$db = \Yii::$app->get(isset($config['db']) ? $config['db'] : 'db');
if (!$db instanceof \yii\db\Connection) {
throw new Exception('The "db" option must refer to a valid database application component.');
}
/** @var Connection $db */
$db = Instance::ensure($config['db'], Connection::className());
$sourceMessageTable = isset($config['sourceMessageTable']) ? $config['sourceMessageTable'] : '{{%source_message}}';
$messageTable = isset($config['messageTable']) ? $config['messageTable'] : '{{%message}}';
$this->saveMessagesToDb(
@ -341,7 +345,6 @@ EOD;
$config['markUnused']
);
} elseif ($config['format'] === 'pot') {
$catalog = isset($config['catalog']) ? $config['catalog'] : 'messages';
$this->saveMessagesToPOT($messages, $config['messagePath'], $catalog);
}
}
@ -350,7 +353,7 @@ EOD;
* Saves messages to database
*
* @param array $messages
* @param \yii\db\Connection $db
* @param Connection $db
* @param string $sourceMessageTable
* @param string $messageTable
* @param bool $removeUnused
@ -359,11 +362,20 @@ EOD;
*/
protected function saveMessagesToDb($messages, $db, $sourceMessageTable, $messageTable, $removeUnused, $languages, $markUnused)
{
$q = new \yii\db\Query;
$current = [];
$currentMessages = [];
$rows = (new Query)->select(['id', 'category', 'message'])->from($sourceMessageTable)->all($db);
foreach ($rows as $row) {
$currentMessages[$row['category']][$row['id']] = $row['message'];
}
foreach ($q->select(['id', 'category', 'message'])->from($sourceMessageTable)->all($db) as $row) {
$current[$row['category']][$row['id']] = $row['message'];
$currentLanguages = [];
$rows = (new Query)->select(['language'])->from($messageTable)->groupBy('language')->all($db);
foreach ($rows as $row) {
$currentLanguages[] = $row['language'];
}
$missingLanguages = [];
if (!empty($currentLanguages)) {
$missingLanguages = array_diff($languages, $currentLanguages);
}
$new = [];
@ -372,21 +384,21 @@ EOD;
foreach ($messages as $category => $msgs) {
$msgs = array_unique($msgs);
if (isset($current[$category])) {
$new[$category] = array_diff($msgs, $current[$category]);
$obsolete += array_diff($current[$category], $msgs);
if (isset($currentMessages[$category])) {
$new[$category] = array_diff($msgs, $currentMessages[$category]);
$obsolete += array_diff($currentMessages[$category], $msgs);
} else {
$new[$category] = $msgs;
}
}
foreach (array_diff(array_keys($current), array_keys($messages)) as $category) {
$obsolete += $current[$category];
foreach (array_diff(array_keys($currentMessages), array_keys($messages)) as $category) {
$obsolete += $currentMessages[$category];
}
if (!$removeUnused) {
foreach ($obsolete as $pk => $m) {
if (mb_substr($m, 0, 2) === '@@' && mb_substr($m, -2) === '@@') {
foreach ($obsolete as $pk => $msg) {
if (mb_substr($msg, 0, 2) === '@@' && mb_substr($msg, -2) === '@@') {
unset($obsolete[$pk]);
}
}
@ -397,9 +409,9 @@ EOD;
$savedFlag = false;
foreach ($new as $category => $msgs) {
foreach ($msgs as $m) {
foreach ($msgs as $msg) {
$savedFlag = true;
$lastPk = $db->schema->insert($sourceMessageTable, ['category' => $category, 'message' => $m]);
$lastPk = $db->schema->insert($sourceMessageTable, ['category' => $category, 'message' => $msg]);
foreach ($languages as $language) {
$db->createCommand()
->insert($messageTable, ['id' => $lastPk['id'], 'language' => $language])
@ -408,7 +420,25 @@ EOD;
}
}
$this->stdout($savedFlag ? "saved.\n" : "Nothing new...skipped.\n");
if (!empty($missingLanguages)) {
$updatedMessages = [];
$rows = (new Query)->select(['id', 'category', 'message'])->from($sourceMessageTable)->all($db);
foreach ($rows as $row) {
$updatedMessages[$row['category']][$row['id']] = $row['message'];
}
foreach ($updatedMessages as $category => $msgs) {
foreach ($msgs as $id => $msg) {
$savedFlag = true;
foreach ($missingLanguages as $language) {
$db->createCommand()
->insert($messageTable, ['id' => $id, 'language' => $language])
->execute();
}
}
}
}
$this->stdout($savedFlag ? "saved.\n" : "Nothing to save.\n");
$this->stdout($removeUnused ? 'Deleting obsoleted messages...' : 'Updating obsoleted messages...');
if (empty($obsolete)) {
@ -554,22 +584,18 @@ EOD;
*/
protected function isCategoryIgnored($category, array $ignoreCategories)
{
$result = false;
if (!empty($ignoreCategories)) {
if (in_array($category, $ignoreCategories, true)) {
$result = true;
} else {
foreach ($ignoreCategories as $pattern) {
if (strpos($pattern, '*') > 0 && strpos($category, rtrim($pattern, '*')) === 0) {
$result = true;
break;
}
return true;
}
foreach ($ignoreCategories as $pattern) {
if (strpos($pattern, '*') > 0 && strpos($category, rtrim($pattern, '*')) === 0) {
return true;
}
}
}
return $result;
return false;
}
/**
@ -584,7 +610,8 @@ EOD;
{
if (is_string($a) && is_string($b)) {
return $a === $b;
} elseif (isset($a[0], $a[1], $b[0], $b[1])) {
}
if (isset($a[0], $a[1], $b[0], $b[1])) {
return $a[0] === $b[0] && $a[1] == $b[1];
}
return false;
@ -695,7 +722,6 @@ EOD;
ksort($merged);
}
$array = VarDumper::export($merged);
$content = <<<EOD
<?php
@ -720,13 +746,13 @@ return $array;
EOD;
if (file_put_contents($fileName, $content) !== false) {
$this->stdout("Translation saved.\n\n", Console::FG_GREEN);
return self::EXIT_CODE_NORMAL;
} else {
if (file_put_contents($fileName, $content) === false) {
$this->stdout("Translation was NOT saved.\n\n", Console::FG_RED);
return self::EXIT_CODE_ERROR;
}
$this->stdout("Translation saved.\n\n", Console::FG_GREEN);
return self::EXIT_CODE_NORMAL;
}
/**
@ -748,7 +774,6 @@ EOD;
$poFile = new GettextPoFile();
$merged = [];
$todos = [];

4
framework/data/BaseDataProvider.php

@ -23,8 +23,8 @@ use yii\base\InvalidArgumentException;
* @property Pagination|false $pagination The pagination object. If this is false, it means the pagination is
* disabled. Note that the type of this property differs in getter and setter. See [[getPagination()]] and
* [[setPagination()]] for details.
* @property Sort|bool $sort The sorting object. If this is false, it means the sorting is disabled. Note
* that the type of this property differs in getter and setter. See [[getSort()]] and [[setSort()]] for details.
* @property Sort|bool $sort The sorting object. If this is false, it means the sorting is disabled. Note that
* the type of this property differs in getter and setter. See [[getSort()]] and [[setSort()]] for details.
* @property int $totalCount Total number of possible data models.
*
* @author Qiang Xue <qiang.xue@gmail.com>

10
framework/data/Pagination.php

@ -58,13 +58,13 @@ use yii\web\Request;
*
* For more details and usage information on Pagination, see the [guide article on pagination](guide:output-pagination).
*
* @property int $limit The limit of the data. This may be used to set the LIMIT value for a SQL statement
* for fetching the current page of data. Note that if the page size is infinite, a value -1 will be returned.
* This property is read-only.
* @property int $limit The limit of the data. This may be used to set the LIMIT value for a SQL statement for
* fetching the current page of data. Note that if the page size is infinite, a value -1 will be returned. This
* property is read-only.
* @property array $links The links for navigational purpose. The array keys specify the purpose of the links
* (e.g. [[LINK_FIRST]]), and the array values are the corresponding URLs. This property is read-only.
* @property int $offset The offset of the data. This may be used to set the OFFSET value for a SQL
* statement for fetching the current page of data. This property is read-only.
* @property int $offset The offset of the data. This may be used to set the OFFSET value for a SQL statement
* for fetching the current page of data. This property is read-only.
* @property int $page The zero-based current page number.
* @property int $pageCount Number of pages. This property is read-only.
* @property int $pageSize The number of items per page. If it is less than 1, it means the page size is

2
framework/db/ActiveRelationTrait.php

@ -398,7 +398,7 @@ trait ActiveRelationTrait
* Indexes buckets by column name.
*
* @param array $buckets
* @var string|callable $column the name of the column by which the query results should be indexed by.
* @param string|callable $indexBy the name of the column by which the query results should be indexed by.
* This can also be a callable (e.g. anonymous function) that returns the index value based on the given row data.
* @return array
*/

2
framework/db/ColumnSchema.php

@ -116,7 +116,7 @@ class ColumnSchema extends Object
if ($value === '' && $this->type !== Schema::TYPE_TEXT && $this->type !== Schema::TYPE_STRING && $this->type !== Schema::TYPE_BINARY && $this->type !== Schema::TYPE_CHAR) {
return null;
}
if ($value === null || gettype($value) === $this->phpType || $value instanceof Expression) {
if ($value === null || gettype($value) === $this->phpType || $value instanceof Expression || $value instanceof Query) {
return $value;
}
switch ($this->phpType) {

4
framework/db/Command.php

@ -421,7 +421,9 @@ class Command extends Component
* Note that the created command is not executed until [[execute()]] is called.
*
* @param string $table the table that new rows will be inserted into.
* @param array $columns the column data (name => value) to be inserted into the table.
* @param array|\yii\db\Query $columns the column data (name => value) to be inserted into the table or instance
* of [[yii\db\Query|Query]] to perform INSERT INTO ... SELECT SQL statement.
* Passing of [[yii\db\Query|Query]] is available since version 2.0.11.
* @return $this the command object itself
*/
public function insert($table, $columns)

7
framework/db/Connection.php

@ -114,17 +114,18 @@ use yii\caching\Cache;
* @property bool $isActive Whether the DB connection is established. This property is read-only.
* @property string $lastInsertID The row ID of the last row inserted, or the last value retrieved from the
* sequence object. This property is read-only.
* @property Connection $master The currently active master connection. `null` is returned if there is no
* master available. This property is read-only.
* @property PDO $masterPdo The PDO instance for the currently active master connection. This property is
* read-only.
* @property QueryBuilder $queryBuilder The query builder for the current DB connection. This property is
* read-only.
* @property Schema $schema The schema information for the database opened by this connection. This property
* is read-only.
* @property Connection $master The currently active master connection. `null` is returned if there is no master
* @property Connection $slave The currently active slave connection. `null` is returned if there is no slave
* available and `$fallbackToMaster` is false. This property is read-only.
* @property PDO $slavePdo The PDO instance for the currently active slave connection. `null` is returned if no
* slave connection is available and `$fallbackToMaster` is false. This property is read-only.
* @property PDO $slavePdo The PDO instance for the currently active slave connection. `null` is returned if
* no slave connection is available and `$fallbackToMaster` is false. This property is read-only.
* @property Transaction $transaction The currently active transaction. Null if no active transaction. This
* property is read-only.
*

64
framework/db/QueryBuilder.php

@ -127,7 +127,9 @@ class QueryBuilder extends \yii\base\Object
* The method will properly escape the table and column names.
*
* @param string $table the table that new rows will be inserted into.
* @param array $columns the column data (name => value) to be inserted into the table.
* @param array|\yii\db\Query $columns the column data (name => value) to be inserted into the table or instance
* of [[yii\db\Query|Query]] to perform INSERT INTO ... SELECT SQL statement.
* Passing of [[yii\db\Query|Query]] is available since version 2.0.11.
* @param array $params the binding parameters that will be generated by this method.
* They should be bound to the DB command later.
* @return string the INSERT SQL
@ -142,23 +144,61 @@ class QueryBuilder extends \yii\base\Object
}
$names = [];
$placeholders = [];
foreach ($columns as $name => $value) {
$names[] = $schema->quoteColumnName($name);
if ($value instanceof Expression) {
$placeholders[] = $value->expression;
foreach ($value->params as $n => $v) {
$params[$n] = $v;
$values = ' DEFAULT VALUES';
if ($columns instanceof \yii\db\Query) {
list($names, $values) = $this->prepareInsertSelectSubQuery($columns, $schema);
} else {
foreach ($columns as $name => $value) {
$names[] = $schema->quoteColumnName($name);
if ($value instanceof Expression) {
$placeholders[] = $value->expression;
foreach ($value->params as $n => $v) {
$params[$n] = $v;
}
} elseif ($value instanceof \yii\db\Query) {
list($sql, $params) = $this->build($value, $params);
$placeholders[] = "($sql)";
} else {
$phName = self::PARAM_PREFIX . count($params);
$placeholders[] = $phName;
$params[$phName] = !is_array($value) && isset($columnSchemas[$name]) ? $columnSchemas[$name]->dbTypecast($value) : $value;
}
} else {
$phName = self::PARAM_PREFIX . count($params);
$placeholders[] = $phName;
$params[$phName] = !is_array($value) && isset($columnSchemas[$name]) ? $columnSchemas[$name]->dbTypecast($value) : $value;
}
}
return 'INSERT INTO ' . $schema->quoteTableName($table)
. (!empty($names) ? ' (' . implode(', ', $names) . ')' : '')
. (!empty($placeholders) ? ' VALUES (' . implode(', ', $placeholders) . ')' : ' DEFAULT VALUES');
. (!empty($placeholders) ? ' VALUES (' . implode(', ', $placeholders) . ')' : $values);
}
/**
* Prepare select-subquery and field names for INSERT INTO ... SELECT SQL statement.
*
* @param \yii\db\Query $columns Object, which represents select query
* @param \yii\db\Schema $schema Schema object to qoute column name
* @return array
* @since 2.0.11
*/
protected function prepareInsertSelectSubQuery($columns, $schema)
{
if (!is_array($columns->select) || empty($columns->select) || in_array('*', $columns->select)) {
throw new InvalidParamException('Expected select query object with enumerated (named) parameters');
}
list ($values, ) = $this->build($columns);
$names = [];
$values = ' ' . $values;
foreach ($columns->select as $title => $field) {
if (is_string($title)) {
$names[] = $title;
} else if (preg_match('/^(.*?)(?i:\s+as\s+|\s+)([\w\-_\.]+)$/', $field, $matches)) {
$names[] = $schema->quoteColumnName($matches[2]);
} else {
$names[] = $schema->quoteColumnName($field);
}
}
return [$names, $values];
}
/**

2
framework/db/QueryInterface.php

@ -259,7 +259,7 @@ interface QueryInterface
* and so on, will return empty or false values.
* You should use this method in case your program logic indicates query should not return any results, like
* in case you set false where condition like `0=1`.
* @param boolean $value whether to prevent query execution.
* @param bool $value whether to prevent query execution.
* @return $this the query object itself.
* @since 2.0.11
*/

4
framework/db/QueryTrait.php

@ -45,7 +45,7 @@ trait QueryTrait
*/
public $orderBy;
/**
* @var string|callable $column the name of the column by which the query results should be indexed by.
* @var string|callable the name of the column by which the query results should be indexed by.
* This can also be a callable (e.g. anonymous function) that returns the index value based on the given
* row data. For more details, see [[indexBy()]]. This property is only used by [[QueryInterface::all()|all()]].
*/
@ -401,7 +401,7 @@ trait QueryTrait
* and so on, will return empty or false values.
* You should use this method in case your program logic indicates query should not return any results, like
* in case you set false where condition like `0=1`.
* @param boolean $value whether to prevent query execution.
* @param bool $value whether to prevent query execution.
* @return $this the query object itself.
* @since 2.0.11
*/

1
framework/db/Schema.php

@ -74,7 +74,6 @@ abstract class Schema extends Object
public $exceptionMap = [
'SQLSTATE[23' => IntegrityException::class,
];
/**
* @var string column schema class
* @since 2.0.11

4
framework/db/Transaction.php

@ -38,8 +38,8 @@ use yii\base\InvalidConfigException;
* > 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.
*
* @property bool $isActive Whether this transaction is active. Only an active transaction can [[commit()]]
* or [[rollBack()]]. This property is read-only.
* @property bool $isActive Whether this transaction is active. Only an active transaction can [[commit()]] or
* [[rollBack()]]. This property is read-only.
* @property string $isolationLevel The transaction isolation level to use for this transaction. This can be
* one of [[READ_UNCOMMITTED]], [[READ_COMMITTED]], [[REPEATABLE_READ]] and [[SERIALIZABLE]] but also a string
* containing DBMS specific syntax to be used after `SET TRANSACTION ISOLATION LEVEL`. This property is

42
framework/db/mysql/QueryBuilder.php

@ -195,30 +195,38 @@ class QueryBuilder extends \yii\db\QueryBuilder
}
$names = [];
$placeholders = [];
foreach ($columns as $name => $value) {
$names[] = $schema->quoteColumnName($name);
if ($value instanceof Expression) {
$placeholders[] = $value->expression;
foreach ($value->params as $n => $v) {
$params[$n] = $v;
$values = ' DEFAULT VALUES';
if ($columns instanceof \yii\db\Query) {
list($names, $values) = $this->prepareInsertSelectSubQuery($columns, $schema);
} else {
foreach ($columns as $name => $value) {
$names[] = $schema->quoteColumnName($name);
if ($value instanceof Expression) {
$placeholders[] = $value->expression;
foreach ($value->params as $n => $v) {
$params[$n] = $v;
}
} elseif ($value instanceof \yii\db\Query) {
list($sql, $params) = $this->build($value, $params);
$placeholders[] = "($sql)";
} else {
$phName = self::PARAM_PREFIX . count($params);
$placeholders[] = $phName;
$params[$phName] = !is_array($value) && isset($columnSchemas[$name]) ? $columnSchemas[$name]->dbTypecast($value) : $value;
}
} else {
$phName = self::PARAM_PREFIX . count($params);
$placeholders[] = $phName;
$params[$phName] = !is_array($value) && isset($columnSchemas[$name]) ? $columnSchemas[$name]->dbTypecast($value) : $value;
}
}
if (empty($names) && $tableSchema !== null) {
$columns = !empty($tableSchema->primaryKey) ? $tableSchema->primaryKey : [reset($tableSchema->columns)->name];
foreach ($columns as $name) {
$names[] = $schema->quoteColumnName($name);
$placeholders[] = 'DEFAULT';
if (empty($names) && $tableSchema !== null) {
$columns = !empty($tableSchema->primaryKey) ? $tableSchema->primaryKey : [reset($tableSchema->columns)->name];
foreach ($columns as $name) {
$names[] = $schema->quoteColumnName($name);
$placeholders[] = 'DEFAULT';
}
}
}
return 'INSERT INTO ' . $schema->quoteTableName($table)
. (!empty($names) ? ' (' . implode(', ', $names) . ')' : '')
. (!empty($placeholders) ? ' VALUES (' . implode(', ', $placeholders) . ')' : ' DEFAULT VALUES');
. (!empty($placeholders) ? ' VALUES (' . implode(', ', $placeholders) . ')' : $values);
}
/**

42
framework/db/oci/QueryBuilder.php

@ -178,30 +178,38 @@ EOD;
}
$names = [];
$placeholders = [];
foreach ($columns as $name => $value) {
$names[] = $schema->quoteColumnName($name);
if ($value instanceof Expression) {
$placeholders[] = $value->expression;
foreach ($value->params as $n => $v) {
$params[$n] = $v;
$values = ' DEFAULT VALUES';
if ($columns instanceof \yii\db\Query) {
list($names, $values) = $this->prepareInsertSelectSubQuery($columns, $schema);
} else {
foreach ($columns as $name => $value) {
$names[] = $schema->quoteColumnName($name);
if ($value instanceof Expression) {
$placeholders[] = $value->expression;
foreach ($value->params as $n => $v) {
$params[$n] = $v;
}
} elseif ($value instanceof \yii\db\Query) {
list($sql, $params) = $this->build($value, $params);
$placeholders[] = "($sql)";
} else {
$phName = self::PARAM_PREFIX . count($params);
$placeholders[] = $phName;
$params[$phName] = !is_array($value) && isset($columnSchemas[$name]) ? $columnSchemas[$name]->dbTypecast($value) : $value;
}
} else {
$phName = self::PARAM_PREFIX . count($params);
$placeholders[] = $phName;
$params[$phName] = !is_array($value) && isset($columnSchemas[$name]) ? $columnSchemas[$name]->dbTypecast($value) : $value;
}
}
if (empty($names) && $tableSchema !== null) {
$columns = !empty($tableSchema->primaryKey) ? $tableSchema->primaryKey : reset($tableSchema->columns)->name;
foreach ($columns as $name) {
$names[] = $schema->quoteColumnName($name);
$placeholders[] = 'DEFAULT';
if (empty($names) && $tableSchema !== null) {
$columns = !empty($tableSchema->primaryKey) ? $tableSchema->primaryKey : [reset($tableSchema->columns)->name];
foreach ($columns as $name) {
$names[] = $schema->quoteColumnName($name);
$placeholders[] = 'DEFAULT';
}
}
}
return 'INSERT INTO ' . $schema->quoteTableName($table)
. (!empty($names) ? ' (' . implode(', ', $names) . ')' : '')
. (!empty($placeholders) ? ' VALUES (' . implode(', ', $placeholders) . ')' : ' DEFAULT VALUES');
. (!empty($placeholders) ? ' VALUES (' . implode(', ', $placeholders) . ')' : $values);
}
/**

9
framework/db/pgsql/QueryBuilder.php

@ -245,12 +245,18 @@ class QueryBuilder extends \yii\db\QueryBuilder
/**
* Normalizes data to be saved into the table, performing extra preparations and type converting, if necessary.
* @param string $table the table that data will be saved into.
* @param array $columns the column data (name => value) to be saved into the table.
* @param array|\yii\db\Query $columns the column data (name => value) to be saved into the table or instance
* of [[yii\db\Query|Query]] to perform INSERT INTO ... SELECT SQL statement.
* Passing of [[yii\db\Query|Query]] is available since version 2.0.11.
* @return array normalized columns
* @since 2.0.9
*/
private function normalizeTableRowData($table, $columns)
{
if ($columns instanceof \yii\db\Query) {
return $columns;
}
if (($tableSchema = $this->db->getSchema()->getTableSchema($table)) !== null) {
$columnSchemas = $tableSchema->columns;
foreach ($columns as $name => $value) {
@ -259,6 +265,7 @@ class QueryBuilder extends \yii\db\QueryBuilder
}
}
}
return $columns;
}

10
framework/di/Container.php

@ -574,10 +574,10 @@ class Container extends Component
* @param array $definitions array of definitions. There are two allowed formats of array.
* The first format:
* - key: class name, interface name or alias name. The key will be passed to the [[set()]] method
* as a first argument `$class`.
* as a first argument `$class`.
* - value: the definition associated with `$class`. Possible values are described in
* [[set()]] documentation for the `$definition` parameter. Will be passed to the [[set()]] method
* as the second argument `$definition`.
* [[set()]] documentation for the `$definition` parameter. Will be passed to the [[set()]] method
* as the second argument `$definition`.
*
* Example:
* ```php
@ -597,9 +597,9 @@ class Container extends Component
*
* The second format:
* - key: class name, interface name or alias name. The key will be passed to the [[set()]] method
* as a first argument `$class`.
* as a first argument `$class`.
* - value: array of two elements. The first element will be passed the [[set()]] method as the
* second argument `$definition`, the second one — as `$params`.
* second argument `$definition`, the second one — as `$params`.
*
* Example:
* ```php

12
framework/filters/AccessRule.php

@ -31,8 +31,16 @@ class AccessRule extends Component
*/
public $actions;
/**
* @var array list of the controller IDs that this rule applies to. Each controller ID is prefixed with the module ID (if any).
* The comparison is case-sensitive. If not set or empty, it means this rule applies to all controllers.
* @var array list of the controller IDs that this rule applies to.
*
* The comparison uses [[\yii\base\Controller::uniqueId]], so each controller ID is prefixed
* with the module ID (if any). For a `product` controller in the application, you would specify
* this property like `['product']` and if that controller is located in a `shop` module, this
* would be `['shop/product']`.
*
* The comparison is case-sensitive.
*
* If not set or empty, it means this rule applies to all controllers.
*/
public $controllers;
/**

14
framework/grid/ActionColumn.php

@ -161,7 +161,19 @@ class ActionColumn extends Column
{
if (!isset($this->buttons[$name]) && strpos($this->template, '{' . $name . '}') !== false) {
$this->buttons[$name] = function ($url, $model, $key) use ($name, $iconName, $additionalOptions) {
$title = Yii::t('yii', ucfirst($name));
switch ($name) {
case 'view':
$title = Yii::t('yii', 'View');
break;
case 'update':
$title = Yii::t('yii', 'Update');
break;
case 'delete':
$title = Yii::t('yii', 'Delete');
break;
default:
$title = ucfirst($name);
}
$options = array_merge([
'title' => $title,
'aria-label' => $title,

2
framework/helpers/BaseHtml.php

@ -663,7 +663,7 @@ class BaseHtml
* The following special options are recognized:
*
* - `doubleEncode`: whether to double encode HTML entities in `$value`. If `false`, HTML entities in `$value` will not
* be further encoded. This option is available since version 2.0.11.
* be further encoded. This option is available since version 2.0.11.
*
* @return string the generated text area tag
*/

2
framework/helpers/BaseStringHelper.php

@ -198,7 +198,7 @@ class BaseStringHelper
*
* @param string $string Input string
* @param string $with Part to search inside the $string
* @param bool $caseSensitive Case sensitive search. Default is true. When case sensitive is enabled, $with must exactly match the starting of the string in order to get a true value.
* @param bool $caseSensitive Case sensitive search. Default is true. When case sensitive is enabled, $with must exactly match the starting of the string in order to get a true value.
* @return bool Returns true if first input starts with second input, false otherwise
*/
public static function startsWith($string, $with, $caseSensitive = true)

3
framework/log/Logger.php

@ -35,7 +35,8 @@ use yii\base\Component;
* @property float $elapsedTime The total elapsed time in seconds for current request. This property is
* read-only.
* @property array $profiling The profiling results. Each element is an array consisting of these elements:
* `info`, `category`, `timestamp`, `trace`, `level`, `duration`, `memory`, `memoryDiff`. This property is read-only.
* `info`, `category`, `timestamp`, `trace`, `level`, `duration`, `memory`, `memoryDiff`. The `memory` and
* `memoryDiff` values are available since version 2.0.11. This property is read-only.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0

1
framework/log/SyslogTarget.php

@ -47,6 +47,7 @@ class SyslogTarget extends Target
Logger::LEVEL_ERROR => LOG_ERR,
];
/**
* @inheritdoc
*/

3
framework/messages/de/yii.php

@ -17,7 +17,7 @@
* NOTE: this file must be saved in UTF-8 encoding.
*/
return [
'The combination {values} of {attributes} has already been taken.' => 'Die Kombination {values} für {attributes} wird bereits verwendet.',
' and ' => ' und ',
'(not set)' => '(nicht gesetzt)',
'An internal server error occurred.' => 'Es ist ein interner Serverfehler aufgetreten.',
'Are you sure you want to delete this item?' => 'Wollen Sie diesen Eintrag wirklich löschen?',
@ -38,6 +38,7 @@ return [
'Please upload a file.' => 'Bitte laden Sie eine Datei hoch.',
'Powered by {yii}' => 'Basiert auf {yii}',
'Showing <b>{begin, number}-{end, number}</b> of <b>{totalCount, number}</b> {totalCount, plural, one{item} other{items}}.' => 'Zeige <b>{begin, number}-{end, number}</b> von <b>{totalCount, number}</b> {totalCount, plural, one{Eintrag} other{Einträgen}}.',
'The combination {values} of {attributes} has already been taken.' => 'Die Kombination {values} für {attributes} wird bereits verwendet.',
'The file "{file}" is not an image.' => 'Die Datei "{file}" ist kein Bild.',
'The file "{file}" is too big. Its size cannot exceed {formattedLimit}.' => 'Die Datei "{file}" ist zu groß. Es sind maximal {formattedLimit} erlaubt.',
'The file "{file}" is too small. Its size cannot be smaller than {formattedLimit}.' => 'Die Datei "{file}" ist zu klein. Es sind mindestens {formattedLimit} erforderlich.',

3
framework/messages/el/yii.php

@ -20,6 +20,7 @@ return [
'(not set)' => '(μη ορισμένο)',
'An internal server error occurred.' => 'Υπήρξε ένα εσωτερικό σφάλμα του διακομιστή.',
'Are you sure you want to delete this item?' => 'Είστε σίγουροι για τη διαγραφή του αντικειμένου;',
'Delete' => 'Διαγραφή',
'Error' => 'Σφάλμα',
'File upload failed.' => 'Το ανέβασμα του αρχείου απέτυχε.',
'Home' => 'Αρχή',
@ -50,6 +51,8 @@ return [
'Unable to verify your data submission.' => 'Δεν ήταν δυνατή η επαλήθευση των απεσταλμένων δεδομένων.',
'Unknown alias: -{name}' => 'Άγνωστο ψευδώνυμο: -{name}',
'Unknown option: --{name}' => 'Άγνωστη επιλογή: --{name}',
'Update' => 'Ενημέρωση',
'View' => 'Προβολή',
'Yes' => 'Ναι',
'You are not allowed to perform this action.' => 'Δεν επιτρέπεται να εκτελέσετε αυτή την ενέργεια.',
'You can upload at most {limit, number} {limit, plural, one{file} other{files}}.' => 'Μπορείτε να ανεβάσετε το πολύ {limit, number} {limit, plural, one{αρχείο} few{αρχεία} many{αρχεία} other{αρχεία}}.',

3
framework/messages/fa/yii.php

@ -25,6 +25,7 @@ return [
'(not set)' => '(تنظیم نشده)',
'An internal server error occurred.' => 'خطای داخلی سرور رخ داده است.',
'Are you sure you want to delete this item?' => 'آیا اطمینان به حذف این مورد دارید؟',
'Delete' => 'حذف',
'Error' => 'خطا',
'File upload failed.' => 'آپلود فایل ناموفق بود.',
'Home' => 'صفحهاصلی',
@ -53,6 +54,8 @@ return [
'Total <b>{count, number}</b> {count, plural, one{item} other{items}}.' => 'مجموع <b>{count, number}</b> مورد.',
'Unable to verify your data submission.' => 'قادر به تأیید اطلاعات ارسالی شما نمیباشد.',
'Unknown option: --{name}' => 'گزینه ناشناخته: --{name}',
'Update' => 'بروزرسانی',
'View' => 'نما',
'Yes' => 'بله',
'You are not allowed to perform this action.' => 'شما برای انجام این عملیات، دسترسی ندارید.',
'You can upload at most {limit, number} {limit, plural, one{file} other{files}}.' => 'شما حداکثر {limit, number} فایل را میتوانید آپلود کنید.',

3
framework/messages/ja/yii.php

@ -20,6 +20,7 @@ return [
'(not set)' => '(未設定)',
'An internal server error occurred.' => '内部サーバーエラーが発生しました。',
'Are you sure you want to delete this item?' => 'このアイテムを削除したいというのは本当ですか?',
'Delete' => '削除',
'Error' => 'エラー',
'File upload failed.' => 'ファイルアップロードに失敗しました。',
'Home' => 'ホーム',
@ -50,6 +51,8 @@ return [
'Unable to verify your data submission.' => 'データ送信を検証できませんでした。',
'Unknown alias: -{name}' => '不明なエイリアス: -{name}',
'Unknown option: --{name}' => '不明なオプション: --{name}',
'Update' => '更新',
'View' => '閲覧',
'Yes' => 'はい',
'You are not allowed to perform this action.' => 'このアクションの実行は許可されていません。',
'You can upload at most {limit, number} {limit, plural, one{file} other{files}}.' => '最大で {limit, number} 個のファイルをアップロードできます。',

3
framework/messages/ru/yii.php

@ -24,6 +24,7 @@ return [
' and ' => ' и ',
'An internal server error occurred.' => 'Возникла внутренняя ошибка сервера.',
'Are you sure you want to delete this item?' => 'Вы уверены, что хотите удалить этот элемент?',
'Delete' => 'Удалить',
'Error' => 'Ошибка',
'File upload failed.' => 'Загрузка файла не удалась.',
'Home' => 'Главная',
@ -53,6 +54,8 @@ return [
'Total <b>{count, number}</b> {count, plural, one{item} other{items}}.' => 'Всего <b>{count, number}</b> {count, plural, one{запись} few{записи} many{записей} other{записи}}.',
'Unable to verify your data submission.' => 'Не удалось проверить переданные данные.',
'Unknown option: --{name}' => 'Неизвестная опция: --{name}',
'Update' => 'Редактировать',
'View' => 'Просмотр',
'Yes' => 'Да',
'You are not allowed to perform this action.' => 'Вам не разрешено производить данное действие.',
'You can upload at most {limit, number} {limit, plural, one{file} other{files}}.' => 'Вы не можете загружать более {limit, number} {limit, plural, one{файла} few{файлов} many{файлов} other{файла}}.',

3
framework/messages/sk/yii.php

@ -20,6 +20,7 @@ return [
'(not set)' => '(nie je nastavené)',
'An internal server error occurred.' => 'Vyskytla sa interná chyba servera.',
'Are you sure you want to delete this item?' => 'Skutočne chcete odstrániť tento záznam?',
'Delete' => 'Zmazať',
'Error' => 'Chyba',
'File upload failed.' => 'Súbor sa nepodarilo nahrať.',
'Home' => 'Úvod',
@ -51,6 +52,8 @@ return [
'Unable to verify your data submission.' => 'Nebolo možné preveriť odoslané údaje.',
'Unknown alias: -{name}' => 'Neznámy alias: -{name}',
'Unknown option: --{name}' => 'Neznáme nastavenie: --{name}',
'Update' => 'Upraviť',
'View' => 'Náhľad',
'Yes' => 'Áno',
'Yii Framework' => 'Yii Framework',
'You are not allowed to perform this action.' => 'Nemáte oprávnenie pre požadovanú akciu.',

2
framework/rbac/CheckAccessInterface.php

@ -9,7 +9,7 @@ namespace yii\rbac;
/**
* For more details and usage information on CheckAccessInterface, see the [guide article on security authorization](guide:security-authorization).
*
*
* @author Sam Mousa <sam@mousa.nl>
* @since 2.0.9
*/

2
framework/rest/DeleteAction.php

@ -14,7 +14,7 @@ use yii\web\ServerErrorHttpException;
* DeleteAction implements the API endpoint for deleting a model.
*
* For more details and usage information on DeleteAction, see the [guide article on rest controllers](guide:rest-controllers).
*
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/

4
framework/rest/IndexAction.php

@ -12,9 +12,9 @@ use yii\data\ActiveDataProvider;
/**
* IndexAction implements the API endpoint for listing multiple models.
*
*
* For more details and usage information on IndexAction, see the [guide article on rest controllers](guide:rest-controllers).
*
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/

12
framework/rest/UrlRule.php

@ -221,9 +221,15 @@ class UrlRule extends CompositeUrlRule
if (strpos($pathInfo, $urlName) !== false) {
foreach ($rules as $rule) {
/* @var $rule \yii\web\UrlRule */
if (($result = $rule->parseRequest($manager, $request)) !== false) {
Yii::trace("Request parsed with URL rule: {$rule->name}", __METHOD__);
$result = $rule->parseRequest($manager, $request);
if (YII_DEBUG) {
Yii::trace([
'rule' => method_exists($rule, '__toString') ? $rule->__toString() : get_class($rule),
'match' => $result !== false,
'parent' => self::className()
], __METHOD__);
}
if ($result !== false) {
return $result;
}
}

2
framework/rest/ViewAction.php

@ -13,7 +13,7 @@ use Yii;
* ViewAction implements the API endpoint for returning the detailed information about a model.
*
* For more details and usage information on ViewAction, see the [guide article on rest controllers](guide:rest-controllers).
*
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/

2
framework/test/FixtureTrait.php

@ -20,7 +20,7 @@ use yii\base\InvalidConfigException;
* through the syntax `$this->fixtureName('model name')`.
*
* For more details and usage information on FixtureTrait, see the [guide article on fixtures](guide:test-fixtures).
*
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/

2
framework/validators/ExistValidator.php

@ -64,13 +64,13 @@ class ExistValidator extends Validator
* @var bool whether to allow array type attribute.
*/
public $allowArray = false;
/**
* @var string and|or define how target attributes are related
* @since 2.0.11
*/
public $targetAttributeJunction = 'and';
/**
* @inheritdoc
*/

36
framework/validators/UniqueValidator.php

@ -67,7 +67,9 @@ class UniqueValidator extends Validator
*/
public $filter;
/**
* @var string the user-defined error message. When validating single attribute, it may contain
* @var string the user-defined error message.
*
* When validating single attribute, it may contain
* the following placeholders which will be replaced accordingly by the validator:
*
* - `{attribute}`: the label of the attribute being validated
@ -87,13 +89,13 @@ class UniqueValidator extends Validator
* to setup custom message for multiple target attributes.
*/
public $comboNotUnique;
/**
* @var string and|or define how target attributes are related
* @since 2.0.11
*/
public $targetAttributeJunction = 'and';
/**
* @inheritdoc
*/
@ -124,7 +126,7 @@ class UniqueValidator extends Validator
$targetClass = $this->targetClass ?: get_class($model);
$targetAttribute = $this->targetAttribute === null ? $attribute : $this->targetAttribute;
$rawConditions = $this->prepareConditions($targetAttribute, $model, $attribute);
$conditions[] = $this->targetAttributeJunction == 'or' ? 'or' : 'and';
$conditions[] = $this->targetAttributeJunction === 'or' ? 'or' : 'and';
foreach ($rawConditions as $key => $value) {
if (is_array($value)) {
@ -167,22 +169,23 @@ class UniqueValidator extends Validator
$exists = $query->exists();
} else {
// if current $model is in the database already we can't use exists()
/** @var $models ActiveRecordInterface[] */
$models = $query->select($targetClass::primaryKey())->limit(2)->all();
if ($query instanceof \yii\db\ActiveQuery) {
// only select primary key to optimize query
$query->select($targetClass::primaryKey());
}
$models = $query->limit(2)->asArray()->all();
$n = count($models);
if ($n === 1) {
$keys = array_keys($conditions);
// if there is one record, check if it is the currently validated model
$dbModel = reset($models);
$pks = $targetClass::primaryKey();
sort($keys);
sort($pks);
if ($keys === $pks) {
// primary key is modified and not unique
$exists = $model->getOldPrimaryKey() != $model->getPrimaryKey();
} else {
// non-primary key, need to exclude the current record based on PK
$exists = reset($models)->getPrimaryKey() != $model->getOldPrimaryKey();
$pk = [];
foreach($pks as $pkAttribute) {
$pk[$pkAttribute] = $dbModel[$pkAttribute];
}
$exists = ($pk != $model->getOldPrimaryKey(true));
} else {
// if there is more than one record, the value is not unique
$exists = $n > 1;
}
}
@ -221,9 +224,10 @@ class UniqueValidator extends Validator
* should be used to validate the uniqueness of the current attribute value. You may use an array to validate
* the uniqueness of multiple columns at the same time. The array values are the attributes that will be
* used to validate the uniqueness, while the array keys are the attributes whose values are to be validated.
* If the key and the value are the same, you can just specify the value.
* @param Model $model the data model to be validated
* @param string $attribute the name of the attribute to be validated in the $model
*
* @return array conditions, compatible with [[\yii\db\Query::where()|Query::where()]] key-value format.
*/
private function prepareConditions($targetAttribute, $model, $attribute)
@ -231,7 +235,7 @@ class UniqueValidator extends Validator
if (is_array($targetAttribute)) {
$conditions = [];
foreach ($targetAttribute as $k => $v) {
$conditions[$v] = is_int($k) ? $model->$attribute : $model->$k;
$conditions[$v] = is_int($k) ? $model->$v : $model->$k;
}
} else {
$conditions = [$targetAttribute => $model->$attribute];

12
framework/web/CompositeUrlRule.php

@ -47,9 +47,15 @@ abstract class CompositeUrlRule extends Object implements UrlRuleInterface
{
foreach ($this->rules as $rule) {
/* @var $rule \yii\web\UrlRule */
if (($result = $rule->parseRequest($manager, $request)) !== false) {
Yii::trace("Request parsed with URL rule: {$rule->name}", __METHOD__);
$result = $rule->parseRequest($manager, $request);
if (YII_DEBUG) {
Yii::trace([
'rule' => method_exists($rule, '__toString') ? $rule->__toString() : get_class($rule),
'match' => $result !== false,
'parent' => self::className()
], __METHOD__);
}
if ($result !== false) {
return $result;
}
}

2
framework/web/ErrorAction.php

@ -66,6 +66,7 @@ class ErrorAction extends Action
* Defaults to "An internal server error occurred.".
*/
public $defaultMessage;
/**
* @var \Exception the exception object, normally is filled on [[init()]] method call.
* @see [[findException()]] to know default way of obtaining exception.
@ -73,6 +74,7 @@ class ErrorAction extends Action
*/
protected $exception;
/**
* {@inheritdoc}
*/

2
framework/web/RangeNotSatisfiableHttpException.php

@ -25,7 +25,7 @@ class RangeNotSatisfiableHttpException extends HttpException
/**
* Constructor.
* @param string $message error message
* @param integer $code error code
* @param int $code error code
* @param \Exception $previous The previous exception used for the exception chaining.
*/
public function __construct($message = null, $code = 0, \Exception $previous = null)

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save