Browse Source

Merge branch 'master' into 7374-inserting-ar-without-values

tags/2.0.6
John Was 9 years ago
parent
commit
57db031d1c
  1. 2
      .travis.yml
  2. 3
      CONTRIBUTING.md
  3. 13
      README.md
  4. 4
      build/controllers/DevController.php
  5. 1
      build/controllers/ReleaseController.php
  6. 4
      composer.json
  7. 2
      docs/guide-es/README.md
  8. 4
      docs/guide-es/intro-yii.md
  9. 6
      docs/guide-es/start-installation.md
  10. 4
      docs/guide-es/structure-applications.md
  11. 2
      docs/guide-es/structure-entry-scripts.md
  12. 4
      docs/guide-fr/intro-yii.md
  13. 4
      docs/guide-fr/start-installation.md
  14. 2
      docs/guide-fr/structure-entry-scripts.md
  15. 4
      docs/guide-it/intro-yii.md
  16. 6
      docs/guide-it/start-installation.md
  17. 2
      docs/guide-ja/caching-data.md
  18. 25
      docs/guide-ja/concept-autoloading.md
  19. 4
      docs/guide-ja/concept-di-container.md
  20. 10
      docs/guide-ja/concept-events.md
  21. 90
      docs/guide-ja/db-active-record.md
  22. 12
      docs/guide-ja/db-dao.md
  23. 3
      docs/guide-ja/db-migrations.md
  24. 2
      docs/guide-ja/db-query-builder.md
  25. 2
      docs/guide-ja/input-file-upload.md
  26. 31
      docs/guide-ja/input-validation.md
  27. 2
      docs/guide-ja/intro-upgrade-from-v1.md
  28. 4
      docs/guide-ja/intro-yii.md
  29. 258
      docs/guide-ja/output-data-providers.md
  30. 119
      docs/guide-ja/output-theming.md
  31. 18
      docs/guide-ja/rest-authentication.md
  32. 2
      docs/guide-ja/rest-error-handling.md
  33. 11
      docs/guide-ja/rest-quick-start.md
  34. 3
      docs/guide-ja/rest-response-formatting.md
  35. 2
      docs/guide-ja/rest-routing.md
  36. 10
      docs/guide-ja/runtime-requests.md
  37. 2
      docs/guide-ja/runtime-routing.md
  38. 9
      docs/guide-ja/runtime-sessions-cookies.md
  39. 155
      docs/guide-ja/security-authentication.md
  40. 51
      docs/guide-ja/security-authorization.md
  41. 14
      docs/guide-ja/security-best-practices.md
  42. 4
      docs/guide-ja/security-passwords.md
  43. 1
      docs/guide-ja/start-forms.md
  44. 2
      docs/guide-ja/start-gii.md
  45. 6
      docs/guide-ja/start-installation.md
  46. 7
      docs/guide-ja/structure-applications.md
  47. 38
      docs/guide-ja/structure-controllers.md
  48. 4
      docs/guide-ja/structure-entry-scripts.md
  49. 2
      docs/guide-ja/test-fixtures.md
  50. 16
      docs/guide-ja/tutorial-core-validators.md
  51. 3
      docs/guide-ja/tutorial-i18n.md
  52. 171
      docs/guide-ja/tutorial-performance-tuning.md
  53. 2
      docs/guide-ja/tutorial-start-from-scratch.md
  54. 2
      docs/guide-ja/tutorial-yii-integration.md
  55. 22
      docs/guide-pt-BR/README.md
  56. 356
      docs/guide-pt-BR/caching-data.md
  57. 166
      docs/guide-pt-BR/caching-fragment.md
  58. 134
      docs/guide-pt-BR/caching-http.md
  59. 17
      docs/guide-pt-BR/caching-overview.md
  60. 38
      docs/guide-pt-BR/caching-page.md
  61. 123
      docs/guide-pt-BR/concept-aliases.md
  62. 304
      docs/guide-pt-BR/concept-behaviors.md
  63. 94
      docs/guide-pt-BR/concept-components.md
  64. 246
      docs/guide-pt-BR/concept-events.md
  65. 61
      docs/guide-pt-BR/concept-properties.md
  66. 421
      docs/guide-pt-BR/db-migrations.md
  67. 10
      docs/guide-pt-BR/intro-upgrade-from-v1.md
  68. 4
      docs/guide-pt-BR/intro-yii.md
  69. 162
      docs/guide-pt-BR/runtime-requests.md
  70. 752
      docs/guide-pt-BR/runtime-routing.md
  71. 1
      docs/guide-pt-BR/start-forms.md
  72. 6
      docs/guide-pt-BR/start-gii.md
  73. 4
      docs/guide-pt-BR/start-hello.md
  74. 24
      docs/guide-pt-BR/start-installation.md
  75. 10
      docs/guide-pt-BR/start-workflow.md
  76. 38
      docs/guide-pt-BR/structure-applications.md
  77. 6
      docs/guide-pt-BR/structure-assets.md
  78. 53
      docs/guide-pt-BR/structure-controllers.md
  79. 6
      docs/guide-pt-BR/structure-entry-scripts.md
  80. 2
      docs/guide-pt-BR/structure-models.md
  81. 31
      docs/guide-ru/README.md
  82. 12
      docs/guide-ru/caching-data.md
  83. 2
      docs/guide-ru/concept-autoloading.md
  84. 2
      docs/guide-ru/concept-di-container.md
  85. 6
      docs/guide-ru/concept-events.md
  86. 2
      docs/guide-ru/concept-properties.md
  87. 2
      docs/guide-ru/concept-service-locator.md
  88. 636
      docs/guide-ru/db-dao.md
  89. 14
      docs/guide-ru/db-migrations.md
  90. 644
      docs/guide-ru/db-query-builder.md
  91. 177
      docs/guide-ru/helper-url.md
  92. 368
      docs/guide-ru/images/rbac-access-check-1.graphml
  93. BIN
      docs/guide-ru/images/rbac-access-check-1.png
  94. 368
      docs/guide-ru/images/rbac-access-check-2.graphml
  95. BIN
      docs/guide-ru/images/rbac-access-check-2.png
  96. 368
      docs/guide-ru/images/rbac-access-check-3.graphml
  97. BIN
      docs/guide-ru/images/rbac-access-check-3.png
  98. 312
      docs/guide-ru/images/rbac-hierarchy-1.graphml
  99. BIN
      docs/guide-ru/images/rbac-hierarchy-1.png
  100. 368
      docs/guide-ru/images/rbac-hierarchy-2.graphml
  101. Some files were not shown because too many files have changed in this diff Show More

2
.travis.yml

@ -38,7 +38,7 @@ addons:
install:
- travis_retry composer self-update && composer --version
- travis_retry composer global require "fxp/composer-asset-plugin:1.0.0"
- travis_retry composer global require "fxp/composer-asset-plugin:~1.0.0"
- export PATH="$HOME/.composer/vendor/bin:$PATH"
# core framework:
- travis_retry composer install --prefer-dist --no-interaction

3
CONTRIBUTING.md

@ -3,4 +3,5 @@ Contributing to Yii2
- [Report an issue](docs/internals/report-an-issue.md)
- [Translate documentation or messages](docs/internals/translation-workflow.md)
- [Contribute to the core code or fix bugs](docs/internals/getting-started.md)
- [Give us feedback or start a design discussion](http://www.yiiframework.com/forum/index.php/forum/42-general-discussions-for-yii-20/)
- [Contribute to the core code or fix bugs](docs/internals/git-workflow.md)

13
README.md

@ -42,7 +42,7 @@ Yii 2.0 has a [Definitive Guide](http://www.yiiframework.com/doc-2.0/guide-index
a [Class Reference](http://www.yiiframework.com/doc-2.0/index.html) which cover every detail of Yii.
There is also a [PDF version](http://stuff.cebe.cc/yii2-guide.pdf) of the Definitive Guide
and a [Definitive Guide Mirror](http://stuff.cebe.cc/yii2docs/) which update every 15 minutes.
and a [Definitive Guide Mirror](http://stuff.cebe.cc/yii2docs/) which is updated every 15 minutes.
For 1.1 users, you may refer to [Upgrading from Yii 1.1](docs/guide/intro-upgrade-from-v1.md)
to have a general idea of what has changed in 2.0.
@ -55,11 +55,8 @@ HOW TO PARTICIPATE
You may participate in the following ways:
* [Report issues](https://github.com/yiisoft/yii2/issues)
* [Give us feedback or start a design discussion](http://www.yiiframework.com/forum/index.php/forum/42-design-discussions-for-yii-20/)
* Fix issues, develop features, write/polish documentation
- Before you start, please adopt an existing issue (labelled with "ready for adoption") or start a new one to avoid duplicated efforts.
- Please submit a merge request after you finish development.
In order to make it easier we've prepared [special `yii2-dev` Composer package](https://github.com/yiisoft/yii2/blob/master/docs/internals/getting-started.md).
- [Report an issue](docs/internals/report-an-issue.md)
- [Translate documentation or messages](docs/internals/translation-workflow.md)
- [Give us feedback or start a design discussion](http://www.yiiframework.com/forum/index.php/forum/42-general-discussions-for-yii-20/)
- [Contribute to the core code or fix bugs](docs/internals/git-workflow.md)

4
build/controllers/DevController.php

@ -29,6 +29,7 @@ class DevController extends Controller
public $apps = [
'basic' => 'git@github.com:yiisoft/yii2-app-basic.git',
'advanced' => 'git@github.com:yiisoft/yii2-app-advanced.git',
'benchmark' => 'git@github.com:yiisoft/yii2-app-benchmark.git',
];
public $extensions = [
@ -97,12 +98,15 @@ class DevController extends Controller
$dirs = array_merge($dirs, $this->listSubDirs("$base/apps"));
asort($dirs);
$oldcwd = getcwd();
foreach($dirs as $dir) {
$displayDir = substr($dir, strlen($base));
$this->stdout("Running '$command' in $displayDir...\n", Console::BOLD);
chdir($dir);
passthru($command);
$this->stdout("done.\n", Console::BOLD, Console::FG_GREEN);
}
chdir($oldcwd);
}
/**

1
build/controllers/ReleaseController.php

@ -67,7 +67,6 @@ class ReleaseController extends Controller
{
$headline = "\n$version under development\n";
$headline .= str_repeat('-', strlen($headline) - 2) . "\n\n";
$headline .= "- no changes in this release.\n";
foreach($this->getChangelogs() as $file) {
$lines = explode("\n", file_get_contents($file));
$hl = [

4
composer.json

@ -52,10 +52,14 @@
"source": "https://github.com/yiisoft/yii2"
},
"minimum-stability": "dev",
"replace": {
"yiisoft/yii2": "self.version"
},
"require": {
"php": ">=5.4.0",
"ext-mbstring": "*",
"lib-pcre": "*",
"yiisoft/yii2-composer": "*",
"ezyang/htmlpurifier": "4.6.*",
"cebe/markdown": "~1.0.0 | ~1.1.0",
"bower-asset/jquery": "2.1.*@stable | 1.11.*@stable",

2
docs/guide-es/README.md

@ -189,7 +189,7 @@ Widgets
* Menu: **TBD** link to demo page
* LinkPager: **TBD** link to demo page
* LinkSorter: **TBD** link to demo page
* **TBD** [Bootstrap Widgets](bootstrap-widgets.md)
* [Bootstrap Widgets](https://github.com/yiisoft/yii2-bootstrap/blob/master/docs/guide-es/README.md)
* **TBD** [Jquery UI Widgets](jui-widgets.md)

4
docs/guide-es/intro-yii.md

@ -25,11 +25,11 @@ Si estás familiarizado con otros framework, puedes apreciar como se compara Yii
- Yii es extremadamente extensible. Puedes personalizar o reemplazar prácticamente cualquier pieza de código de base, como se puede también aprovechar su sólida arquitectura de extensiones para utilizar o desarrollar extensiones distribuibles.
- El alto rendimiento es siempre la meta principal de Yii.
Yii no es un proyecto de un sola persona, detrás de Yii hay un [sólido equipo de desarrollo][], así como una gran comunidad en la que numerosos profesionales contribuyen constantemente a su desarrollo.
Yii no es un proyecto de un sola persona, detrás de Yii hay un [sólido equipo de desarrollo][about_yii], así como una gran comunidad en la que numerosos profesionales contribuyen constantemente a su desarrollo.
El equipo de desarrollo de Yii se mantiene atento a las últimas tendencias de desarrollo web, así como a las mejores prácticas y características de otros frameworks y proyectos.
Las buenas prácticas y características más relevantes de otros proyectos se incorporan regularmente a la base del framework y se exponen a través de interfaces simples y elegantes.
[sólido equipo de desarrollo]: http://www.yiiframework.com/about/
[about_yii]: http://www.yiiframework.com/about/
Versiones de Yii
----------------

6
docs/guide-es/start-installation.md

@ -1,7 +1,7 @@
Instalando Yii
==============
Yii puede ser instalado de dos maneras, usando [Composer](http://getcomposer.org/) o descargando un archivo comprimido.
Yii puede ser instalado de dos maneras, usando [Composer](https://getcomposer.org/) o descargando un archivo comprimido.
Es preferible usar la primera forma, ya que te permite instalar [extensiones](structure-extensions.md) o actualizar Yii ejecutando un simple comando.
> Nota: A diferencia de Yii 1, la instalación estándar de Yii 2 resulta en la descarga e instalación tanto del framework como del esqueleto de la aplicación.
@ -13,7 +13,7 @@ Instalando a través de Composer <span id="installing-via-composer"></span>
Si aún no tienes Composer instalado, puedes hacerlo siguiendo las instrucciones que se encuentran en
[getcomposer.org](https://getcomposer.org/download/). En Linux y Mac OS X, se ejecutan los siguientes comandos:
curl -s http://getcomposer.org/installer | php
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
En Windows, tendrás que descargar y ejecutar [Composer-Setup.exe](https://getcomposer.org/Composer-Setup.exe).
@ -26,7 +26,7 @@ Si ya tienes composer instalado asegurate que esté actualizado ejecutando `comp
Teniendo Composer instalado, puedes instalar Yii ejecutando los siguientes comandos en un directorio accesible vía Web:
Nota: es posible que en al ejecutar el primer comando te pida tu username
composer global require "fxp/composer-asset-plugin:1.0.0"
composer global require "fxp/composer-asset-plugin:~1.0.0"
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
El comando anterior instala Yii dentro del directorio `basic`.

4
docs/guide-es/structure-applications.md

@ -386,7 +386,7 @@ sin proveer ningún argumento, mostrará la información de ayuda.
Esta propiedad especifica la lista de [extensiones](structure-extensions.md) que se encuentran instaladas y son utilizadas
por la aplicación.
Por defecto, tomará el array devuelto por el archivo `@vendor/yiisoft/extensions.php`. El archivo `extensions.php`
es generado y mantenido automáticamente cuando utilizas [Composer](http://getcomposer.org) para instalar extensiones.
es generado y mantenido automáticamente cuando utilizas [Composer](https://getcomposer.org) para instalar extensiones.
Por lo tanto, en la mayoría de los casos no necesitas configurarla.
En el caso especial de que quieras mantener las extensiones a mano, puedes configurar la propiedad como se muestra a continuación:
@ -456,7 +456,7 @@ representado por el alias `@app/views`. Puedes configurarlo como un directorio o
#### [[yii\base\Application::vendorPath|vendorPath]] <span id="vendorPath"></span>
Esta propiedad especifica el directorio `vendor` que maneja [Composer](http://getcomposer.org). Contiene
Esta propiedad especifica el directorio `vendor` que maneja [Composer](https://getcomposer.org). Contiene
todas las librerías de terceros utilizadas por tu aplicación, incluyendo el núcleo de Yii. Su valor por defecto
está representado por el alias `@app/vendor`.

2
docs/guide-es/structure-entry-scripts.md

@ -17,7 +17,7 @@ deberían ser ejecutables para que los usuarios puedan ejecutar las aplicaciones
El script de entrada principalmente hace los siguientes trabajos:
* Definir las constantes globales;
* Registrar el [cargador automático de Composer](http://getcomposer.org/doc/01-basic-usage.md#autoloading);
* Registrar el [cargador automático de Composer](https://getcomposer.org/doc/01-basic-usage.md#autoloading);
* Incluir el archivo de clase [[Yii]];
* Cargar la configuración de la aplicación;
* Crear y configurar una instancia de [aplicación](structure-applications.md);

4
docs/guide-fr/intro-yii.md

@ -29,13 +29,13 @@ support cache multi-niveaux; et plus.
profiter de son architecture extensible solide, afin d'utiliser ou développer des extensions redistribuables.
- La haute performance est toujours un des principaux objectifs de Yii.
Yii n'est pas un one-man show, il est soutenu par une [solide équipe de développement du noyau][] ainsi que d'une grande communauté
Yii n'est pas un one-man show, il est soutenu par une [solide équipe de développement du noyau][about_yii] ainsi que d'une grande communauté
avec de nombreux professionnels qui contribuent constamment au développement de Yii. L'équipe de développeurs de Yii
garde un œil attentif sur les dernières tendances en développement Web, et sur les meilleures pratiques et caractéristiques
trouvées dans d'autres frameworks ou projets. Les meilleures pratiques et caractéristiques les plus pertinentes trouvées ailleurs sont régulièrement intégrées dans le code du noyau et utilisables
via des interfaces simples et élégantes.
[solide équipe de développement du noyau]: http://www.yiiframework.com/about/
[about_yii]: http://www.yiiframework.com/about/
Versions de Yii
---------------

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

@ -1,7 +1,7 @@
Installer Yii
=============
Vous pouvez installer Yii de deux façons, en utilisant [Composer](http://getcomposer.org/) ou en téléchargeant une archive.
Vous pouvez installer Yii de deux façons, en utilisant [Composer](https://getcomposer.org/) ou en téléchargeant une archive.
La première méthode est conseillée, étant donné qu'elle permet d'installer de nouvelles [extensions](extend-creating-extensions.md) ou de mettre à jour Yii en éxécutant simplement une commande.
> Remarque : Contrairement à Yii 1, les installations standards de Yii 2 auront pour résultat le téléchargement et l'installation du framework, ainsi que d'un squelette d'application.
@ -13,7 +13,7 @@ Installer via Composer <span id="installing-via-composer"></span>
Si vous n'avez pas déjà installé Composer, vous pouvez le faire en suivant les instructions sur le site [getcomposer.org](https://getcomposer.org/download/).
Sous Linux et Mac OS X, vous pouvez éxécuter les commandes :
curl -s http://getcomposer.org/installer | php
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
Sous Windows, téléchargez et éxécutez [Composer-Setup.exe](https://getcomposer.org/Composer-Setup.exe).

2
docs/guide-fr/structure-entry-scripts.md

@ -16,7 +16,7 @@ utilisateurs puissent lancer des applications console grâce à la commande `./y
Les scipts de démarrage effectuent principalement les tâches suivantes :
* Définir des constantes globales;
* Enregistrer l'[autoloader Composer](http://getcomposer.org/doc/01-basic-usage.md#autoloading);
* Enregistrer l'[autoloader Composer](https://getcomposer.org/doc/01-basic-usage.md#autoloading);
* Inclure le fichier de classe de [[Yii]];
* Charger la configuration de l'application;
* Créer et configurer une instance d'[application](structure-applications.md);

4
docs/guide-it/intro-yii.md

@ -29,13 +29,13 @@ Se hai già familiarità con altri framework potrai apprezzare questi punti in c
sfuttare la solida architettura delle estensioni di Yii per usare o sviluppare estensioni ridistribuibili.
- Le prestazioni elevate sono sempre il focus primario di Yii.
Yii non è frutto di un uomo solo, ma è supportato da un [folto gruppo di sviluppatori][], così come da una numerosa
Yii non è frutto di un uomo solo, ma è supportato da un [folto gruppo di sviluppatori][about_yii], così come da una numerosa
comunità di professionisti che contribuiscono costantemente allo sviluppo. Il gruppo di sviluppatori tiene sempre
sott'occhio le ultime tendenze e tecnologie di sviluppo web, sulle pratiche ottimali e funzionalità degli altri
framework e progetti. Le peculiarità più rilevanti che si trovano altrove sono regolarmente incorporate nel
codice principale del framework, e rese disponibili tramite semplici ed eleganti interfacce.
[folto gruppo di sviluppatori]: http://www.yiiframework.com/about/
[about_yii]: http://www.yiiframework.com/about/
Versioni di Yii
---------------

6
docs/guide-it/start-installation.md

@ -1,7 +1,7 @@
Installare Yii
==============
Puoi installare Yii in due modi, usando [Composer](http://getcomposer.org/) o scaricando un archivio.
Puoi installare Yii in due modi, usando [Composer](https://getcomposer.org/) o scaricando un archivio.
Il metodo preferito è il primo, perché ti consente di installare [estensioni](structure-extensions.md) o aggiornare il core di Yii
semplicemente eseguendo un comando.
@ -14,7 +14,7 @@ Installazione via Composer <span id="installing-via-composer"></span>
Se non hai già installato Composer puoi farlo seguendo le istruzioni al sito
[getcomposer.org](https://getcomposer.org/download/). Su Linux e Mac OS X puoi installare Composer con questo comando:
curl -s http://getcomposer.org/installer | php
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
Su Windows devi scaricare ed eseguire [Composer-Setup.exe](https://getcomposer.org/Composer-Setup.exe).
@ -27,7 +27,7 @@ Se hai già Composer installato assicurati di avere una versione aggiornata. Puo
Una volta installato Composer, puoi installare Yii eseguendo questo comando in una directory accessbile via web:
composer global require "fxp/composer-asset-plugin:1.0.0"
composer global require "fxp/composer-asset-plugin:~1.0.0"
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
Il primo comando installa il [plugin composer asset](https://github.com/francoispluchino/composer-asset-plugin/)

2
docs/guide-ja/caching-data.md

@ -213,7 +213,7 @@ $data = $cache->get($key);
クエリキャッシュは、データキャッシュ上に構築された特別なキャッシュ機能で、データベースのクエリ結果をキャッシュするために提供されています。
クエリキャッシュは [[yii\db\Connection|データベース接続]] と有効な `cache` アプリケーションコンポーネントを必要とします。
クエリキャッシュは [[yii\db\Connection|データベース接続]] と有効な `cache` [アプリケーションコンポーネント](#cache-components) を必要とします。
`$db` を [[yii\db\Connection]] のインスタンスと仮定した場合、クエリキャッシュの基本的な使い方は以下のようになります:
```php

25
docs/guide-ja/concept-autoloading.md

@ -1,8 +1,8 @@
クラスのオートローディング
=================
Yiiは、必要となるすべてのクラスファイルを特定してインクルードするにあたり、 [クラスのオートローディングメカニズム](http://www.php.net/manual/ja/language.oop5.autoload.php)
を頼りにします。[PSR-4 標準](https://github.com/php-fig/fig-standards/blob/master/proposed/psr-4-autoloader/psr-4-autoloader.md) に準拠した、高性能なクラスのオートローダーを提供します。
Yiiは、必要となるすべてのクラスファイルを特定してインクルードするにあたり、 [クラスのオートローディングメカニズム](http://www.php.net/manual/ja/language.oop5.autoload.php)
を頼りにします。Yii は、[PSR-4 標準](https://github.com/php-fig/fig-standards/blob/master/proposed/psr-4-autoloader/psr-4-autoloader.md) に準拠した、高性能なクラスのオートローダーを提供しています。
このオートローダーは、あなたが `Yii.php` ファイルをインクルードするときにインストールされます。
> 補足: 説明を簡単にするため、このセクションではクラスのオートローディングについてのみお話しします。しかし、
@ -14,24 +14,24 @@ Yii オートローダーの使用 <span id="using-yii-autoloader"></span>
Yii のクラスオートローダーを使用するには、自分のクラスを作成して名前を付けるとき、次の2つの単純なルールに従わなければなりません:
* 各クラスは名前空間の下になければなりません (例 `foo\bar\MyClass`)
* 各クラスは [名前空間](http://php.net/manual/ja/language.namespaces.php) の下になければなりません (例 `foo\bar\MyClass`)
* 各クラスは次のアルゴリズムで決定される個別のファイルに保存されなければなりません:
```php
// $className は先頭にバックスラッシュを持つ完全修飾
// $className は先頭にバックスラッシュを持たない完全修飾クラス
$classFile = Yii::getAlias('@' . str_replace('\\', '/', $className) . '.php');
```
たとえば、クラス名と名前空間が `foo\bar\MyClass` であれば、対応するクラスファイルのパスの [エイリアス](concept-aliases.md) は、
`@foo/bar/MyClass.php` になります。このエイリアスがファイルパスになるようにするには、`@foo` または `@foo/bar`
`@foo/bar/MyClass.php` になります。このエイリアスがファイルパスとして解決できるようにするためには、`@foo` または `@foo/bar`
のどちらかが、 [ルートエイリアス](concept-aliases.md#defining-aliases) でなければなりません。
[ベーシックプロジェクトテンプレート](start-basic.md) を使用している場合、最上位の名前空間 `app` の下にクラスを置くことができ、
[ベーシックプロジェクトテンプレート](start-installation.md) を使用している場合、最上位の名前空間 `app` の下にクラスを置くことができ、
そうすると、新しいエイリアスを定義しなくても、Yii によってそれらをオートロードできるようになります。これは `@app`
が [事前定義されたエイリアス](concept-aliases.md#predefined-aliases) であるためで、`app\components\MyClass` のようなクラス名を
今説明したアルゴリズムに従って、クラスファイル `AppBasePath/components/MyClass.php` だと解決できるのです。
今説明したアルゴリズムに従って、クラスファイル `AppBasePath/components/MyClass.php` であると解決することが出来ます。
[アドバンストプロジェクトテンプレート](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide-ja/README.md) では、各階層にそれ自身のルートエイリアスを持っています。たとえば、
フロントエンド層はルートエイリアス `@frontend` を持ち、バックエンド層は `@backend` です。その結果、名前空間 `frontend` の下に
[アドバンストプロジェクトテンプレート](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide-ja/README.md) では、各層がそれ自身のルートエイリアスを持っています。たとえば、
フロントエンド層はルートエイリアス `@frontend` を持ち、バックエンド層のルートエイリアス`@backend` です。その結果、名前空間 `frontend` の下に
フロントエンドクラスを置き、バックエンドクラスを `backend` の下に置けます。これで、これらのクラスは Yii のオートローダーによって
オートロードできるようになります。
@ -62,7 +62,7 @@ Yii はパッケージ依存関係マネージャとして Composer を包含し
Yii オートローダーを他のオートローダーと一緒に使うときは、他のすべてのオートローダーがインストールされた *後で*`Yii.php`
ファイルをインクルードする必要があります。これで Yii のオートローダーが、任意クラスのオートローディング要求に応答する最初のものになります。
たとえば、次のコードは [Basic Application Template](start-basic.md) の [エントリスクリプト](structure-entry-scripts.md) から抜粋したものです。
たとえば、次のコードは [ベーシックプロジェクトテンプレート](start-installation.md) の [エントリスクリプト](structure-entry-scripts.md) から抜粋したものです。
最初の行は、Composer のオートローダーをインストールしており、二行目は Yii のオートローダーをインストールしています。
```php
@ -73,7 +73,7 @@ require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
あなたは Yii のオートローダーを使わず、Composer のオートローダーだけを単独で使用することもできます。しかし、そうすることによって、
あなたのクラスのオートローディングのパフォーマンスは低下し、クラスをオートロード可能にするために Composer が設定したルールに従わなければならなくなります。
> Info: Yiiのオートローダーを使用したくない場合は、 `Yii.php` ファイルの独自のバージョンを作成し、
> Info: Yiiのオートローダーを使用したくない場合は、 `Yii.php` ファイルのあなた独自のバージョンを作成し、
それを [エントリスクリプト](structure-entry-scripts.md) でインクルードする必要があります。
@ -84,5 +84,4 @@ Yii のオートローダーは、 [エクステンション](structure-extensio
エクステンションがその `composer.json` ファイルに正しく `autoload` セクションを指定していることです。
`autoload` 指定方法の詳細については [Composer のドキュメント](https://getcomposer.org/doc/04-schema.md#autoload) 参照してください。
Yii のオートローダーを使用しない場合でも、まだ Composer のオートローダーはエクステンションクラスをオートロード可能です。
Yii のオートローダーを使用しない場合でも、まだ Composer のオートローダーがエクステンションクラスをオートロードすることが可能です。

4
docs/guide-ja/concept-di-container.md

@ -325,8 +325,8 @@ class HotelController extends Controller
}
```
あなたがブラウザからこのコントローラにアクセスすると、 `BookingInterface` をインスタンス化できませんとい
不具合報告エラーが表示されるでしょう。これは、この依存関係に対処する方法を DI コンテナに教える必要があるからです:
あなたがブラウザからこのコントローラにアクセスすると、 `BookingInterface` をインスタンス化できない、という不平を言
エラーが表示されるでしょう。これは、この依存関係に対処する方法を DI コンテナに教える必要があるからです:
```php
\Yii::$container->set('app\components\BookingInterface', 'app\components\BookingService');

10
docs/guide-ja/concept-events.md

@ -4,7 +4,7 @@
イベントを使うと、既存のコードの特定の実行ポイントに、カスタムコードを挿入することができます。イベントにカスタムコードを添付すると、
イベントがトリガされたときにコードが自動的に実行されます。たとえば、メーラーオブジェクトがメッセージを正しく送信できたとき、
`messageSent` イベントをトリガするとします。もしメッセージの送信がうまく行ったことを知りたければ、単に `messageSent`
イベントにトラッキングコードを付与するだけで、それが可能になります。
イベントにトラッキングコードを付与するだけで、それが可能になります。
Yiiはイベントをサポートするために、 [[yii\base\Component]] と呼ばれる基底クラスを導入してします。クラスがイベントをトリガする必要がある場合は、
[[yii\base\Component]] もしくはその子クラスを継承する必要があります。
@ -16,10 +16,10 @@ Yiiはイベントをサポートするために、 [[yii\base\Component]] と
イベントハンドラとは、関連するイベントがトリガされたときに実行される、 [PHP コールバック](http://www.php.net/manual/ja/language.types.callable.php)
です。次のコールバックのいずれも使用可能です:
- 文字列で指定されたグローバル PHP 関数 (括弧を除く) `'trim'` など
- オブジェクトとメソッド名文字列の配列で指定された、オブジェクトのメソッド (括弧を除く) `[$object, 'methodName']` など
- クラス名文字列とメソッド名文字列の配列で指定された、静的なクラスメソッド (括弧を除く) `['ClassName', 'methodName']` など
- 無名関数 `function ($event) { ... }` など
- 文字列で指定されたグローバル PHP 関数 (括弧を除く)、例えば `'trim'`
- オブジェクトとメソッド名文字列の配列で指定された、オブジェクトのメソッド (括弧を除く)、例えば `[$object, 'methodName']`
- クラス名文字列とメソッド名文字列の配列で指定された、静的なクラスメソッド (括弧を除く)、例えば `['ClassName', 'methodName']`
- 無名関数、例えば `function ($event) { ... }`
イベントハンドラのシグネチャはこのようになります:

90
docs/guide-ja/db-active-record.md

@ -190,7 +190,7 @@ $customer = Customer::findOne([
// アクティブでない全ての顧客を返す
// SELECT * FROM `customer` WHERE `status` = 0
$customer = Customer::findAll([
$customers = Customer::findAll([
'status' => Customer::STATUS_INACTIVE,
]);
```
@ -695,7 +695,7 @@ $customer = Customer::findOne(123);
$orders = $customer->orders;
```
> Info|情報: `xyz` という名前のリレーションを getter メソッド `getXyz()` によって宣言すると、`xyz` をオブジェクト [プロパティ](concept-properties.md) のようにアクセスすることが出来るようになります。
> Info|情報: `xyz` という名前のリレーションを getter メソッド `getXyz()` によって宣言すると、`xyz` を [オブジェクトプロパティ](concept-properties.md) のようにアクセスすることが出来るようになります。
名前は大文字と小文字を区別することに注意してください。
リレーションが [[yii\db\ActiveRecord::hasMany()|hasMany()]] によって宣言されている場合は、このリレーションプロパティにアクセスすると、関連付けられたアクティブレコードインスタンスの配列が返されます。
@ -705,6 +705,16 @@ $orders = $customer->orders;
その同じプロパティに再びアクセスしたときは、SQL 文を再実行することなく、以前の結果が返されます。
SQL 文の再実行を強制するためには、まず、リレーションプロパティの割り当てを解除 (unset) しなければなりません : `unset($customer->orders)`
> Note|注意: リレーションプロパティの概念は [オブジェクトプロパティ](concept-properties.md) の機能と同一であるように見えますが、一つ、重要な相違点があります。
> 通常のオブジェクトプロパティでは、プロパティの値はそれを定義する getter メソッドと同じ型を持ちます。
> しかし、リレーションプロパティにアクセスすると [[yii\db\ActiveRecord]] のインスタンスまたはその配列が返されるのに対して、リレーションメソッドは [[yii\db\ActiveQuery]] のインスタンスを返します。
>
> ```php
> $customer->orders; // `Order` オブジェクトの配列
> $customer->getOrders(); // ActiveQuery のインスタンス
> ```
>
> このことは、次の項で説明するように、カスタマイズしたクエリを作成するのに役に立ちます。
### 動的なリレーショナルクエリ <span id="dynamic-relational-query"></span>
@ -721,6 +731,8 @@ $orders = $customer->getOrders()
->all();
```
リレーションプロパティにアクセスする場合と違って、リレーションメソッドによって動的なリレーショナルクエリを実行する場合は、同じ動的なリレーショナルクエリが以前に実行されたことがあっても、毎回、SQL 文が実行されます。
さらに進んで、もっと簡単に動的なリレーショナルクエリを実行できるように、リレーションの宣言をパラメータ化したい場合もあるでしょう。
例えば、`bigOrders` リレーションを下記のように宣言することが出来ます。
@ -746,11 +758,6 @@ $orders = $customer->getBigOrders(200)->all();
$orders = $customer->bigOrders;
```
> Note|注意: リレーションメソッドが [[yii\db\ActiveQuery]] インスタンスを返すのに対して、リレーションプロパティにアクセスすると [[yii\db\ActiveRecord]] のインスタンスまたはその配列が返されます。
この点で、通常のオブジェクト [プロパティ](concept-properties.md) が、そのプロパティを定義する getter メソッドと同じ型の値を持つのと異なります。
リレーショナルプロパティにアクセスする場合と異なって、リレーショナルメソッドを使って動的なリレーショナルクエリを実行する場合は、前に同じ動的リレーショナルクエリが実行されている場合であっても、毎回、SQL 文が実行されます。
### 中間テーブルによるリレーション <span id="junction-table"></span>
@ -1253,3 +1260,72 @@ $customers = Customer::find()->with([
> Info|情報: Yii 1.1 には、*スコープ* と呼ばれる概念がありました。
Yii 2.0 では、スコープはもはや直接にはサポートされません。
同じ目的を達するためには、カスタマイズされたクエリクラスとクエリメソッドを使わなければなりません。
## 追加のフィールドを選択する
アクティブレコードのインスタンスにクエリ結果からデータが投入されるときは、受け取ったデータセットのカラムの値が対応する属性に入れられます。
クエリ結果から追加のカラムや値を取得して、アクティブレコードの内部に格納することが出来ます。
例えば、ホテルの客室の情報を含む 'room' という名前のテーブルがあるとしましょう。
そして、全ての客室のデータは 'length' (長さ)、'width' (幅)、'height' (高さ) というフィールドを使って、部屋の幾何学的なサイズに関する情報を格納しているとします。
空いている全ての部屋の一覧を容積の降順で取得する必要がある場合を考えて見てください。
レコードをその値で並べ替える必要があるので、PHP を使って容積を計算することは出来ません。
しかし、同時に、一覧には 'volume' (容積) も表示したいでしょう。
目的を達するためには、'Room' アクティブレコードクラスにおいて追加のフィールドを宣言し、'volume' の値を格納する必要があります。
```php
class Room extends \yii\db\ActiveRecord
{
public $volume;
// ...
}
```
そして、部屋の容積を計算して並べ替えを実行するクエリを構築しなければなりません。
```php
$rooms = Room::find()
->select([
'{{room}}.*', // 全てのカラムを選択
'([[length]] * [[width]].* [[height]]) AS volume', // 容積を計算
])
->orderBy('volume DESC') // 並べ替えを適用
->all();
foreach ($rooms as $room) {
echo $room->volume; // SQL によって計算された値を含んでいる
}
```
追加のフィールドが選択できることは、集計クエリに対して特に有効に機能します。
注文の数とともに顧客の一覧を表示する必要がある場合を想定してください。
まず初めに、`Customer` クラスの中で、'orders' リレーションと、注文数を格納するための追加のフィールドを宣言しなければなりません。
```php
class Customer extends \yii\db\ActiveRecord
{
public $ordersCount;
// ...
public function getOrders()
{
return $this->hasMany(Order::className(), ['customer_id' => 'id']);
}
}
```
そして、order を結合して注文数を計算するクエリを構築することが出来ます。
```php
$customers = Customer::find()
->select([
'{{customer}}.*', // 顧客の全てのフィールドを選択
'COUNT({{order}}.id) AS ordersCount' // 注文数を計算
])
->joinWith('orders') // テーブルの結合を保証する
->groupBy('{{customer}}.id') // 結果をグループ化して、集計関数の動作を保証する
->all();
```

12
docs/guide-ja/db-dao.md

@ -87,6 +87,18 @@ ODBC 経由でデータベースに接続しようとする場合は、[[yii\db\
> Info|情報: DB 接続のインスタンスを作成するとき、実際のデータベース接続は、最初の SQL を実行するか、[[yii\db\Connection::open()|open()]] メソッドを明示的に呼ぶかするまでは確立されません。
> Tip|ヒント: 時として、何らかの環境変数を初期化するために、データベース接続を確立した直後に何かクエリを実行したい場合があります。
> そのためには、データベース接続の [[yii\db\Connection::EVENT_AFTER_OPEN|afterOpen]] イベントに対するイベントハンドラを登録することが出来ます。
> 以下のように、アプリケーションの構成情報に直接にハンドラを登録してください。
>
> ```php
> 'db' => [
> // ...
> 'on afterOpen' => function($event) {
> $event->sender->createCommand("YOUR SQL HERE")->execute();
> }
> ]
> ```
## SQL クエリを実行する <span id="executing-sql-queries"></span>

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

@ -30,6 +30,9 @@ Yii は一連のマイグレーションコマンドラインツールを提供
この節では、これらのツールを使用して、さまざまなタスクをどうやって達成するかを詳細に説明します。
各ツールの使用方法は、ヘルプコマンド `yii help migrate` によっても知ることが出来ます。
> Note|注意: マイグレーションはデータベーススキーマに影響を及ぼすだけでなく、既存のデータを新しいスキーマに合うように修正したり、RBAC 階層を作成したり、キャッシュをクリーンアップしたりすることも出来ます。
## マイグレーションを作成する <span id="creating-migrations"></span>
新しいマイグレーションを作成するためには、次のコマンドを実行します。

2
docs/guide-ja/db-query-builder.md

@ -494,7 +494,7 @@ $query1->union($query2);
これらのメソッドでは、`$q` パラメータは必須であり、カラム名または DB 式とすることが出来る。
上記のメソッドの全ては、オプションで、DB クエリの実行に使用されるべき [[yii\db\Connection|DB 接続]] を表す `$db` パラメータを取ることが出来ます。
このパラメータを省略した場合は、DB 接続として `db` アプリケーションコンポーネントが使用されます。
このパラメータを省略した場合は、DB 接続として `db` [アプリケーションコンポーネント](structure-application-components.md) が使用されます。
次に `count()` クエリメソッドを使う例をもう一つ挙げます。
```php

2
docs/guide-ja/input-file-upload.md

@ -170,7 +170,7 @@ public function rules()
画像をアップロードするときは、[[yii\validators\ImageValidator|ImageValidator]] が重宝するでしょう。
このバリデータは、属性が有効な画像を受け取ったか否かを検証します。
画像は、保存するか、または、[Imagine エクステンション](https://github.com/yiisoft/yii2/tree/master/extensions/imagine) によって処理することが出来ます。
画像は、保存するか、または、[Imagine エクステンション](https://github.com/yiisoft/yii2-imagine) によって処理することが出来ます。
複数のファイルをアップロードする
--------------------------------

31
docs/guide-ja/input-validation.md

@ -9,10 +9,12 @@
例えば、
```php
$model = new \app\models\ContactForm;
$model = new \app\models\ContactForm();
// モデルの属性にユーザ入力を投入する
$model->attributes = \Yii::$app->request->post('ContactForm');
$model->load(\Yii::$app->request->post());
// これは次と等価
// $model->attributes = \Yii::$app->request->post('ContactForm');
if ($model->validate()) {
// 全ての入力が有効
@ -440,6 +442,7 @@ class LoginForm extends Model
クライアント側の検証を完全に無効にしたい場合は、[[yii\widgets\ActiveForm::enableClientValidation]] プロパティを false に設定することが出来ます。
また、個々の入力フィールドごとにクライアント側の検証を無効にしたい場合には、入力フィールドの [[yii\widgets\ActiveField::enableClientValidation]] プロパティを false に設定することが出来ます。
`eanbleClientValidation` が入力フィールドのレベルとフォームのレベルの両方で構成されている場合は前者が優先されます。
### クライアント側の検証を実装する <span id="implementing-client-side-validation"></span>
@ -583,16 +586,32 @@ JS;
このような場合には、AJAX ベースの検証を使うことが出来ます。
AJAX 検証は、通常のクライアント側での検証と同じユーザ体験を保ちながら、入力値を検証するためにバックグラウンドで AJAX リクエストを発行します。
AJAX 検証をフォーム全体に対して有効にするためには、[[yii\widgets\ActiveForm::enableAjaxValidation]] プロパティを `true` に設定して、`id` にフォームを特定するユニークな ID を設定しなければなりません
単一のインプットフィールドに対して AJAX 検証を有効にするためには、そのフィールドの [[yii\widgets\ActiveField::enableAjaxValidation|enableAjaxValidation]] プロパティを true に設定し、フォームに一意の `id` を指定します
```php
<?php $form = yii\widgets\ActiveForm::begin([
use yii\widgets\ActiveForm;
$form = ActiveForm::begin([
'id' => 'registration-form',
]);
echo $form->field($model, 'username', ['enableAjaxValidation' => true]);
// ...
ActiveForm::end();
```
フォーム全体に対して AJAX 検証を有効にするためには、フォームのレベルで [[yii\widgets\ActiveForm::enableAjaxValidation|enableAjaxValidation]] を true に設定します。
```php
$form = ActiveForm::begin([
'id' => 'contact-form',
'enableAjaxValidation' => true,
]); ?>
]);
```
個別の入力フィールドについても、[[yii\widgets\ActiveField::enableAjaxValidation]] プロパティを設定して、AJAX 検証を有効にしたり無効にしたりすることが出来ます。
> Note|注意: `enableAjaxValidation` プロパティがインプットフィールドのレベルとフォームのレベルの両方で構成された場合は、前者が優先されます。
また、サーバ側では、AJAX 検証のリクエストを処理できるように準備しておく必要があります。
これは、コントローラのアクションにおいて、次のようなコード断片を使用することで達成できます。

2
docs/guide-ja/intro-upgrade-from-v1.md

@ -102,7 +102,7 @@ $object = Yii::createObject([
], [$param1, $param2]);
```
構成情報に関する詳細は、[オブジェクトの構成情報](concept-configurations.md) の節で見ることが出来ます。
構成情報に関する詳細は、[構成情報](concept-configurations.md) の節で見ることが出来ます。
イベント

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

@ -28,11 +28,11 @@ Yii を他のフレームワークと比べると
また、Yii の堅固なエクステンションアーキテクチャを利用して、再配布可能なエクステンションを使用したり開発したりすることも出来ます。
- 高性能であることは常に Yii の主たる目標です。
Yii はワンマンショーではありません。Yii は [強力なコア開発チーム][] および Yii 開発に間断なく貢献してくれるプロフェッショナルの大きなコミュニティーに支えられたプロジェクトです。
Yii はワンマンショーではありません。Yii は [強力なコア開発チーム][about_yii] および Yii 開発に間断なく貢献してくれるプロフェッショナルの大きなコミュニティーに支えられたプロジェクトです。
Yii 開発チームは、最新のウェブ開発の潮流と、他のフレームワークやプロジェクトに見出される最善のプラクティスと機能を、注意深く見守り続けています。
他のところで見出された最善のプラクティスと機能で最も適切なものは、定期的にコアフレームワークに組み込まれ、シンプルかつエレガントなインターフェイスを通じて公開されます。
[強力なコア開発チーム]: http://www.yiiframework.com/about/
[about_yii]: http://www.yiiframework.com/about/
Yii のバージョン
----------------

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

@ -1,150 +1,240 @@
データプロバイダ
================
> Note|注意: この節はまだ執筆中です。
[ページネーション](output-pagination.md) と [並べ替え](output-sorting.md) の節において、エンドユーザが特定のページのデータを選んで表示し、いずれかのカラムによってデータを並べ替えることが出来るようにする方法を説明しました。
データのページネーションと並べ替えは非常によくあるタスクですから、Yii はこれをカプセル化した一連の *データプロバイダ* を提供しています。
データプロバイダは、 [[yii\data\DataProviderInterface]] によってデータセットを抽象化し、ページネーションと並べ替えを処理します。
[グリッドやリストなどのデータウィジェット](output-data-widgets.md) で使用することが出来ます。
データプロバイダは [[yii\data\DataProviderInterface]] を実装するクラスであり、主として、ページ分割され並べ替えられたデータの取得をサポートするものです。
通常は、[データウィジェット](output-data-widgets.md) と共に使用して、エンドユーザが対話的にデータのページネーションと並べ替えをすることが出来るようにします。
Yii は三つのデータプロバイダを内蔵しています。すなわち、[[yii\data\ActiveDataProvider]]、[[yii\data\ArrayDataProvider]] そして [[yii\data\SqlDataProvider]] です。
Yii のリリースには次のデータプロバイダのクラスが含まれています。
アクティブデータプロバイダ
--------------------------
* [[yii\data\ActiveDataProvider]]: [[yii\db\Query]] または [[yii\db\ActiveQuery]] を使ってデータベースからデータを取得して、配列または [アクティブレコード](db-active-record.md) インスタンスの形式でデータを返します。
* [[yii\data\SqlDataProvider]]: SQL 文を実行して、データベースのデータを配列として返します。
* [[yii\data\ArrayDataProvider]]: 大きな配列を受け取り、ページネーションと並べ替えの指定に基づいて、一部分を切り出して返します。
`ActiveDataProvider` は [[yii\db\Query]] および [[yii\db\ActiveQuery]] を使って DB クエリを実行して、データを提供します。
次のコードは、これを使って、ActiveRecord のインスタンスを提供する例です。
これら全てのデータプロバイダの使用方法は、次の共通のパターンを持っています。
```php
$provider = new ActiveDataProvider([
'query' => Post::find(),
'pagination' => [
'pageSize' => 20,
],
// ページネーションと並べ替えのプロパティを構成してデータプロバイダを作成する
$provider = new XyzDataProvider([
'pagination' => [...],
'sort' => [...],
]);
// 現在のページの投稿を取得する
$posts = $provider->getModels();
// ページ分割されて並べ替えられたデータを取得する
$models = $provider->getModels();
// 現在のページにあるデータアイテムの数を取得する
$count = $provider->getCount();
// 全ページ分のデータアイテムの総数を取得する
$totalCount = $provider->getTotalCount();
```
そして次の例は、ActiveRecord なしで ActiveDataProvider を使う方法を示すものです。
データプロバイダのページネーションと並べ替えの振る舞いを指定するためには、その [[yii\data\BaseDataProvider::pagination|pagination]] と [[yii\data\BaseDataProvider::sort|sort]] のプロパティを構成します。
二つのプロパティは、それぞれ、[[yii\data\Pagination]] と [[yii\data\Sort]] の構成情報に対応します。
これらを false に設定して、ページネーションや並べ替えの機能を無効にすることも出来ます。
[データウィジェット](output-data-widgets.md)、例えば [[yii\grid\GridView]] は、`dataProvider` という名前のプロパティを持っており、これにデータプロバイダのインスタンスを受け取らせて、それが提供するデータを表示させることが出来ます。
例えば、
```php
$query = new Query();
$provider = new ActiveDataProvider([
'query' => $query->from('post'),
'sort' => [
// デフォルトのソートを name ASC, created_at DESC とする
'defaultOrder' => [
'name' => SORT_ASC,
'created_at' => SORT_DESC
]
],
'pagination' => [
'pageSize' => 20,
],
echo yii\grid\GridView::widget([
'dataProvider' => $dataProvider,
]);
// 現在のページの投稿を取得する
$posts = $provider->getModels();
```
配列データプロバイダ
--------------------
これらのデータプロバイダの主たる相異点は、データソースがどのように指定されるかという点にあります。
次に続く項において、各データプロバイダの詳細な使用方法を説明します。
ArrayDataProvider はデータの配列に基づいたデータプロバイダを実装するものです。
[[yii\data\ArrayDataProvider::$allModels]] プロパティが、並べ替えやページネーションの対象となるデータの全てのモデルを含みます。
ArrayDataProvider は、並べ替えとページネーションを実行した後に、データを提供します。
[[yii\data\ArrayDataProvider::$sort]] および [[yii\data\ArrayDataProvider::$pagination]] のプロパティを構成して、並べ替えとページネーションの動作をカスタマイズすることが出来ます。
## アクティブデータプロバイダ <span id="active-data-provider"></span>
[[yii\data\ArrayDataProvider::$allModels]] 配列の要素は、オブジェクト (例えば、モデルのオブジェクト) であるか、連想配列 (例えば、DAO のクエリ結果) であるかの、どちらかです。
[[yii\data\ArrayDataProvider::$key]] プロパティには、必ず、データレコードを一意的に特定出来るフィールドの名前をセットするか、そのようなフィールドがない場合は `false` をセットするかしなければなりません。
[[yii\data\ActiveDataProvider]] を使用するためには、その [[yii\data\ActiveDataProvider::query|query]] プロパティを構成しなければなりません。
これは、[[yii\db\Query]] または [[yii\db\ActiveQuery]] のオブジェクトを取ることが出来ます。
前者であれば、返されるデータは配列になります。
後者であれば、返されるデータは配列または [アクティブレコード](db-active-record.md) インスタンスとすることが出来ます。
例えば、
`ActiveDataProvider` と比較すると、`ArrayDataProvider` は、[[yii\data\ArrayDataProvider::$allModels]] を準備して持たなければならないため、効率が良くありません。
```php
use yii\data\ActiveDataProvider;
`ArrayDataProvider` は次のようにして使用することが出来ます。
$query = Post::find()->where(['status' => 1]);
```php
$query = new Query();
$provider = new ArrayDataProvider([
'allModels' => $query->from('post')->all(),
'sort' => [
'attributes' => ['id', 'username', 'email'],
],
$provider = new ActiveDataProvider([
'query' => $query,
'pagination' => [
'pageSize' => 10,
],
'sort' => [
'defaultOrder' => [
'created_at' => SORT_DESC,
'title' => SORT_ASC,
]
],
]);
// 現在のページの投稿を取得する
// Post オブジェクトの配列を返す
$posts = $provider->getModels();
```
> Note|注意: 並べ替えの機能を使いたいときは、どのカラムがソート出来るかをプロバイダが知ることが出来るように、[[sort]] プロパティを構成しなければなりません。
上記の例における `$query` が次のコードによって作成される場合は、提供されるデータは生の配列になります。
```php
use yii\db\Query;
$query = (new Query())->from('post')->where(['status' => 1]);
```
> Note|注意: クエリが既に `orderBy` 句を指定しているものである場合、(`sort` の構成を通して) エンドユーザによって与えられる並べ替えの指定は、既存の `orderBy` 句に追加されます。
一方、`limit` と `offset` の句が存在している場合は、(`pagenation` の構成を通して) エンドユーザによって指定されるページネーションのリクエストによって上書きされます。
デフォルトでは、[[yii\data\ActiveDataProvider]] はデータベース接続として `db` アプリケーションコンポーネントを使用します。
[[yii\data\ActiveDataProvider::db]] プロパティを構成すれば、別のデータベース接続を使用することが出来ます。
SQL データプロバイダ
--------------------
SqlDataProvider は、素の SQL 文に基づいたデータプロバイダを実装するものです。
これは、各要素がクエリ結果の行を表す配列の形式でデータを提供します。
## SQL データプロバイダ <span id="sql-data-provider"></span>
他のプロバイダ同様に、SqlDataProvider も、並べ替えとページネーションをサポートしています。
並べ替えとページネーションは、与えられた [[yii\data\SqlDataProvider::$sql]] 文を "ORDER BY" 句および "LIMIT" 句で修正することによって実行されます。
[[yii\data\SqlDataProvider::$sort]] および [[yii\data\SqlDataProvider::$pagination]] のプロパティを構成して、並べ替えとページネーションの動作をカスタマイズすることが出来ます。
[[yii\data\SqlDataProvider]] は、生の SQL 文を使用して、必要なデータを取得します。
このデータプロバイダは、[[yii\data\SqlDataProvider::sort|sort]] と [[yii\data\SqlDataProvider::pagination|pagination]] の指定に基づいて、SQL 文の `ORDER BY``OFFSET/LIMIT` の句を修正し、指定された順序に並べ替えられたデータを要求されたページの分だけ取得します。
`SqlDataProvider` は次のようにして使用することが出来ます。
[[yii\data\SqlDataProvider]] を使用するためには、[[yii\data\SqlDataProvider::sql|sql]] プロパティだけでなく、[[yii\data\SqlDataProvider::totalCount|totalCount]] プロパティを指定しなければなりません。
例えば、
```php
use yii\data\SqlDataProvider;
$count = Yii::$app->db->createCommand('
SELECT COUNT(*) FROM user WHERE status=:status
SELECT COUNT(*) FROM post WHERE status=:status
', [':status' => 1])->queryScalar();
$dataProvider = new SqlDataProvider([
'sql' => 'SELECT * FROM user WHERE status=:status',
$provider = new SqlDataProvider([
'sql' => 'SELECT * FROM post WHERE status=:status',
'params' => [':status' => 1],
'totalCount' => $count,
'pagination' => [
'pageSize' => 10,
],
'sort' => [
'attributes' => [
'age',
'name' => [
'asc' => ['first_name' => SORT_ASC, 'last_name' => SORT_ASC],
'desc' => ['first_name' => SORT_DESC, 'last_name' => SORT_DESC],
'default' => SORT_DESC,
'label' => 'Name',
],
'title',
'view_count',
'created_at',
],
],
]);
// データ行の配列を返す
$models = $provider->getModels();
```
> Info|情報: [[yii\data\SqlDataProvider::totalCount|totalCount]] プロパティは、データにページネーションを適用しなければならない場合にだけ要求されます。
これは、[[yii\data\SqlDataProvider::sql|sql]] によって指定される SQL 文は、現在要求されているページのデータだけを返すように、データプロバイダによって修正されてしまうからです。
データプロバイダは、総ページ数を正しく計算するためには、データアイテムの総数を知る必要があります。
## 配列データプロバイダ <span id="array-data-provider"></span>
[[yii\data\ArrayDataProvider]] は、一つの大きな配列を扱う場合に最も適しています。
このデータプロバイダによって、一つまたは複数のカラムで並べ替えた配列データの 1 ページ分を返すことが出来ます。
[[yii\data\ArrayDataProvider]] を使用するためには、全体の大きな配列として [[yii\data\ArrayDataProvider::allModels|allModels]] プロパティを指定しなければなりません。
この大きな配列の要素は、連想配列 (例えば [DAO](db-dao.md) のクエリ結果) またはオブジェクト (例えば [アクティブレコード](db-active-record.md) インスタンス) とすることが出来ます。
例えば、
```php
use yii\data\ArrayDataProvider;
$data = [
['id' => 1, 'name' => 'name 1', ...],
['id' => 2, 'name' => 'name 2', ...],
...
['id' => 100, 'name' => 'name 100', ...],
];
$provider = new ArrayDataProvider([
'allModels' => $data,
'pagination' => [
'pageSize' => 20,
'pageSize' => 10,
],
'sort' => [
'attributes' => ['id', 'name'],
],
]);
// 現在リクエストされているページの行を返す
$rows = $provider->getModels();
```
> Note|注意: [アクティブデータプロバイダ](#active-data-provider) および [SQL データプロバイダ](#sql-data-provider) と比較すると、配列データプロバイダは効率の面では劣ります。
何故なら、*全ての* データをメモリにロードしなければならないからです。
## データのキーを扱う <span id="working-with-keys"></span>
データプロバイダによって返されたデータアイテムを使用する場合、各データアイテムを一意のキーで特定しなければならないことがよくあります。
例えば、データアイテムが顧客情報を表す場合、顧客 ID を各顧客データのキーとして使用したいでしょう。
データプロバイダは、[[yii\data\DataProviderInterface::getModels()]] によって返されたデータアイテムに対応するそのようなキーのリストを返すことが出来ます。
例えば、
```php
use yii\data\ActiveDataProvider;
$query = Post::find()->where(['status' => 1]);
$provider = new ActiveDataProvider([
'query' => Post::find(),
]);
// 現在のページの user のレコードを取得する
$models = $dataProvider->getModels();
// Post オブジェクトの配列を返す
$posts = $provider->getModels();
// $post に対応するプライマリキーの値を返す
$ids = $provider->getKeys();
```
> Note|注意: ページネーションの機能を使いたい場合は、[[yii\data\SqlDataProvider::$totalCount]] プロパティに (ページネーション無しの) 総行数を設定しなければなりません。
そして、並べ替えの機能を使いたい場合は、どのカラムがソート出来るかをプロバイダが知ることが出来るように、[[yii\data\SqlDataProvider::$sort]] プロパティを構成しなければなりません。
上記の例では、[[yii\data\ActiveDataProvider]] に対して [[yii\db\ActiveQuery]] オブジェクトを供給していますから、キーとしてプライマリキーの値を返すのが理にかなっています。
キーの値の計算方法を明示的に指定するために、[[yii\data\ActiveDataProvider::key]] にカラム名を設定したり、キーの値を計算するコーラブルを設定したりすることも出来ます。
例えば、
```php
// "slug" カラムをキーの値として使用する
$provider = new ActiveDataProvider([
'query' => Post::find(),
'key' => 'slug',
]);
// md5(id) の結果をキーの値として使用する
$provider = new ActiveDataProvider([
'query' => Post::find(),
'key' => function ($model) {
return md5($model->id);
}
]);
```
あなた自身のカスタムデータプロバイダを実装する
----------------------------------------------
## カスタムデータプロバイダを作成する <span id="custom-data-provider"></span>
Yii はあなた自身のカスタムデータプロバイダを導入することを許容しています。
そうするためには、下記の `protected` メソッドを実装する必要があります。
あなた自身のカスタムデータプロバイダクラスを作成するためには、[[yii\data\DataProviderInterface]] を実装しなければなりません。
[[yii\data\BaseDataProvider]] を拡張するのが比較的簡単な方法です。
そうすれば、データプロバイダのコアのロジックに集中することが出来ます。
具体的に言えば、実装する必要があるのは、主として次のメソッドです。
- `prepareModels` - 現在のページで利用できるデータモデルを準備して、それを配列として返します。
- `prepareKeys` - 現在利用できるデータモデルの配列を受け取って、それと関連付けられるキーの配列を返します。
- `prepareTotalCount` - データプロバイダにあるデータモデルの総数を示す値を返します。
- [[yii\data\BaseDataProvider::prepareModels()|prepareModels()]]: 現在のページで利用できるデータモデルを準備して、それを配列として返します。
- [[yii\data\BaseDataProvider::prepareKeys()|prepareKeys()]]: 現在利用できるデータモデルの配列を受け取って、それと関連付けられるキーの配列を返します。
- [[yii\data\BaseDataProvider::prepareTotalCount()|prepareTotalCount]]: データプロバイダにあるデータモデルの総数を示す値を返します。
下記は、CSV ファイルを効率的に読み出すデータプロバイダのサンプルです。
```php
<?php
class CsvDataProvider extends \yii\data\BaseDataProvider
use yii\data\BaseDataProvider;
class CsvDataProvider extends BaseDataProvider
{
/**
* @var string 読み出すファイルの名前
* @var 読み出す CSV ファイルの名前
*/
public $filename;

119
docs/guide-ja/output-theming.md

@ -1,91 +1,95 @@
テーマ
======
> Note|注意: この節はまだ執筆中です。
テーマは、元のビューレンダリングのコードに触れる必要なしに、[ビュー](structure-views.md) のセットを別のセットに置き換えるための方法です。
テーマを使うとアプリケーションのルックアンドフィールを体系的に変更することが出来ます。
テーマとは、あるディレクトリの下に集められたビューとレイアウトのファイルです。
テーマの各ファイルが、アプリケーションの対応するファイルをレンダリングの際にオーバーライドします。
一つのアプリケーションは複数のテーマを使用することが可能で、それぞれのテーマはまったく異なるユーザ体験を提供することが出来ます。
いつでも一つのテーマだけがアクティブになり得ます。
テーマを使うためには、`view` アプリケーションコンポーネントの [[yii\base\View::theme|theme]] プロパティを構成しなければなりません。
このプロパティが、ビューファイルが置換される方法を管理する [[yii\base\Theme]] オブジェクトを構成します。
指定しなければならない [[yii\base\Theme]] のプロパティは主として以下のものです。
> Note|注意: ビューはアプリケーションの固有性が強いものですので、通常は、テーマを再配布可能なものとして作ることはしません。
カスタマイズしたルックアンドフィールを再配布したい場合は、テーマの代りに、[アセットバンドル](structure-assets.md) の形で CSS と JavaScript のファイルを再配布することを検討してください。
- [[yii\base\Theme::basePath]]: テーマのリソース (CSS、JS、画像など) を含むベースディレクトリを指定します。
- [[yii\base\Theme::baseUrl]]: テーマのリソースのベース URL を指定します。
- [[yii\base\Theme::pathMap]]: ビューファイルの置換の規則を指定します。
詳細は後述する項で説明します。
テーマを構成する
----------------
テーマの構成情報は、アプリケーションの `view` コンポーネントを通じて指定します。
`basic application` のビューに対して働くテーマをセットアップするためには、アプリケーションの構成情報ファイルに以下のように記述しなければなりません。
例えば、`SiteController` で `$this->render('about')` を呼び出すと、ビューファイル `@app/views/site/about.php` をレンダリングすることになります。
しかし、下記のようにアプリケーション構成情報でテーマを有効にすると、代りに、ビューファイル `@app/themes/basic/site/about.php` がレンダリングされます。
```php
'components' => [
'view' => [
'theme' => [
'pathMap' => ['@app/views' => '@app/themes/basic'],
'baseUrl' => '@web/themes/basic',
return [
'components' => [
'view' => [
'theme' => [
'basePath' => '@app/themes/basic'
'baseUrl' => '@web/themes/basic',
'pathMap' => [
'@app/views' => '@app/themes/basic',
],
],
],
],
],
];
```
上記においては、`pathMap` が元のパスからテーマのパスへの割り付けを定義し、`baseUrl` がテーマのファイルによって参照されるリソースのベース URL を定義しています。
> Info|情報: テーマではパスエイリアスがサポートされています。
ビューの置換を行う際に、パスエイリアスは実際のファイルパスまたは URL に変換されます。
私たちの例では、`pathMap` は `['@app/views' => '@app/themes/basic']`す。
これは、`@app/views` の全てのビューは、最初に `@app/themes/basic` の下で探され、そのテーマのディレクトリにビューが存在していれば、それが元のビューの代りに使われる、ということを意味します。
[[yii\base\View::theme]] プロパティを通じて [[yii\base\Theme]] オブジェクトにアクセスすることが出来ます。
例えば、ビューファイルの中では `$this` がビューオブジェクトを指すので、次のようなコードを書くことが出来ます。
例えば、上記の構成においては、ビューファイル `@app/views/site/index.php` のテーマ版は `@app/themes/basic/site/index.php` になります。
基本的には、`@app/views/site/index.php` の `@app/views``@app/themes/basic` に置き換えるわけです。
```php
$theme = $this->theme;
ランタイムにおいてテーマを構成するためには、ビューをレンダリングする前に次のコードを使用することが出来ます。
典型的には、コントローラの中に次のコードを置きます。
// $theme->baseUrl . '/img/logo.gif' を返す
$url = $theme->getUrl('img/logo.gif');
```php
$this->getView()->theme = Yii::createObject([
'class' => '\yii\base\Theme',
'pathMap' => ['@app/views' => '@app/themes/basic'],
'baseUrl' => '@web/themes/basic',
]);
// $theme->basePath . '/img/logo.gif' を返す
$file = $theme->getPath('img/logo.gif');
```
### モジュールにテーマを適用する
[[yii\base\Theme::pathMap]] プロパティが、ビューファイルがどのように置換されるべきかを制御します。
このプロパティは「キー・値」ペアの配列を取ります。
キーは置き換えられる元のビューのパスであり、値は対応するテーマのビューのパスです。
置換は部分一致に基づいて行われます。
あるビューのパスが [[yii\base\Theme::pathMap|pathMap]] 配列のキーのどれかで始っていると、その一致している部分が対応する配列の値によって置き換えられます。
上記の構成例を使う場合、`@app/views/site/about.php` は `@app/views` というキーに部分一致するため、`@app/themes/basic/site/about.php` に置き換えられることになります。
モジュールにテーマを適用するためには、`pathMap` を次のようなものにすることが出来ます。
### モジュールにテーマを適用する <span id="theming-modules"></span>
モジュールにテーマを適用するためには、[[yii\base\Theme::pathMap]] を次のように構成します。
```php
'components' => [
'view' => [
'theme' => [
'pathMap' => [
'@app/views' => '@app/themes/basic',
'@app/modules' => '@app/themes/basic/modules', // <-- !!!
],
],
],
'pathMap' => [
'@app/views' => '@app/themes/basic',
'@app/modules' => '@app/themes/basic/modules', // <-- !!!
],
```
これによって、`@app/modules/blog/views/comment/index.php` に `@app/themes/basic/modules/blog/views/comment/index.php` というテーマを適用することが出来ます。
### ウィジェットにテーマを適用する
`@app/widgets/currency/views/index.php` に配置されているウィジェットのビューにテーマを適用するためには、ビューコンポーネントのテーマに、次のような構成情報を設定する必要があります。
### ウィジェットにテーマを適用する <span id="theming-widgets"></span>
ウィジェットにテーマを適用するためには、[[yii\base\Theme::pathMap]] を次のように構成します。
```php
'components' => [
'view' => [
'theme' => [
'pathMap' => ['@app/widgets' => '@app/themes/basic/widgets'],
],
],
'pathMap' => [
'@app/views' => '@app/themes/basic',
'@app/widgets' => '@app/themes/basic/widgets', // <-- !!!
],
```
上記の構成によって、`@app/widgets/currency/index.php` ビューのテーマ版を `@app/themes/basic/widgets/currency/index.php` として作成することが出来るようになります。
これによって、`@app/widgets/currency/views/index.php` に `@app/themes/basic/widgets/currency/index.php` というテーマを適用することが出来ます。
複数のパスを使う
----------------
一つのパスを複数のテーマパスに割り付けることが出来ます。例えば、
## テーマの継承 <span id="theme-inheritance"></span>
場合によっては、基本的なルックアンドフィールを含むアプリケーションの基本テーマを定義しておいて、現在の祝日に基づいて少しだけルックアンドフィールを変更したい、ということがあるかもしれません。
テーマの継承を使ってこの目的を達することが出来ます。
テーマの継承は、一つのビューパスを複数のターゲットに割り付けることによって設定することが出来ます。
例えば、
```php
'pathMap' => [
@ -96,7 +100,6 @@ $this->getView()->theme = Yii::createObject([
]
```
この場合、最初に `@app/themes/christmas/site/index.php` というビューファイルが探され、それが見つからない場合は、次に `@app/themes/basic/site/index.php` が探されます。
そして、そこにもビューがない場合は、アプリケーションのビューが使用されます。
この機能は、いくつかのビューを一時的または条件的にオーバーライドしたい場合に、特に役立ちます。
この場合、ビュー `@app/views/site/index.php` には、どちらのテーマファイルが存在するかに従って、`@app/themes/christmas/site/index.php` または `@app/themes/basic/site/index.php` というテーマが適用されます。
テーマファイルが両方とも存在する場合は、最初のものが優先されます。
実際の場面では、ほとんどのテーマビューファイルを `@app/themes/basic` に保管し、その中のいくつかを `@app/themes/christmas` でカスタマイズすることになるでしょう。

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

@ -19,7 +19,7 @@ Yii は上記の全ての認証方法をサポートしています。新しい
あなたの API に対して認証を有効にするためには、次のステップを実行します。
1. `user` アプリケーションコンポーネントを構成します。
1. `user` [アプリケーションコンポーネント](structure-application-components.md) を構成します。
- [[yii\web\User::enableSession|enableSession]] プロパティを `false` に設定します。
- [[yii\web\User::loginUrl|loginUrl]] プロパティを `null` に設定し、ログインページにリダイレクトする代りに HTTP 403 エラーを表示します。
2. REST コントローラクラスにおいて、`authenticator` ビヘイビアを構成することによって、どの認証方法を使用するかを指定します。
@ -29,15 +29,15 @@ Yii は上記の全ての認証方法をサポートしています。新しい
[[yii\web\User::enableSession|enableSession]] が false である場合、ユーザの認証ステータスがセッションを使ってリクエストをまたいで存続することはありません。
その代りに、すべてのリクエストに対して認証が実行されます。このことは、ステップ 2 と 3 によって達成されます。
> Tip|情報: RESTful API をアプリケーションの形式で開発する場合は、アプリケーションの構成情報で `user` アプリケーションコンポーネントの [[yii\web\User::enableSession|enableSession]] プロパティを構成することが出来ます。
RESTful API をモジュールとして開発する場合は、次のように、モジュールの `init()` メソッドに一行を追加することが出来ます。
> Tip|情報: RESTful API をアプリケーションの形式で開発する場合は、アプリケーションの構成情報で `user` アプリケーションコンポーネント(structure-application-components.md) の [[yii\web\User::enableSession|enableSession]] プロパティを構成することが出来ます。
> RESTful API をモジュールとして開発する場合は、次のように、モジュールの `init()` メソッドに一行を追加することが出来ます。
> ```php
public function init()
{
parent::init();
\Yii::$app->user->enableSession = false;
}
```
> public function init()
> {
> parent::init();
> \Yii::$app->user->enableSession = false;
> }
> ```
例えば、HTTP Basic 認証を使う場合は、`authenticator` ビヘイビアを次のように構成することが出来ます。

2
docs/guide-ja/rest-error-handling.md

@ -74,7 +74,7 @@ return [
'class' => 'yii\web\Response',
'on beforeSend' => function ($event) {
$response = $event->sender;
if ($response->data !== null && !empty(Yii::$app->request->get('suppress_response_code'))) {
if ($response->data !== null && Yii::$app->request->get('suppress_response_code')) {
$response->data = [
'success' => $response->isSuccessful,
'data' => $response->data,

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

@ -19,12 +19,12 @@ Yii は、RESTful ウェブサービス API を実装する仕事を簡単にす
以下においては、例を使って、どのようにして最小限のコーディング労力で一組の RESTful API を構築することが出来るかを説明します。
ユーザのデータを RESTful API によって公開したいと仮定しましょう。
ユーザのデータは `user` という DB テーブルに保存されており、それにアクセスするための [[yii\db\ActiveRecord|ActiveRecord]] クラス `app\models\User` が既に作成済みであるとします。
ユーザのデータは `user` という DB テーブルに保存されており、それにアクセスするための [アクティブレコード](db-active-record.md) クラス `app\models\User` が既に作成済みであるとします。
## コントローラを作成する <span id="creating-controller"></span>
最初に、コントローラクラス `app\controllers\UserController` を次のようにして作成します。
最初に、[コントローラ](structure-controllers.md) クラス `app\controllers\UserController` を次のようにして作成します。
```php
namespace app\controllers;
@ -37,8 +37,11 @@ class UserController extends ActiveController
}
```
このコントローラクラスは、[[yii\rest\ActiveController]] を拡張するものです。
このコントローラクラスは、よく使用される一揃いの RESTful アクションを実装した [[yii\rest\ActiveController]] を拡張するものです。
[[yii\rest\ActiveController::modelClass|modelClass]] を `app\models\User` と指定することによって、データの取得と操作にどのモデルが使用できるかをコントローラに教えてやります。
The controller class extends from [[yii\rest\ActiveController]], which implements a common set of RESTful actions.
By specifying [[yii\rest\ActiveController::modelClass|modelClass]]
as `app\models\User`, the controller knows which model can be used for fetching and manipulating data.
## URL 規則を構成する <span id="configuring-url-rules"></span>
@ -61,7 +64,7 @@ class UserController extends ActiveController
## JSON の入力を可能にする <span id="enabling-json-input"></span>
API が JSON 形式で入力データを受け取ることが出来るように、`request` アプリケーションコンポーネントの [[yii\web\Request::$parsers|parsers]] プロパティを構成して、JSON 入力のために [[yii\web\JsonParser]] を使うようにします。
API が JSON 形式で入力データを受け取ることが出来るように、`request` [アプリケーションコンポーネント](structure-application-components.md) の [[yii\web\Request::$parsers|parsers]] プロパティを構成して、JSON 入力のために [[yii\web\JsonParser]] を使うようにします。
```php
'request' => [

3
docs/guide-ja/rest-response-formatting.md

@ -8,8 +8,7 @@ RESTful API のリクエストを処理するとき、アプリケーション
2. リソースオブジェクトを配列に変換します。
[リソース](rest-resources.md) の節で説明したように、この作業は [[yii\rest\Serializer]] によって実行されます。
3. 配列をコンテントネゴシエーションのステップで決定された形式の文字列に変換します。
この作業は、[[yii\web\Response::formatters|response]] アプリケーションコンポーネントに登録された [[yii\web\ResponseFormatterInterface|レスポンスフォーマッタ]] によって実行されます。
この作業は、`response` [アプリケーションコンポーネント](structure-application-components.md) の [[yii\web\Response::formatters|formatters]] プロパティに登録された [[yii\web\ResponseFormatterInterface|レスポンスフォーマッタ]] によって実行されます。
## コンテントネゴシエーション <span id="content-negotiation"></span>

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

@ -5,7 +5,7 @@
実際には、綺麗な URL を有効にして HTTP 動詞を利用したいというのが普通でしょう。
例えば、`POST /users` というリクエストが `user/create` アクションへのアクセスを意味するようにする訳です。
これは、アプリケーションの構成情報で `urlManager` アプリケーションコンポーネントを次のように構成することによって容易に達成することが出来ます。
これは、アプリケーションの構成情報で `urlManager` [アプリケーションコンポーネント](structure-application-components.md) を次のように構成することによって容易に達成することが出来ます。
```php
'urlManager' => [

10
docs/guide-ja/runtime-requests.md

@ -64,10 +64,10 @@ $param = $request->getBodyParam('id');
```php
$request = Yii::$app->request;
if ($request->isAjax) { // リクエストは AJAX リクエスト }
if ($request->isGet) { // リクエストメソッドは GET }
if ($request->isPost) { // リクエストメソッドは POST }
if ($request->isPut) { // リクエストメソッドは PUT }
if ($request->isAjax) { /* リクエストは AJAX リクエスト */ }
if ($request->isGet) { /* リクエストメソッドは GET */ }
if ($request->isPost) { /* リクエストメソッドは POST */ }
if ($request->isPut) { /* リクエストメソッドは PUT */ }
```
## リクエストの URL <span id="request-urls"></span>
@ -99,7 +99,7 @@ $headers = Yii::$app->request->headers;
// Accept ヘッダの値を返す
$accept = $headers->get('Accept');
if ($headers->has('User-Agent')) { // User-Agent ヘッダが在る }
if ($headers->has('User-Agent')) { /* User-Agent ヘッダが在る */ }
```
`request` コンポーネントは、よく使用されるいくつかのヘッダにすばやくアクセスする方法を提供しています。

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

@ -9,7 +9,7 @@ Yii のアプリケーションがリクエストされた URL の処理を開
これは、与えられたルートとそれに結び付けられたクエリパラメータから URL を生成するものです。
生成された URL が後でリクエストされたときには、ルーティングのプロセスがその URL を解決して元のルートとクエリパラメータに戻すことが出来ます。
ルーティングと URL 生成について主たる役割を果たすのが `urlManager` アプリケーションコンポーネントとして登録されている [[yii\web\UrlManager|URL マネージャ]] です。
ルーティングと URL 生成について主たる役割を果たすのが `urlManager` [アプリケーションコンポーネント](structure-application-components.md) として登録されている [[yii\web\UrlManager|URL マネージャ]] です。
[[yii\web\UrlManager|URL マネージャ]] は、入ってくるリクエストをルートとそれに結び付けられたクエリパラメータとして解析するための [[yii\web\UrlManager::parseRequest()|parseRequest()]] メソッドと、与えられたルートとそれに結び付けられたクエリパラメータから URL を生成するための [[yii\web\UrlManager::createUrl()|createUrl()]] メソッドを提供します。
アプリケーション構成情報の `urlManager` コンポーネントを構成することによって、既存のアプリケーションコードを修正することなく、任意の URL 形式をアプリケーションに認識させることが出来ます。

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

@ -218,6 +218,15 @@ $alerts = $session->getFlash('alerts');
これは、後者のメソッドが、同じ名前のフラッシュデータを追加できるように、フラッシュデータを自動的に配列に変換するからです。
その結果、[[yii\web\Session::getFlash()]] を呼び出したとき、この二つのメソッドの呼び出し順によって、あるときは配列を受け取り、あるときは文字列を受け取るということになってしまいます。
> Tip|ヒント: フラッシュメッセージを表示するためには、[[yii\bootstrap\Alert|bootstrap Alert]] ウィジェットを次のように使用することが出来ます。
>
> ```php
> echo Alert::widget([
> 'options' => ['class' => 'alert-info'],
> 'body' => Yii::$app->session->getFlash('postDeleted'),
> ]);
> ```
## クッキー <span id="cookies"></span>

155
docs/guide-ja/security-authentication.md

@ -1,23 +1,64 @@
認証
====
> Note|注意: この節はまだ執筆中です。
認証は、ユーザが誰であるかを確認するプロセスです。
通常は、識別子 (ユーザ名やメールアドレスなど) と秘密のトークン (パスワードやアクセストークンなど) を使って、ユーザがそうであると主張する通りのユーザであるか否かを判断します。
認証がログイン機能の基礎となります。
認証はユーザが誰であるかを確認する行為であり、ログインプロセスの基礎となるものです。
典型的には、認証は、識別子 (ユーザ名またはメールアドレス) とパスワードの組み合わせを使用します。
ユーザはこれらの値をフォームを通じて送信し、アプリケーションは送信された情報を以前に (例えば、ユーザ登録時に) 保存された情報と比較します。
Yii はログインをサポートするさまざまなコンポーネントを結び付ける認証フレームワークを提供しています。
このフレームワークを使用するために、あなたは主として次の仕事をする必要があります。
Yii では、このプロセス全体が半自動的に実行されます。
開発者に残されているのは、認証システムにおいて最も重要なクラスである [[yii\web\IdentityInterface]] を実装することだけです。
典型的には、`IdentityInterface` の実装は `User` モデルを使って達成されます。
* [[yii\web\User|user]] アプリケーションコンポーネントを構成する。
* [[yii\web\IdentityInterface]] インタフェイスを実装するクラスを作成する。
十分な機能を有する認証の実例を [アドバンストプロジェクトテンプレート](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide-ja/README.md) の中に見出すことが出来ます。
下記にインターフェイスのメソッドだけをリストします。
## [[yii\web\User]] を構成する <span id="configuring-user"></span>
[[yii\web\User|user]] アプリケーションコンポーネントがユーザの認証状態を管理します。
実際の認証ロジックを含む [[yii\web\User::identityClass|ユーザ識別情報クラス]] は、あなたが指定しなければなりません。
下記のアプリケーション構成情報においては、[[yii\web\User|user]] の [[yii\web\User::identityClass|ユーザ識別情報クラス]] は `app\models\User` であると構成されています。
`app\models\User` の実装については、次の項で説明します。
```php
return [
'components' => [
'user' => [
'identityClass' => 'app\models\User',
],
],
];
```
## [[yii\web\IdentityInterface]] を実装する <span id="implementing-identity"></span>
[[yii\web\User::identityClass|ユーザ識別情報クラス]] が実装しなければならない [[yii\web\IdentityInterface]] は次のメソッドを含んでいます。
* [[yii\web\IdentityInterface::findIdentity()|findIdentity()]]: 指定されたユーザ ID を使ってユーザ識別情報クラスのインスタンスを探します。
セッションを通じてログイン状態を保持する必要がある場合に、このメソッドが使用されます。
* [[yii\web\IdentityInterface::findIdentityByAccessToken()|findIdentityByAccessToken()]]: 指定されたアクセストークンを使ってユーザ識別情報クラスのインスタンスを探します。
単一の秘密のトークンでユーザを認証する必要がある場合 (ステートレスな RESTful アプリケーションなどの場合) に、このメソッドが使用されます。
* [[yii\web\IdentityInterface::getId()|getId()]]: ユーザ識別情報クラスのインスタンスによって表されるユーザの ID を返します。
* [[yii\web\IdentityInterface::getAuthKey()|getAuthKey()]]: クッキーベースのログインを検証するのに使用されるキーを返します。
このキーがログインクッキーに保存され、後でサーバ側のキーと比較されて、ログインクッキーが有効であることが確認されます。
* [[yii\web\IdentityInterface::validateAuthKey()|validateAuthKey()]]: クッキーベースのログインキーを検証するロジックを実装します。
特定のメソッドが必要でない場合は、中身を空にして実装しても構いません。
例えば、あなたのアプリケーションが純粋なステートレス RESTful アプリケーションであるなら、実装する必要があるのは [[yii\web\IdentityInterface::findIdentityByAccessToken()|findIdentityByAccessToken()]] と [[yii\web\IdentityInterface::getId()|getId()]] だけであり、他のメソッドは全て中身を空にしておくことが出来ます。
次の例では、[[yii\web\User::identityClass|ユーザ識別情報クラス]] は、`user` データベーステーブルと関連付けられた [アクティブレコード](db-active-record.md) クラスとして実装されています。
```php
<?php
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
class User extends ActiveRecord implements IdentityInterface
{
// ...
public static function tableName()
{
return 'user';
}
/**
* 与えられた ID によってユーザ識別情報を探す
@ -68,25 +109,91 @@ class User extends ActiveRecord implements IdentityInterface
}
```
概要を述べたメソッドのうち、二つは単純なものです。
`findIdentity` は ID の値を受け取って、その ID と関連付けられたモデルのインスタンスを返します。
`getId` メソッドは ID そのものを返します。
その他のメソッドのうち、二つのもの - `getAuthKey``validateAuthKey` - は、「次回から自動ログイン ("remember me")」のクッキーに対して追加のセキュリティを提供するために使われます。
`getAuthKey` メソッドは全てのユーザに対してユニークな文字列を返さなければなりません。
`Yii::$app->getSecurity()->generateRandomString()` を使うと、信頼性の高い方法でユニークな文字列を生成することが出来ます。
これをユーザのレコードの一部として保存しておくのは良いアイデアです。
前述のように、`getAuthKey()` と `validateAuthKey()` は、あなたのアプリケーションがクッキーベースのログイン機能を使用する場合にのみ実装する必要があります。
この場合、次のコードを使って、各ユーザに対して認証キーを生成して、`user` テーブルに保存しておくことが出来ます。
```php
public function beforeSave($insert)
class User extends ActiveRecord implements IdentityInterface
{
if (parent::beforeSave($insert)) {
if ($this->isNewRecord) {
$this->auth_key = Yii::$app->getSecurity()->generateRandomString();
......
public function beforeSave($insert)
{
if (parent::beforeSave($insert)) {
if ($this->isNewRecord) {
$this->auth_key = \Yii::$app->security->generateRandomString();
}
return true;
}
return true;
return false;
}
return false;
}
```
`validateAuthKey` メソッドでは、パラメータとして渡された `$authKey` 変数 (これ自体はクッキーから読み出されます) をデータベースから読み出された値と比較する必要があるだけです。
> Note|注意: ユーザ識別情報クラスである `User` と [[yii\web\User]] を混同してはいけません。
前者は認証のロジックを実装するクラスであり、普通は、ユーザの認証情報を保存する何らかの持続的ストレージと関連付けられた [アクティブレコード](db-active-record.md) クラスとして実装されます。
後者はユーザの認証状態の管理に責任を持つアプリケーションコンポーネントです。
## [[yii\web\User]] を使う <span id="using-user"></span>
[[yii\web\User]] は、主として、`user` アプリケーションコンポーネントの形で使います。
現在のユーザの識別情報は、`Yii::$app->user->identity` という式を使って取得することが出来ます。
これは、現在ログインしているユーザの [[yii\web\User::identityClass|ユーザ識別情報クラス]] のインスタンスを返すか、現在のユーザが認証されていない (つまりゲストである) 場合は null を返します。
次のコードは、[[yii\web\User]] からその他の認証関連の情報を取得する方法を示すものです。
```php
// 現在のユーザの識別情報。ユーザが認証されていない場合は null
$identity = Yii::$app->user->identity;
// 現在のユーザの ID。ユーザが認証されていない場合は null
$id = Yii::$app->user->id;
// 現在のユーザがゲストである (認証されていない) かどうか
$isGuest = Yii::$app->user->isGuest;
```
ユーザをログインさせるためには、次のコードを使うことが出来ます。
```php
// 指定された username を持つユーザ識別情報を探す
// 必要ならパスワードをチェックしてもよいことに注意
$identity = User::findOne(['username' => $username]);
// ユーザをログインさせる
Yii::$app->user->login($identity);
```
[[yii\web\User::login()]] メソッドは現在のユーザの識別情報を [[yii\web\User]] にセットします。
セッションが [[yii\web\User::enableSession|有効]] にされている場合は、ユーザの認証状態がセッション全体を通じて保持されるように、ユーザ識別情報がセッションに保管されます。
クッキーベースのログイン (つまり "remember me"、「次回は自動ログイン」) が [[yii\web\User::enableAutoLogin|有効]] にされている場合は、ユーザ識別情報をクッキーにも保存して、クッキーが有効である限りは、ユーザの認証状態をクッキーから復元することが可能になります。
クッキーベースのログインを有効にするためには、アプリケーションの構成情報で [[yii\web\User::enableAutoLogin]] を true に構成する必要があります。
また、[[yii\web\User::login()]] メソッドを呼ぶときには、有効期間のパラメータを与える必要があります。
ユーザをログアウトさせるためには、単に次のように `logout()` を呼びます。
```php
Yii::$app->user->logout();
```
ユーザのログアウトはセッションが有効にされている場合にだけ意味があることに注意してください。
`logout()` メソッドは、ユーザ認証状態をメモリとセッションの両方から消去します。
そして、デフォルトでは、ユーザのセッションデータの *全て* を破壊します。
セッションデータを保持したい場合は、代りに、`Yii::$app->user->logout(false)` を呼ばなければなりません。
## 認証のイベント <span id="auth-events"></span>
[[yii\web\User]] クラスは、ログインとログアウトのプロセスで、いくつかのイベントを発生させます。
* [[yii\web\User::EVENT_BEFORE_LOGIN|EVENT_BEFORE_LOGIN]]: [[yii\web\User::login()]] の開始時に発生します。
イベントハンドラがイベントの [[yii\web\UserEvent::isValid|isValid]] プロパティを false にセットした場合は、ログインのプロセスがキャンセルされます。
* [[yii\web\User::EVENT_AFTER_LOGIN|EVENT_AFTER_LOGIN]]: ログインが成功した時に発生します。
* [[yii\web\User::EVENT_BEFORE_LOGOUT|EVENT_BEFORE_LOGOUT]]: [[yii\web\User::logout()]] の開始時に発生します。
イベントハンドラがイベントの [[yii\web\UserEvent::isValid|isValid]] プロパティを false にセットした場合は、ログアウトのプロセスがキャンセルされます。
* [[yii\web\User::EVENT_AFTER_LOGOUT|EVENT_AFTER_LOGOUT]]: ログアウトが成功した時に発生します。
これらのイベントに反応して、ログイン監査、オンラインユーザ統計などの機能を実装することが出来ます。
例えば、[[yii\web\User::EVENT_AFTER_LOGIN|EVENT_AFTER_LOGIN]] のハンドラの中で、`user` テーブルにログインの日時と IP アドレスを記録することが出来ます。

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

@ -1,8 +1,6 @@
権限付与
========
> Note|注意: この節はまだ執筆中です。
権限付与は、ユーザが何かをするのに十分な許可を有しているか否かを確認するプロセスです。
Yii は二つの権限付与の方法を提供しています。すなわち、アクセス制御フィルタ (ACF) と、ロールベースアクセス制御 (RBAC) です。
@ -10,13 +8,14 @@ Yii は二つの権限付与の方法を提供しています。すなわち、
アクセス制御フィルタ (ACF)
--------------------------
アクセス制御フィルタ (ACF) は、何らかの単純なアクセス制御だけを必要とするアプリケーションで使うのに最も適した、単純な権限付与の方法です。
その名前が示すように、ACF は、コントローラまたはモジュールにビヘイビアとしてアタッチすることが出来るアクションフィルタです。
ACF は一連の [[yii\filters\AccessControl::rules|アクセス規則]] をチェックして、現在のユーザがリクエストしたアクションにアクセスすることが出来るかどうかを確認します。
アクセス制御フィルタ (ACF) は、[[yii\filters\AccessControl]] として実装される単純な権限付与の方法であり、何らかの単純なアクセス制御だけを必要とするアプリケーションで使うのに最も適したものです。
その名前が示すように、ACF は、コントローラまたはモジュールで使用することが出来るアクション [フィルタ](structure-filters.md) です。
ACF は、ユーザがアクションの実行をリクエストしたときに、一連の [[yii\filters\AccessControl::rules|アクセス規則]] をチェックして、現在のユーザがそのアクションにアクセスする許可を持つかどうかを決定します。
下記のコードは、[[yii\filters\AccessControl]] として実装された ACF の使い方を示すものです。
下記のコードは、`site` コントローラで ACF を使う方法を示すものです。
```php
use yii\web\Controller;
use yii\filters\AccessControl;
class SiteController extends Controller
@ -49,28 +48,29 @@ class SiteController extends Controller
上記のコードにおいて、ACF は `site` コントローラにビヘイビアとしてアタッチされています。
これがアクションフィルタを使用する典型的な方法です。
`only` オプションは、ACF が `login`、`logout`、`signup` のアクションにのみ適用されるべきであることを指定しています。
`site` コントローラの他の全てのアクションには ACF の影響は及びません。
`rules` オプションは [[yii\filters\AccessRule|アクセス規則]] を指定するものであり、以下のように読むことが出来ます。
- 全てのゲストユーザ (まだ認証されていないユーザ) に、'login' と 'singup' のアクションにアクセスすることを許可します。
`roles` オプションに疑問符 `?` が含まれていますが、これは「ゲスト」として認識される特殊なトークンです。
`roles` オプションに疑問符 `?` が含まれていますが、これは「ゲスト」を表す特殊なトークンです。
- 認証されたユーザに、'logout' アクションにアクセスすることを許可します。
`@` という文字はもう一つの特殊なトークンで、認証されたユーザとして認識されるものです。
`@` という文字はもう一つの特殊なトークンで、「認証されたユーザ」を表すものです。
ACF が権限のチェックを実行するときには、規則を一つずつ上から下へ、適用されるものを見つけるまで調べます。
そして、適用される規則の `allow` の値が、ユーザが権限を有するか否かを判断するのに使われます。
適用される規則が一つもなかった場合は、ユーザが権限をもたないことを意味し、ACF はアクションの継続を中止します。
デフォルトでは、ユーザが現在のアクションにアクセスする権限を持っていないと判定した場合は、ACF は以下のことだけを行います。
ユーザが現在のアクションにアクセスする権限を持っていないと判定した場合は、デフォルトでは、ACF は以下の手段を取ります。
* ユーザがゲストである場合は、[[yii\web\User::loginRequired()]] を呼び出します。
このメソッドで、ブラウザをログインページにリダイレクトすることが出来ます。
* ユーザがゲストである場合は、[[yii\web\User::loginRequired()]] を呼び出して、ユーザのブラウザをログインページにリダイレクトします。
* ユーザが既に認証されている場合は、[[yii\web\ForbiddenHttpException]] を投げます。
この動作は、[[yii\filters\AccessControl::denyCallback]] プロパティを構成することによって、カスタマイズすることが出来ます。
この動作は、次のように、[[yii\filters\AccessControl::denyCallback]] プロパティを構成することによって、カスタマイズすることが出来ます。
```php
[
'class' => AccessControl::className(),
...
'denyCallback' => function ($rule, $action) {
throw new \Exception('このページにアクセスする権限がありません。');
}
@ -100,7 +100,7 @@ ACF が権限のチェックを実行するときには、規則を一つずつ
- `?`: ゲストユーザ (まだ認証されていないユーザ) を意味します。
- `@`: 認証されたユーザを意味します。
その他のロール名を使う場合には、RBAC (次の節で説明します) が必要とされ、判断のために [[yii\web\User::can()]] が呼び出されます。
その他のロール名を使うと、[[yii\web\User::can()]] の呼び出しが惹起されますが、そのためには、RBAC (次の節で説明します) を有効にする必要があります。
このオプションが空であるか指定されていない場合は、規則が全てのロールに適用されることを意味します。
* [[yii\filters\AccessRule::ips|ips]]: どの [[yii\web\Request::userIP|クライアントの IP アドレス]] にこの規則が適用されるかを指定します。
@ -151,8 +151,7 @@ class SiteController extends Controller
```
ロールベースアクセス制御 (RBAC)
---------------------------------------
## ロールベースアクセス制御 (RBAC) <span id="rbac"></span>
ロールベースアクセス制御 (RBAC) は、単純でありながら強力な集中型のアクセス制御を提供します。
RBAC と他のもっと伝統的なアクセス制御スキーマとの比較に関する詳細については、[Wiki 記事](http://ja.wikipedia.org/wiki/%E3%83%AD%E3%83%BC%E3%83%AB%E3%83%99%E3%83%BC%E3%82%B9%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E5%88%B6%E5%BE%A1) を参照してください。
@ -166,7 +165,7 @@ RBAC を使用することには、二つの作業が含まれます。
説明を容易にするために、まず、いくつかの基本的な RBAC の概念を導入します。
### 基本的な概念
### 基本的な概念 <span id="basic-concepts"></span>
ロール (役割) は、*許可* (例えば、記事を作成する、記事を更新するなど) のコレクションです。
一つのロールを一人または複数のユーザに割り当てることが出来ます。
@ -183,14 +182,14 @@ Yii は、一般的な *半順序* 階層を実装していますが、これは
ロールは許可を含むことが出来ますが、許可はロールを含むことが出来ません。
### RBAC マネージャを構成する
### RBAC を構成する <span id="configuring-rbac"></span>
権限付与データを定義してアクセスチェックを実行する前に、[[yii\base\Application::authManager|authManager]] アプリケーションコンポーネントを構成する必要があります。
Yii は二種類の権限付与マネージャを提供しています。すなわち、[[yii\rbac\PhpManager]] と [[yii\rbac\DbManager]] です。
前者は権限付与データを保存するのに PHP スクリプトファイルを使いますが、後者は権限付与データをデータベースに保存します。
あなたのアプリケーションが非常に動的なロールと許可の管理を必要とするのでなければ、前者を使うことを考慮するのが良いでしょう。
#### authManager を `PhpManager` で構成する
#### `PhpManager` を使用する <span id="using-php-manager"></span>
次のコードは、アプリケーションの構成情報で [[yii\rbac\PhpManager]] クラスを使って `authManager` を構成する方法を示すものです。
@ -208,10 +207,10 @@ return [
これで `authManager``\Yii::$app->authManager` によってアクセスすることが出来るようになります。
> Tip|ヒント: デフォルトでは、[[yii\rbac\PhpManager]] は RBAC データを `@app/rbac/` ディレクトリの下のファイルに保存します。
権限の階層をオンラインで変更する必要がある場合は、必ず、ウェブサーバのプロセスがこのディレクトリとその中の全てのファイルに対する書き込み権限を有するようにしてください。
デフォルトでは、[[yii\rbac\PhpManager]] は RBAC データを `@app/rbac/` ディレクトリの下のファイルに保存します。
権限の階層をオンラインで変更する必要がある場合は、必ず、ウェブサーバのプロセスがこのディレクトリとその中の全てのファイルに対する書き込み権限を有するようにしてください。
#### authManager を `DbManager` で構成する
#### `DbManager` を使用する <span id="using-db-manager"></span>
次のコードは、アプリケーションの構成情報で [[yii\rbac\DbManager]] クラスを使って `authManager` を構成する方法を示すものです。
@ -243,7 +242,7 @@ return [
これで `authManager``\Yii::$app->authManager` によってアクセスすることが出来るようになります。
### 権限付与データを構築する
### 権限付与データを構築する <span id="generating-rbac-data"></span>
権限付与データを構築する作業は、つまるところ、以下のタスクに他なりません。
@ -335,7 +334,7 @@ public function signup()
動的に更新される権限付与データを持つ複雑なアクセス制御を必要とするアプリケーションについては、`authManager` が提供する API を使って、特別なユーザインタフェイス (つまり、管理パネル) を開発する必要があるでしょう。
### 規則を使う
### 規則を使う <span id="using-rules"></span>
既に述べたように、規則がロールと許可に制約を追加します。
規則は [[yii\rbac\Rule]] を拡張したクラスであり、[[yii\rbac\Rule::execute()|execute()]] メソッドを実装しなければなりません。
@ -394,7 +393,7 @@ $auth->addChild($author, $updateOwnPost);
![規則を持つ RBAC 階層](images/rbac-hierarchy-2.png "規則を持つ RBAC 階層")
### アクセスチェック
### アクセスチェック <span id="access-check"></span>
権限付与データが準備できてしまえば、アクセスチェックは [[yii\rbac\ManagerInterface::checkAccess()]] メソッドを呼ぶだけの簡単な仕事です。
たいていのアクセスチェックは現在のユーザに関するものですから、Yii は、便利なように、[[yii\web\User::can()]] というショートカットメソッドを提供しています。
@ -406,7 +405,7 @@ if (\Yii::$app->user->can('createPost')) {
}
```
現在のユーザが ID=1 である Jane であるとすると、`createPost` からスタートして `Jane` まで到達しようと試みます。
現在のユーザが `ID=1` である Jane であるとすると、`createPost` からスタートして `Jane` まで到達しようと試みます。
![アクセスチェック](images/rbac-access-check-1.png "アクセスチェック")
@ -431,7 +430,7 @@ Jane の場合は、彼女が管理者であるため、少し簡単になりま
![アクセスチェック](images/rbac-access-check-3.png "アクセスチェック")
### デフォルトロールを使う
### デフォルトロールを使う <span id="using-default-roles"></span>
デフォルトロールというのは、*全て* のユーザに *黙示的* に割り当てられるロールです。
[[yii\rbac\ManagerInterface::assign()]] を呼び出す必要はなく、権限付与データはその割り当て情報を含みません。

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

@ -136,12 +136,18 @@ CSRF は、クロスサイトリクエストフォージェリ (cross-site reque
例えば、`an.example.com` というウェブサイトが `/logout` という URL を持っており、この URL を単純な GET でアクセスするとユーザをログアウトさせるようになっているとします。
ユーザ自身によってこの URL がリクエストされる限りは何も問題はありませんが、ある日、悪い奴が、ユーザが頻繁に訪れるフォーラムに `<img src="http://an.example.com/logout">` というリンクを含むコンテントを何とかして投稿することに成功します。
ブラウザは画像のリクエストとページのリクエストの間に何ら区別を付けませんので、ユーザがそのような `img` タグを含むページを開くと `an.example.com` からログアウトされてしまうことになる訳です。
ブラウザは画像のリクエストとページのリクエストの間に何ら区別を付けませんので、ユーザがそのような `img` タグを含むページを開くとブラウザはその URL に対して GET リクエストを送信します。
そして、ユーザが `an.example.com` からログアウトされてしまうことになる訳です。
これは基本的な考え方です。ユーザがログアウトされるぐらいは大したことではない、と言うことも出来るでしょう。
しかし、POST を送信することも、それほど難しくはありません。
CSRF を回避するためには、次のことを守らなければなりません。
しかし、悪い奴は、この考え方を使って、もっとひどいことをすることも出来ます。
例えば、`http://an.example.com/purse/transfer?to=anotherUser&amout=2000` という URL を持つウェブサイトがあると考えて見てください。
この URL に GET リクエストを使ってアクセスすると、権限を持つユーザアカウントから `anotherUser` に $2000 が送金されるのです。
私たちは、ブラウザは画像をロードするのに常に GET リクエストを使う、ということを知っていますから、この URL が POST リクエストだけを受け入れるようにコードを修正することは出来ます。
しかし残念なことに、それで問題が解決する訳ではありません。
攻撃者は `<img>` タグの代りに何らかの JavaScript コードを書いて、その URL に対する POST リクエストの送信を可能にすることが出来ます。
CSRF を回避するためには、常に次のことを守らなければなりません。
1. HTTP の規格、すなわち、GET はアプリケーションの状態を変更すべきではない、という規則に従うこと。
2. Yii の CSRF 保護を有効にしておくこと。

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

@ -1,5 +1,5 @@
セキュリティ
============
パスワードを扱う
================
> Note|注意: この節はまだ執筆中です。

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

@ -25,6 +25,7 @@
namespace app\models;
use Yii;
use yii\base\Model;
class EntryForm extends Model

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

@ -15,7 +15,7 @@ Gii を使ってコードを自動生成することは、Gii のウェブペー
Gii を開始する <span id="starting-gii"></span>
--------------
[Gii](tool-gii.md) は Yii の [モジュール](structure-modules.md) として提供されています。
[Gii](https://github.com/yiisoft/yii2-gii/blob/master/docs/guide-ja/README.md) は Yii の [モジュール](structure-modules.md) として提供されています。
Gii は、アプリケーションの [[yii\base\Application::modules|modules]] プロパティの中で構成することで有効にすることが出来ます。
アプリケーションを生成した仕方にもよりますが、`config/web.php` の構成情報ファイルの中に、多分、下記のコードが既に提供されているでしょう。

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

@ -1,7 +1,7 @@
Yii をインストールする
======================
Yii は二つの方法でインストールすることが出来ます。すなわち、[Composer](http://getcomposer.org/) を使うか、アーカイブファイルをダウンロードするかです。
Yii は二つの方法でインストールすることが出来ます。すなわち、[Composer](https://getcomposer.org/) を使うか、アーカイブファイルをダウンロードするかです。
前者がお薦めの方法です。と言うのは、一つのコマンドを走らせるだけで、新しい [エクステンション](structure-extensions.md) をインストールしたり、Yii をアップデートしたりすることが出来るからです。
Yii の標準的なインストールを実行すると、フレームワークとプロジェクトテンプレートの両方がダウンロードされてインストールされます。
@ -24,7 +24,7 @@ Composer によるインストール <span id="installing-via-composer"></span>
まだ Composer をインストールしていない場合は、[getcomposer.org](https://getcomposer.org/download/) の指示に従ってインストールすることが出来ます。
Linux や Mac OS X では、次のコマンドを実行します。
curl -s http://getcomposer.org/installer | php
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
Windows では、[Composer-Setup.exe](https://getcomposer.org/Composer-Setup.exe) をダウンロードして実行します。
@ -36,7 +36,7 @@ Composer は `composer self-update` コマンドを実行してアップデー
Composer がインストールされたら、ウェブからアクセスできるフォルダで下記のコマンドを実行することによって Yii をインストールすることが出来ます。
composer global require "fxp/composer-asset-plugin:1.0.0"
composer global require "fxp/composer-asset-plugin:~1.0.0"
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
最初のコマンドは [composer アセットプラグイン](https://github.com/francoispluchino/composer-asset-plugin/) をインストールします。

7
docs/guide-ja/structure-applications.md

@ -2,7 +2,8 @@
================
アプリケーションは Yii アプリケーションシステム全体の構造とライフサイクルを統制するオブジェクトです。
全ての Yii アプリケーションシステムは、それぞれ、[エントリスクリプト](structure-entry-scripts.md) において作成され、`\Yii::$app` という式でグローバルにアクセス可能な、単一のアプリケーションオブジェクトを持ちます。
全ての Yii アプリケーションシステムは、それぞれ、単一のアプリケーションオブジェクトを持ちます。
アプリケーションオブジェクトは、[エントリスクリプト](structure-entry-scripts.md) において作成され、`\Yii::$app` という式でグローバルにアクセスすることが出来るオブジェクトです。
> Info|情報: ガイドの中で「アプリケーション」という言葉は、文脈に応じて、アプリケーションオブジェクトを意味したり、アプリケーションシステムを意味したりします。
@ -384,7 +385,7 @@ $width = \Yii::$app->params['thumbnail.size'][0];
このプロパティは、アプリケーションにインストールされて使われている [エクステンション](structure-extensions.md) のリストを指定するものです。
デフォルトでは、`@vendor/yiisoft/extensions.php` というファイルによって返される配列を取ります。
`extensions.php` は、[Composer](http://getcomposer.org) を使ってエクステンションをインストールすると、自動的に生成され保守されます。
`extensions.php` は、[Composer](https://getcomposer.org) を使ってエクステンションをインストールすると、自動的に生成され保守されます。
ですから、たいていの場合、このプロパティをあなたが構成する必要はありません。
エクステンションを手作業で保守したいという特殊なケースにおいては、次のようにしてこのプロパティを構成することが出来ます。
@ -453,7 +454,7 @@ $width = \Yii::$app->params['thumbnail.size'][0];
#### [[yii\base\Application::vendorPath|vendorPath]] <span id="vendorPath"></span>
このプロパティは、[Composer](http://getcomposer.org) によって管理される vendor ディレクトリを指定するものです。
このプロパティは、[Composer](https://getcomposer.org) によって管理される vendor ディレクトリを指定するものです。
Yii フレームワークを含めて、あなたのアプリケーションによって使われる全てのサードパーティライブラリを格納するディレクトリです。
デフォルト値は、`@app/vendor` というエイリアスで表現されるディレクトリです。

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

@ -119,20 +119,20 @@ class SiteController extends Controller
### コントローラクラスの命名規則 <span id="controller-class-naming"></span>
コントローラクラスの名前は下記の規則に従ってコントローラ ID から導出することが出来ます。
コントローラクラスの名前は下記の手順に従ってコントローラ ID から導出することが出来ます。
* ダッシュで区切られた各単語の最初の文字を大文字に変える。
コントローラ ID がスラッシュを含む場合、この規則は ID の最後のスラッシュの後ろの部分にのみ適用されることに注意。
* ダッシュを削除し、フォワードスラッシュを全てバックワードスラッシュに置き換える。
* 接尾辞 `Controller` を追加する。
* そして、[[yii\base\Application::controllerNamespace|コントローラ名前空間]] を頭に付ける。
1. ハイフンで区切られた各単語の最初の文字を大文字に変える。
コントローラ ID がスラッシュを含む場合、この規則は ID の最後のスラッシュの後ろの部分にのみ適用されることに注意。
2. ハイフンを削除し、フォワードスラッシュを全てバックワードスラッシュに置き換える。
3. 接尾辞 `Controller` を追加する。
4. [[yii\base\Application::controllerNamespace|コントローラ名前空間]] を頭に付ける。
以下は、[[yii\base\Application::controllerNamespace|コントローラ名前空間]] がデフォルト値 `app\controllers` を取っていると仮定したときの、いくつかの例です。
* `article` から `app\controllers\ArticleController` が導出される。
* `post-comment` から `app\controllers\PostCommentController` が導出される。
* `admin/post-comment` から `app\controllers\admin\PostCommentController` が導出される。
* `adminPanels/post-comment` から `app\controllers\adminPanels\PostCommentController` が導出される。
* `article` `app\controllers\ArticleController` になる。
* `post-comment` `app\controllers\PostCommentController` になる。
* `admin/post-comment` `app\controllers\admin\PostCommentController` になる。
* `adminPanels/post-comment` `app\controllers\adminPanels\PostCommentController` になる。
コントローラクラスは [オートロード可能](concept-autoloading.md) でなければなりません。
この理由により、上記の例の `aritcle` コントローラクラスは [エイリアス](concept-aliases.md) が `@app/controllers/ArticleController.php` であるファイルに保存されるべきものとなります。
@ -213,8 +213,8 @@ class SiteController extends Controller
アクションは、たいてい、あるリソースについて特定の操作を実行するように設計されます。
この理由により、アクション ID は、通常、`view`、`update` などのような動詞になります。
デフォルトでは、アクション ID は、小文字の英字、数字、アンダースコア、そして、ダッシュのみを含むべきものです。
アクション ID の中のダッシュは単語を分けるために使われます。
デフォルトでは、アクション ID は、小文字の英字、数字、アンダースコア、そして、ハイフンのみを含むべきものです。
アクション ID の中のハイフンは単語を分けるために使われます。
例えば、`view`、`update2`、`comment-post` は全て有効なアクション ID ですが、`view?`、`Update` はそうではありません。
アクションは二つの方法、すなわち、インラインアクションまたはスタンドアロンアクションとして作成することが出来ます。
@ -227,11 +227,11 @@ class SiteController extends Controller
インラインアクションは、たった今説明したように、アクションメソッドの形で定義されるアクションを指します。
アクションメソッドの名前は、次の基準に従って、アクション ID から導出されます。
アクションメソッドの名前は、次の手順に従って、アクション ID から導出されます。
* アクション ID に含まれる各単語の最初の文字を大文字に変換する。
* ダッシュを削除する。
* 接頭辞 `action` を付ける。
1. アクション ID に含まれる各単語の最初の文字を大文字に変換する。
2. ハイフンを削除する。
3. 接頭辞 `action` を付ける。
例えば、`index` は `actionIndex` となり、`hello-world` は `actionHelloWorld` となります。
@ -397,10 +397,10 @@ class SiteController extends Controller
* アクション ID に合致するアクションメソッドが見つかった場合は、インラインアクションが作成される。
* 上記以外の場合は、[[yii\base\InvalidRouteException]] 例外が投げられる。
3. コントローラは、アプリケーション、(コントローラがモジュールに属する場合は) モジュール、そしてコントローラの `beforeAction()` メソッドをこの順で呼び出す。
* どれか一つの呼び出しが false を返した場合は、残りのまだ呼ばれていない `beforeAction()` はスキップされ、アクションの実行はキャンセルされる。
* どれか一つの呼び出しが false を返した場合は、残りのまだ呼ばれていない `beforeAction()` メソッドはスキップされ、アクションの実行はキャンセルされる。
* デフォルトでは、それぞれの `beforeAction()` メソッドは、ハンドラをアタッチすることが可能な `beforeAction` イベントをトリガする。
4. コントローラがアクションを実行する。
* リクエストデータが解析されて、アクションパラメータにデータが投入される。
* アクションパラメータが解析されて、リクエストデータからデータが投入される。
5. コントローラは、コントローラ、(コントローラがモジュールに属する場合は) モジュール、そしてアプリケーションの `afterAction()` メソッドをこの順で呼び出す。
* デフォルトでは、それぞれの `afterAction()` メソッドは、ハンドラをアタッチすることが可能な `afterAction` イベントをトリガする。
6. アプリケーションはアクションの結果を受け取り、それを [レスポンス](runtime-responses.md) に割り当てる。
@ -411,7 +411,7 @@ class SiteController extends Controller
良く設計されたアプリケーションでは、コントローラはたいてい非常に軽いものになり、それぞれのアクションは数行のコードしか含まないものになります。
あなたのコントローラが少々複雑になっている場合、そのことは、通常、コントローラをリファクタして、コードの一部を他のクラスに移動すべきことを示すものです。
要約すると、コントローラは、
いくつかのベストプラクティスを特に挙げるなら、コントローラは、
* [リクエスト](runtime-requests.md) データにアクセスすることが出来ます。
* リクエストデータを使って [モデル](structure-models.md) や他のサービスコンポーネントのメソッドを呼ぶことが出来ます。

4
docs/guide-ja/structure-entry-scripts.md

@ -1,7 +1,7 @@
エントリスクリプト
==================
エントリスクリプトは、アプリケーションのブートストラップ過程のチェーンにおける最初の環です。
エントリスクリプトは、アプリケーションのブートストラップの過程における最初のステップです。
アプリケーションは (ウェブアプリケーションであれ、コンソールアプリケーションであれ)単一のエントリスクリプトを持ちます。
エンドユーザはエントリスクリプトに対してリクエストを発行し、エントリスクリプトはアプリケーションのインスタンスを作成して、それにリクエストを送付します。
@ -14,7 +14,7 @@
エントリスクリプトは主として次の仕事をします。
* グローバルな定数を定義する。
* [Composer のオートローダ](http://getcomposer.org/doc/01-basic-usage.md#autoloading) を登録する。
* [Composer のオートローダ](https://getcomposer.org/doc/01-basic-usage.md#autoloading) を登録する。
* [[Yii]] クラスファイルをインクルードする。
* アプリケーションの構成情報を読み出す。
* [アプリケーション](structure-applications.md) のインスタンスを生成して構成する。

2
docs/guide-ja/test-fixtures.md

@ -373,4 +373,4 @@ Auto-generating fixtures
Yii also can auto-generate fixtures for you based on some template. You can generate your fixtures with different data on different languages and formats.
These feature is done by [Faker](https://github.com/fzaninotto/Faker) library and `yii2-faker` extension.
See extension [guide](https://github.com/yiisoft/yii2/tree/master/extensions/faker) for more docs.
See extension [guide](https://github.com/yiisoft/yii2-faker) for more docs.

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

@ -97,18 +97,23 @@ public function rules()
```
このバリデータは、入力値が正しい書式の date、time、または datetime であるかどうかをチェックします。
オプションとして、入力値を UNIX タイムスタンプに変換して、[[yii\validators\DateValidator::timestampAttribute|timestampAttribute]] によって指定された属性に保存することも出来ます。
オプションとして、入力値を UNIX タイムスタンプ (または、その他、機械による読み取りが可能な形式) に変換して、[[yii\validators\DateValidator::timestampAttribute|timestampAttribute]] によって指定された属性に保存することも出来ます。
- `format`: 検証される値が従っているべき日付/時刻の書式。
これには [ICU manual](http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax) で記述されている日付/時刻のパターンを使うことが出来ます。
あるいは、PHP の `Datetime` クラスによって認識される書式に接頭辞 `php:` を付けた文字列でも構いません。
サポートされている書式については、<http://php.net/manual/ja/datetime.createfromformat.php> を参照してください。
このプロパティが設定されていないときは、`Yii::$app->formatter->dateFormat` の値を取ります。
- `timestampAttribute`: このバリデータが、入力された日付/時刻から変換した UNIX タイムスタンプを代入することが出来る属性の名前。
これは、検証される属性と同じ属性であってもかまいません。
その場合は、元の値は検証実行後にタイムスタンプで上書きされます。
[DatePicker で日付の入力を扱う](widget-jui#datepicker-date-input) に使用例がありますので、参照してください。
バージョン 2.0.4 以降では、[[yii\validators\DateValidator::$timestampAttributeFormat|$timestampAttributeFormat]] と [[yii\validators\DateValidator::$timestampAttributeTimeZone|$timestampAttributeTimeZone]] を使って、この属性に対するフォーマットとタイムゾーンを指定することが出来ます。
- バージョン 2.0.4 以降では、タイムスタンプの [[yii\validators\DateValidator::$min|最小値]] または [[yii\validators\DateValidator::$max|最大値]] を指定することも出来ます。
入力が必須でない場合には、date バリデータに加えて、default バリデータ (デフォルト値フィルタ) を追加すれば、空の入力値が `NULL` として保存されることを保証することが出来ます。
そうしないと、データベースに `0000-00-00` という日付が保存されたり、デートピッカーの入力フィールドが `1970-01-01` になったりしてしまいます。
@ -241,9 +246,12 @@ function foo($model, $attribute) {
]
```
このバリデータは、入力値がテーブルのカラムに存在するかどうかをチェックします。
[アクティブレコード](db-active-record.md) モデルの属性に対してのみ働きます。
一つのカラムに対するバリデーションか、複数のカラムに対するバリデーションか、どちらかをサポートします。
このバリデータは、入力値が [アクティブレコード](db-active-record.md) の属性によって表されるテーブルのカラムに存在するかどうかをチェックします。
`targetAttribute` を使って [アクティブレコード](db-active-record.md) の属性を指定し、`targetClass` によって対応するクラスを指定することが出来ます。
これらを指定しない場合は、検証されるモデルの属性とクラスの値が使用されます。
このバリデータは、一つまたは複数のカラムに対する検証に使用することが出来ます
(複数のカラムに対する検証の場合は、それらの属性の組み合せが存在しなければならないことを意味します)。
- `targetClass`: 検証される入力値を探すために使用される [アクティブレコード](db-active-record.md) クラスの名前。
設定されていない場合は、現在検証されているモデルのクラスが使用されます。

3
docs/guide-ja/tutorial-i18n.md

@ -517,7 +517,8 @@ use yii\i18n\MissingTranslationEvent;
class TranslationEventHandler
{
public static function handleMissingTranslation(MissingTranslationEvent $event) {
public static function handleMissingTranslation(MissingTranslationEvent $event)
{
$event->translatedMessage = "@MISSING: {$event->category}.{$event->message} FOR LANGUAGE {$event->language} @";
}
}

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

@ -5,53 +5,58 @@
あなたのウェブアプリケーションのパフォーマンスは二つの部分に基づいています。
一つはフレームワークのパフォーマンスであり、もう一つはアプリケーションそのものです。
Yii は、そのままの状態でも、あなたのアプリケーションのパフォーマンスを劣化させる影響がかなり小さいものですが、本番環境のためには、さらに微調整することが可能です。
Yii は、そのままの状態でも、パフォーマンスを劣化させる影響がかなり小さいものですが、本番環境のためには、さらに微調整することが可能です。
アプリケーションに関しては、ベストプラクティスのいくつかを提供すると共に、それを Yii に適用する方法を例示します。
環境を準備する
--------------
## PHP 環境を最適化する <span id="optimizing-php"></span>
PHP アプリケーションを走らせるための環境を正しく構成することは本当に重要です。
PHP 環境を正しく構成することは非常に重要です。
最大のパフォーマンスを得るためには、
- 常に最新の安定した PHP バージョンを使うこと。
PHP は、メジャーリリースのたびに、顕著なパフォーマンスの改善とメモリ使用の削減がなされています。
- PHP 5.4 以下には [APC](http://ru2.php.net/apc)、または、PHP 5.5 以上には [Opcache](http://php.net/opcache) を使うこと。
このことは、非常に良いパフォーマンス強化をもたらします。
- 最新の安定した PHP バージョンを使うこと。
使用する PHP のメジャーリリースを上げると、顕著なパフォーマンスの改善がもたらされることがあります。
- [Opcache](http://php.net/opcache) (PHP 5.5 以降) または [APC](http://ru2.php.net/apc) (PHP 5.4 以前) を使って、バイトコードキャッシュを有効にすること。
バイトコードキャッシュによって、リクエストが入ってくるたびに PHP スクリプトを解析してインクルードする時間の浪費を避けることが出来ます。
フレームワークを本番用に準備する
--------------------------------
## デバッグモードを無効にする <span id="disable-debug"></span>
### デバッグモードを無効化する
本番環境でアプリケーションを実行するときには、デバッグモードを無効にしなければなりません。
Yii は、`YII_DEBUG` という名前の定数の値を使って、デバッグモードを有効にすべきか否かを示します。
デバッグモードが有効になっているときは、Yii はデバッグ情報の生成と記録のために時間を余計に費やします。
アプリケーションを本番環境に配備する前に行うべき最初のことは、デバッグモードの無効化です。
Yii のアプリケーションは、`index.php` において定数 `YII_DEBUG``true` と定義されていると、デバッグモードで走ります。
従って、デバッグモードを無効にするために、以下のコードが `index.php` になければなりません。
[エントリスクリプト](structure-entry-scripts.md) の冒頭に次のコード行を置くことによってデバッグモードを無効にすることが出来ます。
```php
defined('YII_DEBUG') or define('YII_DEBUG', false);
```
デバッグモードは開発段階において非常に役に立ちますが、いくつかのコンポーネントがデバッグモードにおいて追加の負荷を発生させるため、パフォーマンスを劣化させます。
例えば、メッセージロガーは、ログに記録されるすべてのメッセージについて、追加のデバッグ情報を記録します
> Info|情報: `YII_DEBUG` のデフォルト値は false です。
従って、アプリケーションコードの他のどこかでこのデフォルト値を変更していないと確信できるなら、単に上記の行を削除してデバッグモードを無効にしても構いません
### PHP opcode キャッシュを有効にする
## キャッシュのテクニックを使う <span id="using-caching"></span>
PHP opcode キャッシュを有効にすると、すべての PHP アプリケーションで、顕著にパフォーマンスが向上し、メモリ使用量が削減されます。
Yii も例外ではありません
Yii は [PHP 5.5 OPcache](http://php.net/manual/ja/book.opcache.php) と [APC PHP 拡張](http://php.net/manual/ja/book.apc.php) の両方でテストされています
どちらのキャッシュも、PHP 中間コードを最適化して、入ってくるリクエストごとに PHP スクリプトを解析するために時間を消費することを回避します
さまざまなキャッシュのテクニックを使うと、あなたのアプリケーションのパフォーマンスを目に見えて改善することが出来ます。
たとえば、あなたのアプリケーションが Markdown 形式のテキスト入力をユーザに許可している場合、解析済みの Markdown のコンテントをキャッシュすることを考慮してください
そうすれば、リクエストごとに毎回同じ Markdown テキストの解析を繰り返すことを回避できるでしょう
Yii によって提供されているキャッシュのサポートについて学ぶためには [キャッシュ](caching-overview.md) の節を参照してください
### ActiveRecord のデータベーススキーマキャッシュを有効にする
## スキーマキャッシュを有効にする <span id="enable-schema-caching"></span>
アプリケーションがアクティブレコードを使用している場合は、スキーマキャッシュを有効にして、データベーススキーマを解析するための時間を節約すべきです。
そうするためには、アプリケーションの構成情報 `config/web.php` において、`Connection::enableSchemaCache` プロパティを `true` に設定します。
スキーマキャッシュは、[アクティブレコード](db-active-record.md) を使おうとする場合には、いつでも有効にすべき特別なキャッシュ機能です。
ご存じのように、アクティブレコードは、賢いことに、あなたがわざわざ記述しなくても、DB テーブルに関するスキーマ情報 (カラムの名前、カラムのタイプ、外部キー制約など) を自動的に検出します。
アクティブレコードはこの情報を取得するために追加の SQL クエリを実行しています。
スキーマキャッシュを有効にすると、取得されたスキーマ情報はキャッシュに保存されて将来のクエリで再利用されるようになります。
スキーマキャッシュを有効にするためには、[アプリケーションの構成情報](concept-configurations.md) の中で、`cache` [アプリケーションコンポーネント](structure-application-components.md) にスキーマ情報を保存するように構成し、[[yii\db\Connection::enableSchemaCache]] を `true` に設定します。
```php
return [
// ...
'components' => [
// ...
'cache' => [
'class' => 'yii\caching\FileCache',
],
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=mydatabase',
@ -60,28 +65,23 @@ return [
'enableSchemaCache' => true,
// スキーマキャッシュの持続時間
// 'schemaCacheDuration' => 3600,
'schemaCacheDuration' => 3600,
// 使用されるキャッシュコンポーネントの名前。デフォルトは 'cache'。
//'schemaCache' => 'cache',
],
'cache' => [
'class' => 'yii\caching\FileCache',
// スキーマ情報を保存するのし使用されるキャッシュコンポーネントの名前
'schemaCache' => 'cache',
],
],
];
```
`cache` [アプリケーションコンポーネント](structure-application-components.md) が構成されていなければならないことに注意してください。
## アセットを結合して最小化する <span id="optimizing-assets"></span>
### アセットを結合して最小化する
複雑なウェブページでは、多数の CSS や JavaScript のアセットファイルをインクルードすることがよくあります。
HTTP リクエストの回数、および、これらのアセットの全体としてのダウンロードサイズを削減するために、アセットを単一のファイルに結合して、それを圧縮することを考慮すべきです。
これによって、ページのロードにかかる時間とサーバの負荷を大きく削減することが出来ます。
詳細については、[アセット](structure-assets.md) の節を参照してください。
アセットは、典型的には JavaScript と CSS ですが、結合して圧縮することが出来ます。
これにより、ページの読み込みにかかる時間をわずかながら削減して、アプリケーションのエンドユーザにより良いユーザ体験をもたらすことが出来ます。
これをどのようにすれば達成できるかについて学ぶためには、ガイドの [アセット](structure-assets.md) の節を参照してください。
### セッションのためにより良いストレージを使用する
## セッションのためにより良いストレージを使用する
デフォルトでは、PHP はセッションを処理するためにファイルを使います。
開発と小さなプロジェクトではそれでも構いませんが、リクエストを並列処理するとなると、データベースのような別のストレージに変更する方が良いでしょう。
@ -111,101 +111,50 @@ return [
サーバに [Redis](http://redis.io/) がある場合は、それをセッションのストレージに使用することを強く推奨します。
アプリケーションを改善する
--------------------------
### サーバ側のキャッシュテクニックを使う
キャッシュの節で説明されているように、Yii はウェブアプリケーションのパフォーマンスを著しく改善することが出来るキャッシュのソリューションをいくつか提供しています。
データの生成に長い時間を要するものがある場合は、データキャッシュの手法を使用して、データを生成する頻度を削減することが出来ます。
ページのある部分が比較的静的なものであり続ける場合は、フラグメントキャッシュの手法を使用して、その部分のレンダリングの頻度を削減することが出来ます。
あるページ全体が比較的静的なものであり続ける場合は、ページキャッシュの手法を使用して、ページ全体のレンダリングのコストを節約することが出来ます。
### HTTP キャッシュを利用して、処理時間と帯域を節約する
HTTP キャッシュを利用すると、処理時間および帯域やリソースを著しく節約することが出来ます。
HTTP キャッシュは、`ETag` または `Last-Modified` ヘッダをアプリケーションのレスポンスで送信することによって実装することが出来ます。
ブラウザが HTTP の仕様に従って実装されていれば (ほとんどのブラウザがそうです)、コンテントは以前の状態と異なる場合にだけ取得されます。
正しいヘッダを作成することは手間のかかる仕事ですので、Yii は [[yii\filters\HttpCache]] というコントローラフィルタの形でショートカットを提供しています。
これを使うことはとても簡単です。
コントローラの中で `behaviors` メソッドを以下のように実装することが必要です。
## データベースを最適化する <span id="optimizing-databases"></span>
```php
public function behaviors()
{
return [
'httpCache' => [
'class' => \yii\filters\HttpCache::className(),
'only' => ['list'],
'lastModified' => function ($action, $params) {
$q = new Query();
return strtotime($q->from('users')->max('updated_timestamp'));
},
// 'etagSeed' => function ($action, $params) {
// return // egat のシードをここで生成
//}
],
];
}
```
上記のコードでは、`etagSeed` または `lastModified` のどちらかを使うことが出来ます。
両方を実装する必要はありません。
目的は、コンテントを取得してレンダリングするよりも安価な方法を使って、コンテントが修正されたかどうかを判断することです。
`lastModified` はコンテントが最後に修正されたときの UNIX タイムスタンプを返さなければなりません。
一方 `etagSeed``ETag` ヘッダの値を生成するために使われる文字列を返さなければなりません。
### データベースの最適化
データベースからのデータ取得がウェブアプリケーションのパフォーマンスの主たるボトルネックになることがよくあります。
[キャッシュ](caching.md#Query-Caching) の使用によってパフォーマンスの劣化を緩和することは出来ますが、問題を完全に解決することは出来ません。
DB クエリの実行とデータベースからのデータ取得がウェブアプリケーションのパフォーマンスの主たるボトルネックになることがよくあります。
[データキャッシュ](caching-data.md) の使用によってパフォーマンスの劣化を緩和することは出来ますが、問題を完全に解決することは出来ません。
データベースが膨大なデータを抱えている場合、キャッシュされたデータが無効化されたときに最新のデータを取得するためのコストは、データベースとクエリが適切に設計されていないと、法外なものになり得ます。
データベースのインデックスを上手に設計しましょう。
インデックスを付けると SELECT クエリを非常に速くすることが出来ます。ただし、INSERT、UPDATE、または DELTE のクエリは遅くなることがあります。
複雑なクエリに対しては、PHP コードの中からクエリを発行して DBMS にクエリを解析するように繰り返して求める代わりに、データベースビューを作成することを推奨します。
アクティブレコードを使い過ぎないでください。
アクティブレコード は OOP 流にデータをモデリングするには便利ですが、クエリ結果の各行を表すために一つまたは複数のオブジェクトを作る必要があるため、パフォーマンスを現実に低下させます。
膨大なデータを扱うアプリケーションでは、より低レベルの DAO や データベース API を使うのが良い選択でしょう。
DB クエリのパフォーマンスを向上させるための一般的なテクニックは、フィルタの対象になるテーブルカラムにインデックスを作成することです。
例えば、`username` によってユーザのレコードを検索する必要があるなら、`username` に対してインデックスを作成するべきです。
ただし、インデックスを付けると SELECT クエリを非常に速くすることが出来る代りに、INSERT、UPDATE、または DELTE のクエリが遅くなることに注意してください。
最後にもう一つ大事なことですが、SELECT クエリで LIMIT を使ってください。
こうすることで、大量のデータが返されて、PHP のために確保されたメモリを使い尽くすということがなくなります。
### asArray を使う
## プレーンな配列を使う <span id="using-arrays"></span>
読み出し専用のページにおいて、メモリと処理時間を節約する良い方法に、アクティブレコードの `asArray` メソッドを使うという方法があります。
[アクティブレコード](db-active-record.md) は非常に使い勝手のよいものですが、データベースから大量のデータを取得する必要がある場合は、プレーンな配列を使うほどには効率的ではありません。
そういう場合は、アクティブレコードを使ってデータを取得する際に `asArray()` を呼んで、取得したデータがかさばるアクティブレコードのオブジェクトではなく配列として表現されるようにすることを考慮するのが良いでしょう。
例えば、
```php
class PostController extends Controller
{
public function actionIndex()
{
$posts = Post::find()->orderBy('id DESC')->limit(100)->asArray()->all();
$posts = Post::find()->limit(100)->asArray()->all();
return $this->render('index', ['posts' => $posts]);
}
}
```
ビューにおいては、`$posts` の個々のレコードのフィールドを配列としてアクセスしなければなりません。
上記において、`$posts` は、テーブル行の配列としてデータを代入されることになります。
各行はプレーンな配列になります。
`$i` 番目の行の `title` カラムにアクセスするためには、`$posts[$i]['title']` という式を使うことが出来ます。
```php
foreach ($posts as $post) {
echo $post['title'] . "<br>";
}
```
クエリを構築するのに [DAO](db-dao.md) を使って、データをプレーンな配列に取得することも出来ます。
`asArray` が指定されていなくても配列記法を使用してフィールドにアクセスすることが出来ますが、その場合は AR オブジェクトを扱っていることに注意してください。
### Composer オートローダを最適化する
## Composer オートローダを最適化する
全体としてのパフォーマンスを改善するために、`composer dumpautoload -o` を実行して、Composer のオートローダを最適化することが出来ます。
### バックグラウンドでデータを処理する
## バックグラウンドでデータを処理する
ユーザのリクエストに素早く応答したい場合、リクエストの重い部分は、それについて即座にレスポンスを返す必要がなければ、後から処理することが出来ます。
@ -216,19 +165,19 @@ foreach ($posts as $post) {
このソリューションでたいていの場合は OK ですが、一つ大きな欠点があります。
データベースを検索するまでは処理すべきデータの有無を知ることが出来ません。
そのため、データベースをかなり頻繁に検索するか、または、処理の間に若干の遅延を生じさせるかのどちらかになります。
そのため、データベースをかなり頻繁に検索するか、または、データの作成と処理の間に若干の遅延を生じさせるかのどちらかになります。
この問題は、キューやジョブサーバ (RabbitMQ、ActiveMQ、Amazon SQS、その他いろいろ) によって解決することが出来ます。
この場合は、持続的ストレージにデータを書き込む代りに、キューやジョブサーバによって提供される API を通じてデータをキューに入れます。
処理はたいていはジョブハンドラのクラスに渡されます。
キューに入れられたジョブは、先行するジョブが全て完了した直後に実行されます。
### 何をしても効果がない場合
## 何をしても効果がない場合
何をしても効果がない場合は、何がパフォーマンスの問題を解決するかについての思い込みを排することです。
代りに、いつでも、何かを変更する前にはコードをプロファイルしてください。
次のツールが役に立つでしょう。
- [Yii のデバッグツールバーとデバッガ](tool-debugger.md)
- [Yii のデバッグツールバーとデバッガ](https://github.com/yiisoft/yii2-debug/blob/master/docs/guide-ja/README.md)
- [XDebug プロファイラ](http://xdebug.org/docs/profiler)
- [XHProf](http://www.php.net/manual/en/book.xhprof.php)
- [XHProf](http://www.php.net/manual/ja/book.xhprof.php)

2
docs/guide-ja/tutorial-start-from-scratch.md

@ -54,6 +54,6 @@ Yii の新しいプロジェクトテンプレートを作成するのに必要
これで、あなたのテンプレートを使ってプロジェクトを作成することが出来ます。
```
composer global require "fxp/composer-asset-plugin:1.0.0"
composer global require "fxp/composer-asset-plugin:~1.0.0"
composer create-project --prefer-dist --stability=dev mysoft/yii2-app-coolone new-project
```

2
docs/guide-ja/tutorial-yii-integration.md

@ -77,7 +77,7 @@ Yii は数多くの優れた機能を提供していますので、サードパ
サードパーティのシステムが Composer を使って依存を管理している場合は、単に下記のコマンドを実行すれば Yii をインストールすることが出来ます。
composer global require "fxp/composer-asset-plugin:1.0.0"
composer global require "fxp/composer-asset-plugin:~1.0.0"
composer require yiisoft/yii2
composer install

22
docs/guide-pt-BR/README.md

@ -78,10 +78,10 @@ Trabalhando com Banco de Dados
* [Query Builder (Construtor de Consulta)](db-query-builder.md)? Consultando o banco de dados usando uma camada de abstração simples
* [Active Record](db-active-record.md): Sobre o Active Record ORM, recuperando e manipulando registros e definindo relacionamentos
* [Migrations (Migrações)](db-migrations.md): Aplica controle de versão para seus banco de dados em um ambiente de desenvolvimento em equipe
* **TBD** [Sphinx](db-sphinx.md)
* **TBD** [Redis](db-redis.md)
* **TBD** [MongoDB](db-mongodb.md)
* **TBD** [ElasticSearch](db-elasticsearch.md)
* [Sphinx]((https://github.com/yiisoft/yii2-sphinx/blob/master/docs/guide-pt-BR/README.md)
* [Redis](https://github.com/yiisoft/yii2-redis/blob/master/docs/guide-pt-BR/README.md)
* [MongoDB](https://github.com/yiisoft/yii2-mongodb/blob/master/docs/guide-pt-BR/README.md)
* [ElasticSearch](https://github.com/yiisoft/yii2-elasticsearch/blob/master/docs/guide-pt-BR/README.md)
Coletando Dados de Usuários
@ -112,7 +112,7 @@ Segurança
* [Autenticação](security-authentication.md)
* [Autorização](security-authorization.md)
* [Trabalhando com Senhas](security-passwords.md)
* [Auth Clients](security-auth-clients.md)
* [Auth Clients](https://github.com/yiisoft/yii2-authclient/blob/master/docs/guide-pt-BR/README.md)
* [Melhores Práticas](security-best-practices.md)
@ -143,9 +143,9 @@ Web Services RESTful
Ferramentas de Desenvolvimento
------------------------------
* [Barra de Ferramentas de Depuração e Depurador](tool-debugger.md)
* [Gerando Código usando o Gii](tool-gii.md)
* **TBD** [Gerando Documentação da API](tool-api-doc.md)
* [Barra de Ferramentas de Depuração e Depurador](https://github.com/yiisoft/yii2-debug/blob/master/docs/guide-pt-BR/README.md)
* [Gerando Código usando o Gii](https://github.com/yiisoft/yii2-gii/blob/master/docs/guide-pt-BR/README.md)
* **TBD** [Gerando Documentação da API](https://github.com/yiisoft/yii2-apidoc)
Testes
@ -162,7 +162,7 @@ Testes
Tópicos Especiais
-----------------
* [Template Avançado de Aplicação](tutorial-advanced-app.md)
* [Template Avançado de Projetos](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide-pt-BR/README.md)
* [Construindo uma Aplicação a Partir do Zero](tutorial-start-from-scratch.md)
* [Comandos de Console](tutorial-console.md)
* [Ferramentas de Validação Embutidas](tutorial-core-validators.md)
@ -185,8 +185,8 @@ Widgets
* Menu: **TBD** link para a página de demonstração
* LinkPager: **TBD** link para a página de demonstração
* LinkSorter: **TBD** link para a página de demonstração
* [Widgets do Bootstrap](widget-bootstrap.md)
* [Widgets do JQuery UI](widget-jui.md)
* [Widgets do Bootstrap](https://github.com/yiisoft/yii2-bootstrap/blob/master/docs/guide-pt-BR/README.md)
* [Widgets do JQuery UI](https://github.com/yiisoft/yii2-jui/blob/master/docs/guide-pt-BR/README.md)
Helpers

356
docs/guide-pt-BR/caching-data.md

@ -0,0 +1,356 @@
Cache de Dados
============
O Cache de Dados é responsável por armazenar uma ou mais variáveis PHP em um arquivo temporário para
ser recuperado posteriormente.
Este também é a fundação para funcionalidades mais avançadas do cache, como [cache de consulta](#query-caching)
e [cache de página](caching-page.md).
O código a seguir é um padrão de uso típico de cache de dados, onde `$cache` refere-se a
um [Componente de Cache](#cache-components):
```php
// tentar recuperar $data do cache
$data = $cache->get($key);
if ($data === false) {
// $data não foi encontrado no cache, calculá-la do zero
// armzaenar $data no cache para que esta possa ser recuperada na próxima vez
$cache->set($key, $data);
}
// $data é acessível a partir daqui
```
## Componentes de Cache <span id="cache-components"></span>
O cache de dados se baseia nos, então chamados, *Componentes de Cache* que representam vários armazenamentos de cache,
como memória, arquivos, bancos de dados.
Componentes de Cache são normalmente registrados como [componentes de aplicação](structure-application-components.md) para que possam ser globalmente configuraveis e acessiveis. O código a seguir exibe como configurar o componente de aplicação `cache` para usar [memcached](http://memcached.org/) com dois servidores de cache:
```php
'components' => [
'cache' => [
'class' => 'yii\caching\MemCache',
'servers' => [
[
'host' => 'servidor1',
'port' => 11211,
'weight' => 100,
],
[
'host' => 'servidor2',
'port' => 11211,
'weight' => 50,
],
],
],
],
```
Você pode então, acessar o componente de cache acima usando a expressão `Yii::$app->cache`.
Já que todos os componentes de cache suportam as mesmas APIs, você pode trocar o componente de cache por outro
reconfigurando-o nas configurações da aplicação sem modificar o código que usa o cache.
Por exemplo, você pode modificar a configuração acima para usar [[yii\caching\ApcCache|APC cache]]:
```php
'components' => [
'cache' => [
'class' => 'yii\caching\ApcCache',
],
],
```
> Dica: você pode registrar múltiplos componentes de cache na aplicação. O componente chamado `cache` é usado
por padrão por muitas classes dependentes de cache (ex. [[yii\web\UrlManager]]).
### Sistemas de cache suportados <span id="supported-cache-storage"></span>
Yii suporta uma ampla gama de sistemas de cache. A seguir um sumario:
* [[yii\caching\ApcCache]]: usa a extensão do PHP [APC](http://php.net/manual/en/book.apc.php). Esta opção pode ser
considerada a mais rápida ao se implementar o cache de uma aplicação densa e centralizada (ex. um
servidor, sem balanceadores de carga dedicados, etc.).
* [[yii\caching\DbCache]]: usa uma tabela no banco de dados para armazenar os dados em cache. Para usar este cache
você deve criar uma tabela como especificada em [[yii\caching\DbCache::cacheTable]].
* [[yii\caching\DummyCache]]: serve apenas como um substituto e não faz nenhum cache na realidade
O propósito deste comoponente é simplificar o codigo que precisa checar se o cache está disponível.
Por exemplo, durante o desenvolvimento or se o servidor não suporta cache, você pode configurar um
componente de cache para usar este cache. Quando o suporte ao cache for habilitado, você pode trocar o
para o componente correspondente. Em ambos os casos, você pode usar o mesmo código
`Yii::$app->cache->get($key)` para tentar recuperar os dados do cache sem se procupar que
`Yii::$app->cache` possa ser `null`.
* [[yii\caching\FileCache]]: usa arquivos para armazenar os dados em cache. Este é particularmente indicado
para armazenar grandes quantidades de dados como o conteúdo da página.
* [[yii\caching\MemCache]]: usa o [memcache](http://php.net/manual/en/book.memcache.php) do PHP e as extensões
[memcached](http://php.net/manual/en/book.memcached.php). Esta opção pode ser considerada a mais rápida
ao se implementar o cache em aplicações distribuidas (ex. vários servidores, balanceadores de carga, etc.)
* [[yii\redis\Cache]]: implementa um componente de cache baseado em armazenamento chave-valor
[Redis](http://redis.io/) (requere redis versão 2.6.12 ou mais recente).
* [[yii\caching\WinCache]]: usa a extensão PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension)
([veja também](http://php.net/manual/en/book.wincache.php)).
* [[yii\caching\XCache]]: usa a extensão PHP [XCache](http://xcache.lighttpd.net/).
* [[yii\caching\ZendDataCache]]: usa
[Cache de Dados Zend](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm)
como o meio de cache subjacente.
> Dica: Você pode usar vários tipos de cache na mesma aplicação. Uma estratégia comum é usar caches baseados
em memória para armazenar dados pequenos mas constantemente usados (ex. dados estatísticos), e usar caches
baseados em arquivo ou banco da dados para armazenar dados que são maiores mas são menos usados
(ex. conteúdo da página).
## APIs De Cache <span id="cache-apis"></span>
Todos os componentes de caches extendem a mesma classe base [[yii\caching\Cache]] e assim suportam as seguintes APIs:
* [[yii\caching\Cache::get()|get()]]: recupera um registro no cache usando uma chave específica.
Retorna `false` caso o item não for encontrado no cache ou se o registro está expirado/invalidado.
* [[yii\caching\Cache::set()|set()]]: armazena um registro no cache identificado por uma chave.
* [[yii\caching\Cache::add()|add()]]: armazena um registro no cache identificado por uma chave se a chave não
for encontrada em cache.
* [[yii\caching\Cache::mget()|mget()]]: recupera múltiplos registros do cache com as chaves especificadas.
* [[yii\caching\Cache::mset()|mset()]]: armazena múltiplos registros no cachee. Cada item identificado por uma chave.
* [[yii\caching\Cache::madd()|madd()]]: armazena múltiplos registros no cachee. Cada item identificado por uma chave.
Se a chave já existir em cache, o registro é ignorado.
* [[yii\caching\Cache::exists()|exists()]]: retorna se a chave específica é encontrada no cache.
* [[yii\caching\Cache::delete()|delete()]]: remove um registro do cache identificado por uma chave.
* [[yii\caching\Cache::flush()|flush()]]: remove todos os registros do cache.
> Note: Não armazene o valor boleano `false` diretamente, porque o método [[yii\caching\Cache::get()|get()]] retorna `false`para indicar que o registro não foi encontrado em cache. Você pode armazena `false` em um array e armazenar este em cache para evitar este problema.
Alguns tipos de cache como MemCache, APC, suportam recuperar em lote múltiplos registros em cache, o que poder reduzir
o custo de processamento envolvido ao recuperar informações em cache. The APIs [[yii\caching\Cache::mget()|mget()]]
e [[yii\caching\Cache::madd()|madd()]] são equipadas para explorar esta funcionalidade. Em caso do cache em questão não suportar esta funcionalidade, ele será simulado.
Como [[yii\caching\Cache]] implementa `ArrayAccess`, um componente de cache pode ser usado como um array. A seguir alguns exemplos:
```php
$cache['var1'] = $valor1; // equivalente a: $cache->set('var1', $valor1);
$valor2 = $cache['var2']; // equivalente a: $valor2 = $cache->get('var2');
```
### Chaves de Cache <span id="cache-keys"></span>
Cada registro armazenado no cache é identificado por uma chave única. Quando você armazena um registro em cache,
você deve especificar uma chave para ele. Mais tarde, quando você quiser recuperar o registro do cache, você deve
fornecer a chave correspondente.
Você pode usar uma string ou um valor arbitrario como uma chave do cache. Quando a chave não for uma string, ela será
automaticamente serializada em uma string.
Uma estratégia comum ao definir uma chave de cache é incluir todos os fatores determinantes na forma de um array.
Por exemplo, [[yii\db\Schema]] usa a seguinte chave para armazenar a informação de um esquema de uma tabela do banco
de dados.
```php
[
__CLASS__, // nome da classe do esquema
$this->db->dsn, // nome da fonte de dados da conexão BD
$this->db->username, // usuario da conexão BD
$name, // nome da tabela
];
```
Como você pode ver, a chave inclui toda a informação necessária para especificar unicamente uma tabela do banco.
Quando o cache de diferentes aplicações é armazenado no mesmo lugar, é aconselhavel especificar, para cada
aplicação, um prefíxo único a chave do cache para evitar conflitos entre elas. Isto pode ser feito ao configurar
a propriedade [[yii\caching\Cache::keyPrefix]]. Por exemplo, na configuração da aplicação você pode escrever o seguinte código:
```php
'components' => [
'cache' => [
'class' => 'yii\caching\ApcCache',
'keyPrefix' => 'minhaapp', // um prefíxo de chave único
],
],
```
Para assegurar interoperabilidade, apenas caracteres numéricos devem ser usados.
To ensure interoperability, only alphanumeric characters should be used.
### Expiração de Cache <span id="cache-expiration"></span>
Um registro armazenado em cache não será apagado a menos que seja removido por alguma política seja aplicada
(ex. espaço determinado para o cache esteja cheio e os registros mais antigos sejam removidos). Para alterar
estes comportamente, você pode fornecer um parametro de expiração ao chamar [[yii\caching\Cache::set()|set()]]
para armazenar um registro. O parametro indica por quantos segundos um registro pode permanecer válidado no cache.
Quando você chamar [[yii\caching\Cache::get()|get()]] para recuperar um registro, se o tempo de expiração houver passado, o método irá retornar `false`, indicando que o registro não foi encontrado no cache. Por exemplo,
```php
// Manter o registro em cache por até 45 segundos
$cache->set($chave, $registro, 45);
sleep(50);
$data = $cache->get($chave);
if ($registro === false) {
// $registro está expirado ou não foi encontrado no sistema
}
```
### Dependências de Cache <span id="cache-dependencies"></span>
Além da definição de expiração, um registro em cache pode também ser invalidado por mudanças nas, então chamadas,
*dependências de cache*. Por exemplo, [[yii\caching\FileDependency]] representa a dependência na data de modificação
de um arquivo.
Quando esta dependência muda, significa que o arquivo correspondente foi mudado. Como um resultado, qualquer
arquivo com data ultrapassada encontrado no cache deve ser invalidado e a chamada de [[yii\caching\Cache::get()|get()]]
retornará `false`.
Dependências de Cache são representadas como objetos de classes dependentes de [[yii\caching\Dependency]]. Quando você chamar [[yii\caching\Cache::set()|set()]] para armazenar um registro em cache, você pode passar um objeto de dependência. Por exemplo,
```php
// Criar uma dependência sobre a data de modificação do arquivo exemplo.txt.
$dependencia = new \yii\caching\FileDependency(['fileName' => 'exemplo.txt']);
// O registro irá expirar em 30 segundos.
// Ele também pode ser invalidado antes, caso o exemplo.txt seja modificado.
$cache->set($key, $data, 30, $dependency);
// O cache irá verificar se o registro expirou.
// E também irá vefiricar se a dependência associada foi alterada.
// Ele retornará false se qualquer uma dessas condições seja atingida.
$data = $cache->get($key);
```
Abaixo um sumário das dependências de cache disponíveis:
- [[yii\caching\ChainedDependency]]: a dependência muda caso alguma das dependencias na cadeia for alterada.
- [[yii\caching\DbDependency]]: a dependência muda caso o resultado da consulta especificada pela instrução SQL seja
alterado.
- [[yii\caching\ExpressionDependency]]: a dependencia muda se o resultado da expressão PHP especificada for alterado.
- [[yii\caching\FileDependency]]: A dependencia muda se a data da última alteração do arquivo for alterada.
- [[yii\caching\TagDependency]]: associa um registro em cache com uma ou múltiplas tags. Você pode invalidar os
registros em cache com a tag especificada ao chamar [[yii\caching\TagDependency::invalidate()]].
## Cache de Consulta <span id="query-caching"></span>
Cache de consulta é uma funcionalidade especial de cache construida com o cache de dados. Ela é fornecida para armazenar em cache consultas ao banco de dados.
O cache de consulta requere uma [[yii\db\Connection|DB connection]] e um [componente de aplicação](#cache-components) de `cache` válido.
A seguir um usu básico de cache de consulta, assumindo que `$bd` é uma instância de [[yii\db\Connection]]:
```php
$resultado = $bd->cache(function ($bd) {
// O resultado da consulta SQL será entregue pelo cache
// se o cache de consulta estiver sido habilitado e o resultado da consulta for encontrado em cache
return $bd->createCommand('SELECT * FROM clientes WHERE id=1')->queryOne();
});
```
Cache de consulta pode ser usado pelo [DAO](db-dao.md) da mesma forma que um [ActiveRecord](db-active-record.md):
```php
$resultado = Cliente::getDb()->cache(function ($bd) {
return Cliente::find()->where(['id' => 1])->one();
});
```
> Info: Alguns SGBDs (ex. [MySQL](http://dev.mysql.com/doc/refman/5.1/en/query-cache.html))
também suportam o cache de consulta no servidor. Você pode escolher usálo ao invés do mecanismo de cache
de consulta.
O cache de consulta descrito acima tem a vantagem de que você pode especificar dependencias de cache flexíveis
e assim sendo potencialmente mais eficiente.
### Configurações <span id="query-caching-configs"></span>
Cache de consulta tem três opções configuraveis globalmente através de [[yii\db\Connection]]:
* [[yii\db\Connection::enableQueryCache|enableQueryCache]]: Configura se o cache de consulta está habilitado.
O padrão é true. Note que para ter efetivamente o cache de consulta habilitado, você também deve ter um cache válido como especificado por [[yii\db\Connection::queryCache|queryCache]].
* [[yii\db\Connection::queryCacheDuration|queryCacheDuration]]: representa o número de segundos que o resultado de uma
consulta pode se manter válido em cache. Você pode usar 0 para indicar que o resultado da consulta deve permancer no
cache indefinidamente. Este é o valor padrão usado quando [[yii\db\Connection::cache()]] é chamado sem nenhuma
especificação de duração.
* [[yii\db\Connection::queryCache|queryCache]]: representa a ID do componente de aplicação de cache.
Seu padrão é `'cache'`. Cache de consulta é habilitado apenas se houver um componente de aplicacão de cache válido.
### Usando o Cache de Consulta <span id="query-caching-usages"></span>
Você pode usar [[yii\db\Connection::cache()]] se tiver múltiplas consultas SQL que precisam ser armazenadas no
cache de consulta. Use da seguinte maneira,
```php
$duracao = 60; // armazenar os resultados em cache por 60 segundos
$dependencia = ...; // alguma dependencia opcional
$result = $db->cache(function ($db) {
// ... executar consultas SQL aqui ...
return $result;
}, $duracao, $dependencia);
```
Qualquer consulta SQL na função anonima irá ser armazenada em cache pela duração especificada com a dependência informada. Se o resultado da consulta for encontrado em cache e for válido, a consulta não será necessária e o
resultado será entregue pelo cache. Se você não especificar o parametro `$duracao`, o valor de
[[yii\db\Connection::queryCacheDuration|queryCacheDuration]] será usado.
Ocasionalmente em `cache()`, você pode precisar desabilitar o cache de consulta para algumas consultas em particular. Você pode usar [[yii\db\Connection::noCache()]] neste caso.
```php
$result = $db->cache(function ($db) {
// consultas SQL que usarão o cache de consulta
$db->noCache(function ($db) {
// consultas SQL que não usarão o cache de consulta
});
// ...
return $result;
});
```
Se você apenas deseja usar o cache de consulta para apenas uma consulta, você pode chamar [[yii\db\Command::cache()]]
ao construir o comando. Por exemplo,
```php
// usar cache de consulta and definir duração do cache para 60 segundos
$customer = $db->createCommand('SELECT * FROM customer WHERE id=1')->cache(60)->queryOne();
```
Você pode também usar [[yii\db\Command::noCache()]] para desabilitar o cache de consulta para um único comando, Por exemplo,
```php
$result = $db->cache(function ($db) {
// consultas SQL que usam o cache de consulta
// não usar cache de consulta para este comando
$customer = $db->createCommand('SELECT * FROM customer WHERE id=1')->noCache()->queryOne();
// ...
return $result;
});
```
### Limitações <span id="query-caching-limitations"></span>
O cache de consulta não funciona com resultados de consulta que contêm <i>manipuladores de recursos</i>(resource handlers).
Por exemplo, ao usar o tipo de coluna `BLOB` em alguns SGBDs, o resultado da consulta irá retornar um <i>manipulador de recurso</i>(resource handler) para o registro na coluna.
Alguns armazenamentos em cache têm limitações de tamanho. Por exemplo, memcache limita o uso máximo de espaço de 1MB para cada registro. Então, se o tamanho do resultado de uma consulta exceder este limite, o cache irá falhar.

166
docs/guide-pt-BR/caching-fragment.md

@ -0,0 +1,166 @@
Cache de Fragmentos
================
Cache de fragmentos é responsável por armazenar em cache um fragmento de uma página web. Por exemplo, se uma
página exibe o sumario de vendas anuais em uma tabela, você pode armazenar esta tabela em cache para eliminar
o tempo necessário para gerar esta tabela para em cada requisição. O Cache de Fragmentos é construido a partir
do [cache de dados](caching-data.md).
Para usar o cache de fragmentos, use o seguinte modelo em uma [view](structure-views.md):
```php
if ($this->beginCache($id)) {
// ... gere o conteúdo aqui ...
$this->endCache();
}
```
Ou seja, encapsule a lógica de geração do conteudo entre as chamadas [[yii\base\View::beginCache()|beginCache()]]
e [[yii\base\View::endCache()|endCache()]]. Se o conteúdo for encontrado em cache, [[yii\base\View::beginCache()|beginCache()]] irá renderizar o conteúdo em cache e retornará falso, e assim não executará a lógica de geração de conteúdo.
Caso contrário, o conteúdo será gerado, e quando [[yii\base\View::endCache()|endCache()]] for chamado, o conteúdo gerado será capturado e armazenado no cache.
Assim como [cache de dados](caching-data.md), uma `$id` única é necessária para identificar um conteúdo no cache.
## Opções do Cache <span id="caching-options"></span>
Você poderá especificar opções adicionais sobre o cache de fragmentos passando um array de opções como o segundo parâmetro do método [[yii\base\View::beginCache()|beginCache()]]. Por trás dos panos, este array de opções será usado para configurar um widget [[yii\widgets\FragmentCache]] que implementa, por sua vez, a funcionalidade de cache de fragmentos.
### Duração <span id="duration"></span>
Esta talvez a opção mais frequentemente usada com cache de fragmentos seja a
[[yii\widgets\FragmentCache::duration|duration]].
Ela especifica por quantos segundos o conteúdo pode permanecer válido no cache. O código a seguir armazena em cache o fragmento do conteúdo por até uma hora:
```php
if ($this->beginCache($id, ['duration' => 3600])) {
// ... gerar o conteúdo aqui ...
$this->endCache();
}
```
Se a opção não for definida, o padrão definido é 60, que significa que o conteúdo em cache expirará em 60 segundosnds.
### Dependências <span id="dependencies"></span>
Assim como [cache de dados](caching-data.md#cache-dependencies), o fragmento de conteúdo sendo armazenado em cache pode ter dependencias.
Por exemplo, o conteúdo de um post sendo exibido depende de ele ter sido ou não modificado.
Para especificar uma dependencia, defina a opção [[yii\widgets\FragmentCache::dependency|dependency]], que pode
ser um objeto [[yii\caching\Dependency]] ou um array de configuração para criar um objeto de dependência.
O código a seguir especifica que o conteudo do fragmento depende do valor da coluna `atualizado_em`:
```php
$dependency = [
'class' => 'yii\caching\DbDependency',
'sql' => 'SELECT MAX(atualizado_em) FROM post',
];
if ($this->beginCache($id, ['dependency' => $dependency])) {
// ... gere o conteúdo aqui ...
$this->endCache();
}
```
### Variações <span id="variations"></span>
O Conteúdo armazenado em cache pode variar de acordo com alguns parâmetros. Por exemplo, para uma aplicação web
suportando múltiplas linguas, a mesma porção de código de uma view pode gerar conteúdo em diferentes línguagem.
Desta forma, você pode desejar que o código em cache exiba um conteúdo diferente para a línguagem exibida na requisição.
Para especificar variações de cache, defina a opção [[yii\widgets\FragmentCache::variations|variations]],
que pode ser um array de valores escalares, cada um representando um fator de variação particular.
Por exemplo, para fazer o conteúdo em cache variar em função da linguagem, você pode usar o seguinte código:
```php
if ($this->beginCache($id, ['variations' => [Yii::$app->language]])) {
// ... gerar o conteúdo aqui ...
$this->endCache();
}
```
### <i>Cache Alternante</i>(Toggling Caching) <span id="toggling-caching"></span>
Em alguns casos, você pode precisar habilitar o cache de fragmentos somente quando certas condições se aplicam.
Por exemplo, para uma página exibindo um formulário, e você deseja armazenar o formulário em cache apenas na
primeira requisição (via requisição GET). Qualquer exibição subsequente (via requisição POST) ao formulário não
deve ser armazenada em cache porque o formulário pode conter os dados submetidos pelo usuário. Para assim fazê-lo,
você pode definir a opção [[yii\widgets\FragmentCache::enabled|enabled]], da seguinte maneira:
```php
if ($this->beginCache($id, ['enabled' => Yii::$app->request->isGet])) {
// ... gerar conteudo aqui ...
$this->endCache();
}
```
## <i>Cache Aninhado</i>(Nested Caching) <span id="nested-caching"></span>
Cache de fragmentos pode ser aninhado. Isto é, um fragmento em cache pode estar contido em outro fragmento que também está em cache. Por exemplo, os comentários estão sendo armazenados em um cache de fragmento inserido em conjunto com o conteudo do post em um outro cache de fragmento. O código a seguir exibe como dois caches de fragmento podem ser aninhados.
```php
if ($this->beginCache($id1)) {
// ...lógica de geração de conteúdo...
if ($this->beginCache($id2, $options2)) {
// ...lógica de geração de conteúdo...
$this->endCache();
}
// ...lógica de geração de conteúdo...
$this->endCache();
}
```
Diferentes opções de cache podem ser definidas para os caches aninhados. Por exemplo, o cache interior e o cache
exterior podem ter tempos diferentes de expiração. Mesmo quando um registro no cache exterior é invalidado, o cache
interior ainda pode permanecer válido. Entretanto, o inverso não pode acontecer. Se o cache exterior é identificado
como validado, ele continuará a servir a mesma copia em cache mesmo após o conteudo no cache interior ter sido
invalidado. Desta forma, você deve ser cuidadoso ao definir durações ou dependencias para os caches aninhados,
já que os fragmentos interiores ultrapassados podem ser mantidos no fragmento externo.
## Conteúdo Dinâmico <span id="dynamic-content"></span>
Ao usar o cache de fragmentos, vocế pode encontrar-se na situação em que um grande fragmento de conteúdo é
relativamente estático exceto em alguns poucos lugares. Por exemplo, um cabeçalho de uma página pode exibir
a barra do menu principal junto ao nome do usuário logado. Outro problema é que o conteudo sendo armazenado em cache
pode conter código PHP que deve ser executado para cada requisição (ex. o código para registrar um <i>pacote de recursos estáticos</i>(asset bundles)). Ambos os problemas podem ser resolvidos com a funcionalidade, então chamada de *Conteúdos Dinâmicos*.
Um conteúdo dinâmico compreende um fragmento de uma saida que não deveria ser armazenada em cache mesmo que esteja encapsulada em um cache de fragmento. Para fazer o conteúdo dinâmico indefinidamente, este deve ser gerado pela execução de
algum código PHP em cada requisição, mesmo que o conteúdo encapsulado esteja sendo servido do cache.
Vocế pode chamar [[yii\base\View::renderDynamic()]] dentro de um cache de fragmento para inserir conteúdo dinâmico no local desejado, como o seguinte,
```php
if ($this->beginCache($id1)) {
// ...lógica de geração de conteúdo...
echo $this->renderDynamic('return Yii::$app->user->identity->name;');
// ...lógica de geração de conteúdo...
$this->endCache();
}
```
O método [[yii\base\View::renderDynamic()|renderDynamic()]] recebe uma porção de código PHP como parâmetro.
O valor retornado pelo código PHP é tratado como conteúdo dinâmico. O mesmo código PHP será executado em
cada requisição, não importando se este esteja encapsulado em um fragmento em cache ou não.

134
docs/guide-pt-BR/caching-http.md

@ -0,0 +1,134 @@
Cache HTTP
============
Além do cache no servidor que nós descrevemos nas seções anteriores, aplicações web pode também aproveitar-se
de cache no cliente para economizar o tempo para gerar e transmitir o mesmo conteúdo de uma página.
Para usar o cache no cliente, vocế poderá configurar [[yii\filters\HttpCache] como um filtro para actions de um
controller ao qual o resultado de sua renderização possa ser armazenado em cache no navegador do cliente. [[yii\filters\HttpCache|HttpCache]] funciona apenas para requisições `GET` e `HEAD`. Ele pode manipular três tipos de cache relacionados a cabeçalhos HTTP para estas requisições:
* [[yii\filters\HttpCache::lastModified|Last-Modified]]
* [[yii\filters\HttpCache::etagSeed|Etag]]
* [[yii\filters\HttpCache::cacheControlHeader|Cache-Control]]
## Cabeçalho de `Last-modified` <span id="last-modified"></span>
O cabeçalho `Last-modified` usa uma data(timestamp) para indicar se a página foi modificada desde que o cliente a armazenou em cache.
Você pode configurar a propriedade [[yii\filters\HttpCache::lastModified]] para permitir enviar o cabeçalho de `Last-modified`. A propriedade deve ser um <i>callable</i> PHP retornando uma data(timestamp) UNIX sobre o tempo de modificação. A declaração do <i>callable</i> PHP deve ser a seguinte,
```php
/**
* @param Action $action O Objeto da action que está sendo manipulada no momento
* @param array $params o valor da propriedade "params"
* @return integer uma data(timestamp) UNIX timestamp representando o tempo da
* última modificação na página
*/
function ($action, $params)
```
A seguir um exemplo que faz o uso do cabeçalho `Last-modified`:
```php
public function behaviors()
{
return [
[
'class' => 'yii\filters\HttpCache',
'only' => ['index'],
'lastModified' => function ($action, $params) {
$q = new \yii\db\Query();
return $q->from('post')->max('updated_at');
},
],
];
}
```
O código acima afirma que o cache HTTP deve ser habilitado apenas para a action `index`. Este deve
gerar um cabeçalho HTTP `last-modified` baseado na última data de alteração dos posts. Quando um
navegador visitar a página `index` pela primeira vez, a página irá ser gerada no servidor e enviada para
o navegador; Se o navegador visitar a mesma página novamente e não houver modificação dos posts durante este
período, o servidor não irá re-gerar a página, e o navegador irá usar a versão em cache no cliente.
Como um resultado a renderização do conteúdo na página não será executada no servidor.
## Cabeçalho `ETag` <span id="etag"></span>
O cabeçalho <i>"Entity Tag"</i> (ou `ETag` abreviado) usa um hash para representar o conteúdo de uma página.
Se a página for alterada, o hash irá mudar também. Ao comparar o hash mantido no cliente com o hash gerado no
servidor, o cache pode determinar se a página foi alterada e se deve ser re-transmitida.
Você pode configurar a propriedade [[yii\filters\HttpCache::etagSeed]] para habilitar o envio do cabeçalho `ETag`.
A propriedade deve ser um <i>callable</i> PHP retornando a <i>semente(seed)</i> para a geração do hash do Etag. A declaração do <i>callable</i> PHP deve ser como a seguinte,
```php
/**
* @param Action $action o objeto da action que está sendo manipulada no momento
* @param array $params o valor da propriedade "params"
* @return string uma string usada como a semente(seed) para gerar um hash ETag
*/
function ($action, $params)
```
A Seguir um exemplo que faz o uso do cabeçalho `ETag`:
```php
public function behaviors()
{
return [
[
'class' => 'yii\filters\HttpCache',
'only' => ['view'],
'etagSeed' => function ($action, $params) {
$post = $this->findModel(\Yii::$app->request->get('id'));
return serialize([$post->title, $post->content]);
},
],
];
}
```
O código acima afirma que o cache de HTTP deve ser habilitado apenas para a action `view`. Este deve
gerar um cabeçalho HTTP `ETag` baseado no titulo e conteúdo do post requisitado. Quando um navegador visitar
a página `view` pela primeira vez, a página será gerada no servidor e enviada para ele; Se o navegador visitar
a mesma página novamente e não houver alteração para o título e o conteúdo do post, o servidor não irá ré-gerar
a página, e o navegador irá usar a versão que estiver no cache do cliente. Como um resultado a renderização do
conteúdo na página não será executada no servidor.
ETags permite estratégias mais complexas e/ou mais precisas do que o uso do cabeçalho de `Last-modified`.
Por exemplo, um ETag pode ser invalidado se o site tiver sido alterado para um novo tema.
Gerações muito complexas de ETags podem contrariar o propósito de se usar `HttpCache` e introduzir despesas desnecessárias ao processamento, já que eles precisam ser re-avaliados a cada requisição.
Tente encontrar uma expressão simples que invalida o cache se o conteúdo da página for modificado.
> Observação: Em complacência com a [RFC 7232](http://tools.ietf.org/html/rfc7232#section-2.4),
`HttpCache` irá enviar os cabeçalhos `ETag` e `Last-Modified` se ambos forem assim configurados.
E se o cliente envia ambos o cabeçalhos `If-None-Match` e `If-Modified-Since`, apenas o primeiro será
respeitado.
## Cabeçalho `Cache-Control` <span id="cache-control"></span>
O cabeçalho `Cache-Control` especifica politicas de cache gerais para as páginas. Você pode enviá-lo configurando a propriedade [[yii\filters\HttpCache::cacheControlHeader]] com o valor do cabeçalho. Por padrão, o seguinte cabeçalho será enviado:
```
Cache-Control: public, max-age=3600
```
## Limitador de Cache na Sessão <span id="session-cache-limiter"></span>
Quando uma página usa sessão, o PHP irá automaticamente enviar alguns cabeçalhos HTTP relacionados ao cache
como especificado na configuração do PHP INI `session.cache_limiter`. Estes cabeçalhos podem inteferirir ou
desabilitar o cache que você deseja do `HttpCache`. Para previnir-se deste problema, por padrão `HttpCache`
irá desabilitar o envio destes cabeçalhos automaticamente. Se você quiser modificar estes comportamente, deve
configurara a propriedade [[yii\filters\HttpCache::sessionCacheLimiter]]. A propriedade pode receber um valor em uma string, incluindo `public`, `private`, `private_no_expire`, e `nocache`. Por favor referir-se ao manual do
PHP sobre [session_cache_limiter()](http://www.php.net/manual/en/function.session-cache-limiter.php)
para explicações sobre estes valores.
## Implicações para SEO <span id="seo-implications"></span>
Os bots do motor de buscas tendem a respeitar cabeçalhos de cache. Ja que alguns rastreadores têm um limite sobre a quantidade de páginas por dominio que eles processam em um certo espaço de tempo, introduzir cabeçalhos de cache podem
ajudar na indexação do seu site já que eles reduzem o número de páginas que precisam ser processadas.

17
docs/guide-pt-BR/caching-overview.md

@ -0,0 +1,17 @@
Cache
=======
Cache é uma maneira barata e eficiente de melhorar o desempenho de uma aplicação web. Ao gravar dados relativamente
estáticos em cache e servindo os do cache quando requisitados, a aplicação economiza o tempo que seria necessário
para renderizar as informações do zero toda vez.
Cache pode ocorrer em diferentes níveis e locais em uma aplicação web. No servidor, no baixo nível,
cache pode ser usado para armazenar dados básicos, como a informação de uma lista de artigos mais recentes trazidos
do banco de dados; e no alto nível, cache pode ser usado para armazenar fragmentos ou páginas web inteiras,como o
resultado da renderização dos artigos mais recentes. No cliente, cache HTTP pode ser usado para manter o conteúdo da última página acessada no cache do navegador.
Yii suporta todos os os três métodos de cache:
* [Cache de Dados](caching-data.md)
* [Cache de Fragmento](caching-fragment.md)
* [Cache de Página](caching-page.md)
* [Cache de HTTP](caching-http.md)

38
docs/guide-pt-BR/caching-page.md

@ -0,0 +1,38 @@
Cache de Página
============
O Cache de página é responsável por armazenar em cache o conteúdo de uma página inteira no servidor. Mais tarde,
quando a mesma página é requisitada novamente, seu conteúdo será servido do cache em vez de ela ser gerada novamente
do zero.
O Cache de página é implementado pela classe [[yii\filters\PageCache]], um [filtro de actions](structure-filters.md).
Esta pode ser usada da seguinte maneira em uma classe de controller:
```php
public function behaviors()
{
return [
[
'class' => 'yii\filters\PageCache',
'only' => ['index'],
'duration' => 60,
'variations' => [
\Yii::$app->language,
],
'dependency' => [
'class' => 'yii\caching\DbDependency',
'sql' => 'SELECT COUNT(*) FROM post',
],
],
];
}
```
O código acima afirma que o cache de página deve ser usado apenas para a action `index`; o conteúdo da página deve
ser armazenado em cache por, no máximo, 60 segundos e deve variar de acordo com a linguagem atual da aplicação;
e esta página em cache deve ser invalidada se o número total de posts for alterado.
Como vocế pode ver, o cache de página é bastante similar ao [cache de fragmentos](caching-fragment.md). Ambos suportam opções como `duration`, `dependencies`, `variations`, and `enabled`. Sua principal diferença é que o cache de página implementado como um [filtro de actions](structure-filters.md) enquanto que o cache de fragmentos é um [widget](structure-widgets.md).
Você pode usar o [cache de fragmentos](caching-fragment.md) ou [conteúdo dinâmico](caching-fragment.md#dynamic-content)
em conjunto com o cache de página.

123
docs/guide-pt-BR/concept-aliases.md

@ -0,0 +1,123 @@
Aliases(Apelidos)
=======
Aliases são usados para representar caminhos de arquivos ou URLs de forma que você não precise acoplar o código usando caminhos absolutos ou URLs em seu projeto. Um alias deve começar com o caractere `@` para se diferenciar de um caminho de arquivo normal ou URL. Yii já possui vários aliases predefinidos disponíveis.
Por exemplo, o alias `@yii` representa o local em que o framework Yii foi instalado; `@web` representa a URL base para a aplicação que está sendo executada no momento.
Definindo Aliases <span id="defining-aliases"></span>
----------------
Você pode definir um alias para um caminho de arquivo ou URL chamando [[Yii::setAlias()]]:
```php
// um alias de um caminho de arquivo
Yii::setAlias('@foo', '/caminho/para/foo');
// um alias de uma URL
Yii::setAlias('@bar', 'http://www.exemplo.com.br');
```
> Observação: O caminho do arquivo ou URL sendo <i>apelidado</i>(aliased) *não* necessariamente refere-se a um arquivo ou a recursos existentes.
Dado um alias definido, você pode derivar um novo alias (sem a necessidade de chamar [[Yii::setAlias()]]) apenas acrescentando uma barra `/` seguido de um ou mais segmentos de caminhos de arquivos. Os aliases definidos através de [[Yii::setAlias()]] tornam-se o *alias raiz*(root alias), enquanto que aliases derivados dele, tornam-se *aliases derivados*. Por exemplo, `@foo` é um <i>alias raiz</i>(root alias), enquanto `@foo/bar/arquivo.php` é um alias derivado.
Você pode definir um alias usando outro alias (tanto raiz quanto derivado):
```php
Yii::setAlias('@foobar', '@foo/bar');
```
Aliases raiz são normalmente definidos durante o estágio de [inicialização](runtime-bootstrapping.md).
Por exemplo, você pode chamar [[Yii::setAlias()]] no [script de entrada](structure-entry-scripts.md).
Por conveniência, as [Aplicações](structure-applications.md) difinem uma propriedade `aliases` que você
pode configurar na [configuração](concept-configurations.md) da aplicação:
```php
return [
// ...
'aliases' => [
'@foo' => '/caminho/para/foo',
'@bar' => 'http://www.exemplo.com.br',
],
];
```
Resolvendo Aliases <span id="resolving-aliases"></span>
-----------------
Você pode chamar [[Yii::getAlias()]] em um alias raiz para resolver o caminho de arquivo ou URL que ele representa.
O mesmo método pode tambem, resolver um alias derivado em seu caminho de arquivo ou URL correspondente.
```php
echo Yii::getAlias('@foo'); // exibe: /caminho/para/foo
echo Yii::getAlias('@bar'); // exibe: http://www.example.com
echo Yii::getAlias('@foo/bar/arquivo.php'); // exibe: /caminho/para/foo/bar/arquivo.php
```
O caminho/URL representado por um alias derivado é determinado substituindo a parte do alias raiz com o seu caminho/URL correspondente.
> Observação: O método [[Yii::getAlias()]] não checa se o caminho/URL resultante refere-se a um arquivo ou recursos existentes.
Um alias raiz pode também conter caracteres de barra `/`. O método [[Yii::getAlias()]] é inteligente o suficiente
para descobrir que parte de um alias é um alias raiz e assim determina o caminho de arquivo ou URL correspondente:
```php
Yii::setAlias('@foo', '/caminho/para/foo');
Yii::setAlias('@foo/bar', '/caminho2/bar');
Yii::getAlias('@foo/test/arquivo.php'); // exibe: /caminho/para/foo/test/arquivo.php
Yii::getAlias('@foo/bar/arquivo.php'); // exibe: /caminho2/bar/arquivo.php
```
Se `@foo/bar` não estivesse definido como um alias raiz, a última chamada exibiria `/caminho/para/foo/bar/arquivo.php`.
Usando Aliases <span id="using-aliases"></span>
-------------
Aliases são reconhecidos em muitos lugares no Yii sem a necessidade de chamar [[Yii::getAlias()]] para convertê-los em caminhos e URLs. Por exemplo, [[yii\caching\FileCache::cachePath]] pode aceitar tanto um caminho de arquivo quanto um alias representando o caminho do arquivo, graças ao prefíxo `@` que nos permite diferenciar um caminho de arquivo de um alias.
```php
use yii\caching\FileCache;
$cache = new FileCache([
'cachePath' => '@runtime/cache',
]);
```
Por favor preste atenção a documentação da API para saber se o parâmetro de uma propriedade ou método suporta aliases.
Aliases Predefinidos <span id="predefined-aliases"></span>
------------------
Yii já predefine uma gama de aliases para referenciar facilmente caminhos de arquivos e URLs comumente usados:
- `@yii`, o diretório onde o arquivo `BaseYii.php` está localizado (também chamado de diretório do framework).
- `@app`, o caminho base [[yii\base\Application::basePath|base path]] da aplicação sendo executada no momento.
- `@runtime`, o caminho em <i>tempo de execução</i>(runtime) [[yii\base\Application::runtimePath|runtime path]] da aplicação sendo
executada no momento.
- `@webroot`, o diretório webroot da aplicação sendo executada no momento. Este é determinado baseado no diretório
contendo o [script de entrada](structure-entry-scripts.md).
- `@web`, a URL base da aplicacão sendo executada no momento. Esta tem o mesmo valor de [[yii\web\Request::baseUrl]].
- `@vendor`, o caminho da pasta vendor [[yii\base\Application::vendorPath|Composer vendor directory]].
Seu padrão é `@app/vendor`.
- `@bower`, o caminho raiz que contém os [pacotes bower](http://bower.io/). Seu padrão é `@vendor/bower`.
- `@npm`, o caminho raiz que contém [pacotes npm](https://www.npmjs.org/). Seu padrão é `@vendor/npm`.
O alias `@yii` é definido quando você inclui o arquivo `Yii.php` em seu [script de entrada](structure-entry-scripts.md).
O resto dos aliases são definidos no construtor da aplicação ao aplicar a [configuração](concept-configurations.md) da aplicação.
Aliases para Extensões <span id="extension-aliases"></span>
-----------------
Um alias é automaticamente definido para cada [extensão](structure-extensions.md) que for instalada através do Composer.
Cada alias é nomeado a partir do namespace raiz da extensão como declarada em seu arquivo `composer.json`, e cada alias representa o diretório raiz de seu pacote. Por exemplo, se você instalar a extensão `yiisoft/yii2-jui`,
você terá automaticamente o alias `@yii/jui` definido durante o estágio de [inicialização](runtime-bootstrapping.md), equivalente a:
```php
Yii::setAlias('@yii/jui', 'VendorPath/yiisoft/yii2-jui');
```

304
docs/guide-pt-BR/concept-behaviors.md

@ -0,0 +1,304 @@
Behaviors (Comportamentos)
=========
Behaviors são instâncias de [[yii\base\Behavior]], ou de uma classe-filha, também conhecido como [mixins](http://en.wikipedia.org/wiki/Mixin), permite melhorar a funcionalidade de uma classe [[yii\base\Component|componente]] existente sem a necessidade de mudar a herança dela.
Anexar um behavior a um componente "introduz" os métodos e propriedades do behavior dentro do componente, tornando esses métodos e propriedades acessíveis como se estes fossem definidos na própria classe do componente. Além disso, um behavior pode responder a um [evento](concept-events.md) disparado pelo componente, o que permite a customização do código normal.
Definindo Behaviors <span id="defining-behaviors"></span>
------------------
Para definir um behavior , Crie uma classe extendendo de [[yii\base\Behavior]], ou de uma classe-filha. Por exemplo:
```php
namespace app\components;
use yii\base\Behavior;
class MyBehavior extends Behavior
{
public $prop1;
private $_prop2;
public function getProp2()
{
return $this->_prop2;
}
public function setProp2($value)
{
$this->_prop2 = $value;
}
public function foo()
{
// ...
}
}
```
O código acima define a classe behavior `app\components\MyBehavior`, com duas propriedades --`prop1` e `prop2`-- e um método `foo()`. Note que a propriedade `prop2`
É definida através do método getter `getProp2()` e setter `setProp2()`. Isto é possível porque [[yii\base\Behavior]] extende de [[yii\base\Object]] e portanto suporta definição de propriedades através de getters e setters [properties](concept-properties.md).
Como essa classe é um behavior , quando ela está anexada a um componente, então este componente terá as propriedades `prop1` e `prop2` e o método `foo()`.
> Dica: Em um behavior , você pode acessar o componente que o behavior está anexado através da propriedade [[yii\base\Behavior::owner]].
Manuseando Eventos de Componente
------------------
Se um behavior precisa responder a eventos disparados pelo componente ao qual está ligado, este deve sobrescrever o método [[yii\base\Behavior::events()]]. Por exemplo:
```php
namespace app\components;
use yii\db\ActiveRecord;
use yii\base\Behavior;
class MyBehavior extends Behavior
{
// ...
public function events()
{
return [
ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate',
];
}
public function beforeValidate($event)
{
// ...
}
}
```
O método [[yii\base\Behavior::events()|events()]] deve retornar uma lista de eventos e seus manipuladores correspondentes.
O exemplo acima declara que o evento [[yii\db\ActiveRecord::EVENT_BEFORE_VALIDATE|EVENT_BEFORE_VALIDATE]] existe e define seu manipulador, `beforeValidate()`. Ao especificar um manipulador de evento, você pode utilizar um dos seguintes formatos:
* uma string que refere-se ao nome do método da classe behavior , como o exemplo acima
* um array com o nome do objeto ou classe, e um nome de método como string (sem parênteses), por exemplo, `[$object, 'methodName']`;
* uma função anônima
A assinatura de um manipulador de eventos deve ser como o exemplo abaixo, onde `$event` refere-se ao parâmetro do evento. Por favor, consulte a seção [Events](concept-events.md) para mais detalhes sobre eventos.
```php
function ($event) {
}
```
Anexando Behaviors (Comportamentos) <span id="attaching-behaviors"></span>
-------------------
Você pode anexar um behavior a um [[yii\base\Component|component]] de forma estática ou dinâmica. Na prática a forma estática é a mais comum.
Para anexar um behavior de forma estática, sobrescreva o método [[yii\base\Component::behaviors()|behaviors()]] da classe componente
para o behavior que está sendo anexado. O método [[yii\base\Component::behaviors()|behaviors()]] deveria retornar uma lista de behavior [configurations](concept-configurations.md).
Cada configuração de behavior pode ser tanto um nome de classe behavior ou um array de configuração:
```php
namespace app\models;
use yii\db\ActiveRecord;
use app\components\MyBehavior;
class User extends ActiveRecord
{
public function behaviors()
{
return [
// behavior anônimo, somente o nome da classe
MyBehavior::className(),
// behavior nomeado, somente o nome da classe
'myBehavior2' => MyBehavior::className(),
// behavior anônimo, array de configuração
[
'class' => MyBehavior::className(),
'prop1' => 'value1',
'prop2' => 'value2',
],
// behavior nomeado, array de configuração
'myBehavior4' => [
'class' => MyBehavior::className(),
'prop1' => 'value1',
'prop2' => 'value2',
]
];
}
}
```
Você pode associar um nome com um behavior especificando a chave do array correspondente à configuração do behavior. Neste caso o behavior é chamado *behavior nomeado*. No exemplo acima existem dois behaviors nomeados: `myBehavior2` e `myBehavior4`. Se um behavior não está associado a um nome, ele é chamado de *behavior anônimo*.
Para anexar um behavior dinâmicamente, execute o método [[yii\base\Component::attachBehavior()]] do component para o behavior que está sendo anexado:
```php
use app\components\MyBehavior;
// anexando um objeto behavior
$component->attachBehavior('myBehavior1', new MyBehavior);
// anexando uma classe behavior
$component->attachBehavior('myBehavior2', MyBehavior::className());
// anexando através de um array de configuração
$component->attachBehavior('myBehavior3', [
'class' => MyBehavior::className(),
'prop1' => 'value1',
'prop2' => 'value2',
]);
```
Você pode anexar vários behaviors de uma só vez usando o método [[yii\base\Component::attachBehaviors()]]:
```php
$component->attachBehaviors([
'myBehavior1' => new MyBehavior, // a named behavior
MyBehavior::className(), // an anonymous behavior
]);
```
Você também pode anexar behaviors através de [configurations](concept-configurations.md) conforme exemplo abaixo:
```php
[
'as myBehavior2' => MyBehavior::className(),
'as myBehavior3' => [
'class' => MyBehavior::className(),
'prop1' => 'value1',
'prop2' => 'value2',
],
]
```
Para mais detalhes, por favor consulte a seção [Configurations](concept-configurations.md#configuration-format).
Usando Behaviors <span id="using-behaviors"></span>
---------------
Para usar um behavior, primeiro este deve ser anexado à um [[yii\base\Component|component]] conforme as instruções acima. Uma vez que o behavior está anexado ao componente, seu uso é simples.
Você pode acessar uma variável *pública* ou uma propriedade [property](concept-properties.md) definida por um getter e/ou um setter do behavior através do componente ao qual ele está anexado:
```php
// "prop1" é uma propriedade defined na classe behavior
echo $component->prop1;
$component->prop1 = $value;
```
Você também pode executar um método *público* do behavior de forma parecida:
```php
// foo() é um método publico definido na classe behavior
$component->foo();
```
Como você pode ver, embora `$component` não define`prop1` e nem `foo()`, eles podem ser utilizados como se eles fizessem parte da definição do componente, isto se deve ao behavior anexado.
Se dois behaviors definem a mesma propriedade ou método e ambos são anexados ao mesmo componente, o behavior que for anexado primeiramente ao componente terá precedência quando a propriedade ou método for acessada.
Um behavior pode estar associado a um nome quando ele for anexado a um componente. Sendo esse o caso, você pode acessar o objeto behavior usando o name:
```php
$behavior = $component->getBehavior('myBehavior');
```
Você também pode pegar todos os behaviors anexados a um componente:
```php
$behaviors = $component->getBehaviors();
```
Desvinculando Behaviors (Comportamentos)<span id="detaching-behaviors"></span>
-------------------
Para desvincular um behavior, execute [[yii\base\Component::detachBehavior()]] com o nome associado ao behavior:
```php
$component->detachBehavior('myBehavior1');
```
Você também pode desvincular *todos* os behaviors:
```php
$component->detachBehaviors();
```
Usando `TimestampBehavior` <span id="using-timestamp-behavior"></span>
-------------------------
Para encerrar, vamos dar uma olhada [[yii\behaviors\TimestampBehavior]]. Este behavior suporta atualização automática dos atributos timestamp de um [[yii\db\ActiveRecord|Active Record]] toda vez que o model (modelo) for salvo (por exemplo, Inserte ou update).
Primeiro, anexe este behavior na classe [[yii\db\ActiveRecord|Active Record]] que você planeja usar:
```php
namespace app\models\User;
use yii\db\ActiveRecord;
use yii\behaviors\TimestampBehavior;
class User extends ActiveRecord
{
// ...
public function behaviors()
{
return [
[
'class' => TimestampBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],
],
],
];
}
}
```
A configuração do behavior acima especifica que quando o registro está sendo:
* inserido, o behavior deve atribuir o timestamp atual para os atributos `created_at` e `updated_at`
* atualizado, o behavior deve atribuir o timestamp atual para o atributo `updated_at`
Com esse código no lugar, se você tem um objeto `User` e tenta salvá-lo, você encontrará seus `created_at` e `updated_at` automáticamente preenchidos com a data e hora atual:
```php
$user = new User;
$user->email = 'test@example.com';
$user->save();
echo $user->created_at; // shows the current timestamp
```
O [[yii\behaviors\TimestampBehavior|TimestampBehavior]] também oferece um método útil
[[yii\behaviors\TimestampBehavior::touch()|touch()]], que irá atribuir a data e hora atual para um atributo específico e salvar o database:
```php
$user->touch('login_time');
```
Comparando Behaviors com Traits <span id="comparison-with-traits"></span>
----------------------
Apesar de behaviors serem semelhantes a [traits](http://www.php.net/traits) em que ambos "injetam" suas propriedades e métodos para a classe principal, eles diferem em muitos aspectos. Tal como explicado abaixo, ambos têm prós e contras. Eles funcionam mais como complemento um do outro.
### Razões para usar Behaviors <span id="pros-for-behaviors"></span>
Classes Behavior, como classes normais, suportam herança. Traits, por outro lado, pode ser só suporta a programação “copia e cola”. Eles não suportam herança.
Behaviors podem ser anexados e desvinculados a um componente dinamicamente sem necessidade de modificação da classe componente.
Para usar um trait, você deve modificar o código da classe de usá-lo.
Behaviors são configuráveis enquanto traits não são.
Behaviors podem customizar a execução do código do componente respondendo aos seus eventos.
Quando houver nomes conflitantes entre diferentes behaviors anexados ao mesmo componente, o conflito é automaticamente resolvido priorizando o behavior anexado primeiramente ao componente. Nomes conflitantes causados por diferentes traits requer resolução manual renomeando as propriedades ou métodos afetados.
### Razões para usar Traits <span id="pros-for-traits"></span>
Traits são muito mais eficientes do que behaviors, estes são objetos e requerem mais tempo e memória.
IDEs são mais amigáveis com traits por serem nativos do PHP.

94
docs/guide-pt-BR/concept-components.md

@ -0,0 +1,94 @@
Componentes
===========
Componente é a parte principal na construção de aplicações Yii. Componentes são instâncias de [[yii\base\Component]],
Ou uma classe extendida. As três características principais que os Componentes fornecem a outras classes são:
* [Propriedades](concept-properties.md)
* [Eventos](concept-events.md)
* [Behaviors (Comportamentos)](concept-behaviors.md)
Separadamente e combinadas, essas características fazem com que as classes no Yii sejam muito mais customizáveis e fáceis de usar. Por Exemplo,
O include [[yii\jui\DatePicker|date picker widget]], um componete de interface do usuário, pode ser usado na [view (visão)](structure-view.md)
Para gerar um `date picker` interativo:
```php
use yii\jui\DatePicker;
echo DatePicker::widget([
'language' => 'ru',
'name' => 'country',
'clientOptions' => [
'dateFormat' => 'yy-mm-dd',
],
]);
```
Os widgets são facilmente escritos porque a classe estende de [[yii\base\Component]].
Enquanto componenetese são muito poderosos, eles são um pouco mais pesados do que um objeto normal, devido ao fato de que é preciso
Memória e CPU extra para dar suporte a [evento](concept-events.md) e [comportamento](concept-behaviors.md) funcionalidade em particular.
Se o seu componente não precisa dessas duas características, você pode considerar extender a sua classe de componente de [[yii\base\Object]] em vez de [[yii\base\Component]]. Se o fizer, fará com que seus componentes sejam tão eficientes como objetos normais do PHP,
Mas com um suporte adcional para [propriedades](concept-properties.md).
Ao extender sua classe de [[yii\base\Component]] ou [[yii\base\Object]], é recomendado que você siga estas convenções:
- Se você sobrescrever o construtor, declare um parâmetro `$config` como último parâmetro do construtor, e em seguida passe este parâmetro para o construtor pai.
- Sempre chame o construtor pai *no final* do seu construtor reescrito.
- Se você sobrescrever o método [[yii\base\Object::init()]],certifique-se de chamar a implementação pai do `init` *no início* do seu método `init`.
Por Exemplo:
```php
<?php
namespace yii\components\MyClass;
use yii\base\Object;
class MyClass extends Object
{
public $prop1;
public $prop2;
public function __construct($param1, $param2, $config = [])
{
// ... initialization before configuration is applied
parent::__construct($config);
}
public function init()
{
parent::init();
// ... initialization after configuration is applied
}
}
```
Seguindo essas orientações fará com que seus componentes sejam [configuraveis](concept-configurations.md) quando forem criados. Por Exemplo:
```php
$component = new MyClass(1, 2, ['prop1' => 3, 'prop2' => 4]);
// alternatively
$component = \Yii::createObject([
'class' => MyClass::className(),
'prop1' => 3,
'prop2' => 4,
], [1, 2]);
```
> informação: Embora a forma de chamar [[Yii::createObject()]] pareça ser mais complicada, ela é mais poderosa porque ela é
> aplicada no topo de um [recipiente
de injeção de dependência](concept-di-container.md).
A Classe [[yii\base\Object]] inpõe o seguinte cilo de vida do objeto:
1. Pré-inicialização dentro do construtor. Você pode definir valores de propriedade padrão aqui.
2. Configuração de objeto via `$config`. A configuração pode sobrescrever o valor padrão configurado dentro do construtor.
3. Pós-inicialização dentro do [[yii\base\Object::init()|init()]]. Você pode sobrescrever este método para executar checagens e normalização das propriedades.
4. Chamadas de método de objeto.
Os três primeiros passos acontecem dentro do construtor do objeto. Isto significa que uma vez que você instancia a classe (Isto é, um objeto), esse objeto foi inicializado adequadamente.

246
docs/guide-pt-BR/concept-events.md

@ -0,0 +1,246 @@
Eventos
=======
Eventos permitem que você injete código personalizado dentro de outo código existente em determinados pontos de execução. Você pode anexar o código personalizado a um evento de modo que quando o evento é acionado, o código é executado automaticamente. Por exemplo, um objeto de e-mail pode disparar um evento `messageSent` quando o envio da mensagem for bem sucedida. Se você quiser acompanhar as mensagens que são enviadas com sucesso, você poderia então simplesmente anexar o código de acompanhamento ao evento `messageSent`.
Yii disponibiliza uma classe base chamada [[yii\base\Component]] para dar suporte a eventos.
Se sua classe precisar disparar eventos, ela deverá estender de [[yii\base\Component]], ou de uma classe-filha.
Manipuladores de Evento <span id="event-handlers"></span>
--------------
Um manipulador de evento é uma função [Callback do PHP] (http://www.php.net/manual/en/language.types.callable.php) que é executada quando o evento é disparado. Você pode usar qualquer um dos seguintes callbacks:
- uma função global do PHP especificada como uma string (sem parênteses), por exemplo, `'trim'`;
- Um método do objeto especificado como um array, informando o objeto e um nome do método como uma string (sem parênteses), por exemplo `[$object, 'methodName']`;
- Um método estático da classe especificado como um array informando o nome da classe e nome do método como string (sem parênteses), por exemplo, `['ClassName', 'methodName']`;
- Uma função anônima, por exemplo, `function ($event) { ... }`.
A assinatura de um manipulador de eventos é:
```php
function ($event) {
// $event is an object of yii\base\Event or a child class
}
```
Através do parâmetro `$event`, um manipulador de evento pode receber as seguintes informações sobre o evento que ocorreu:
- [[yii\base\Event::name|event name]]
- [[yii\base\Event::sender|event sender]]: o objeto cujo método `trigger()` foi chamado
- [[yii\base\Event::data|custom data]]: os dados que são fornecidos ao anexar o manipulador de eventos (a ser explicado a seguir)
Anexando manipuladores de eventos <span id="attaching-event-handlers"></span>
------------------------
Você pode anexar um manipulador para um evento, chamando o método [[yii\base\Component::on()]]. Por exemplo:
```php
$foo = new Foo;
// esse manipulador é uma função global
$foo->on(Foo::EVENT_HELLO, 'function_name');
// esse manipulador é um método de objeto
$foo->on(Foo::EVENT_HELLO, [$object, 'methodName']);
// esse manipulador é um método estático da classe
$foo->on(Foo::EVENT_HELLO, ['app\components\Bar', 'methodName']);
// esse manipulador é uma função anônima
$foo->on(Foo::EVENT_HELLO, function ($event) {
// Código ...
});
```
Você também pode anexar manipuladores de eventos por meio de [configurações](concept-configurations.md). Para mais detalhes, consulte a seção [Configurações](concept-configurations.md#configuration-format).
Ao anexar um manipulador de eventos, você pode fornecer dados adicionais no terceiro parâmetro do método [[yii\base\Component::on()]].
Os dados serão disponibilizados para o manipulador quando o evento for disparado e o manipulador chamado. Por exemplo:
```php
// O código a seguir mostrará "abc" quando o evento for disparado
// porque $event->data contêm os dados passados no terceiro parâmetro do "on"
$foo->on(Foo::EVENT_HELLO, 'function_name', 'abc');
function function_name($event) {
echo $event->data;
}
```
Ordem dos Manipuladores de Eventos
-------------------
Você pode anexar um ou mais manipuladores para um único evento. Quando o evento é disparado, os manipuladores anexados serão chamados na ordem em que eles foram anexados ao evento. Se o manipulador precisar interromper os eventos subsequentes, pode definir a propriedade [[yii\base\Event::handled]] do parâmetro `$event` para *true*:
```php
$foo->on(Foo::EVENT_HELLO, function ($event) {
$event->handled = true;
});
```
Por padrão, um novo manipulador é anexado a fila de manipuladores existente para o evento.
Como resultado, o manipulador será chamado por último quando o evento for disparado.
Para inserir um novo manipulador de evento no início da fila de modo a ser chamado primeiro, você pode chamar o método [[yii\base\Component::on()]], passando *false* para o quarto parâmetro `$append`:
```php
$foo->on(Foo::EVENT_HELLO, function ($event) {
// ...
}, $data, false);
```
Disparando Eventos <span id="triggering-events"></span>
-----------------
Os eventos são disparados chamando o método [[yii\base\Component::trigger()]]. Este método requer um *nome de evento*, e, opcionalmente, um objeto de evento que descreve os parâmetros a serem passados para os manipuladores de eventos. Por exemplo:
```php
namespace app\components;
use yii\base\Component;
use yii\base\Event;
class Foo extends Component
{
const EVENT_HELLO = 'hello';
public function bar()
{
$this->trigger(self::EVENT_HELLO);
}
}
```
Com o código acima, todas as chamadas para `bar ()` irão disparar um evento chamado `hello`.
> Dica: Recomenda-se usar constantes de classe para representar nomes de eventos. No exemplo acima, a constante `EVENT_HELLO` representa o evento `hello`. Esta abordagem tem três benefícios. Primeiro, previne erros de digitação. Segundo, pode fazer o evento se tornar reconhecível para recursos de *auto-complete* de IDEs. Terceiro, você pode especificar quais eventos são suportados em uma classe, basta verificar suas declarações de constantes.
Às vezes, quando um evento é disparado você pode querer passar junto informações adicionais para os manipuladores de eventos. Por exemplo, um objeto de e-mail pode querer passar uma informação para o manipulador do evento `messageSent` de modo que os manipuladores podem conhecer os detalhes das mensagens enviadas. Para fazer isso, você pode fornecer um objeto de evento como o segundo parâmetro para o método [[yii\base\Component::trigger()]]. Este objeto precisa ser uma instância da classe [[yii\base\Event]] ou de uma classe filha. Por exemplo:
```php
namespace app\components;
use yii\base\Component;
use yii\base\Event;
class MessageEvent extends Event
{
public $message;
}
class Mailer extends Component
{
const EVENT_MESSAGE_SENT = 'messageSent';
public function send($message)
{
// ...sending $message...
$event = new MessageEvent;
$event->message = $message;
$this->trigger(self::EVENT_MESSAGE_SENT, $event);
}
}
```
Quando o método [[yii\base\Component::trigger()]] é chamado, ele chamará todos os manipuladores ligados ao evento passado.
Desvinculando manipuladores de eventos <span id="detaching-event-handlers"></span>
------------------------
Para retirar um manipulador de um evento, chame o método [[yii\base\Component::off()]]. Por Exemplo:
```php
// o manipulador é uma função global
$foo->off(Foo::EVENT_HELLO, 'function_name');
// o manipulador é um método de objeto
$foo->off(Foo::EVENT_HELLO, [$object, 'methodName']);
// o manipulador é um método de estático da Classe
$foo->off(Foo::EVENT_HELLO, ['app\components\Bar', 'methodName']);
// o manipulador é uma função anônima
$foo->off(Foo::EVENT_HELLO, $anonymousFunction);
```
Note que, em geral, você não deve tentar desvincular uma função anônima, a menos que você guarde em algum lugar quando ela for ligada ao evento. No exemplo acima, é assumido que a função anónima é armazenada em uma variável `$anonymousFunction`.
Para desvincular todos os manipuladores de um evento, simplesmente chame [[yii\base\Component::off()]] sem o segundo parâmetro:
```php
$foo->off(Foo::EVENT_HELLO);
```
Manipuladores de Eventos de Classe <span id="class-level-event-handlers"></span>
--------------------------
As subseções acima descreveram como anexar um manipulador para um evento a *nível de instância* (objeto).
Às vezes, você pode querer responder a um evento acionado por *todas* as instâncias da classe em vez de apenas uma instânica específica. Em vez de anexar um manipulador de evento em todas as instâncias, você pode anexar o manipulador a *nível da classe* chamando o método estático [[yii\base\Event::on()]].
Por Exemplo, um objeto [Active Record](db-active-record.md) irá disparar um evento [[yii\db\BaseActiveRecord::EVENT_AFTER_INSERT|EVENT_AFTER_INSERT]] sempre que inserir um novo registro no database. A fim de acompanhar inserções feitas por *cada* objeto
[Active Record](db-active-record.md), você pode usar o seguinte código:
```php
use Yii;
use yii\base\Event;
use yii\db\ActiveRecord;
Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
Yii::trace(get_class($event->sender) . ' is inserted');
});
```
O manipulador de evento será invocado sempre que uma instância de [[yii\db\ActiveRecord|ActiveRecord]], ou uma de suas classes filhas, disparar o evento [[yii\db\BaseActiveRecord::EVENT_AFTER_INSERT|EVENT_AFTER_INSERT]]. No manipulador, você pode obter o objeto que disparou o evento através de `$event->sender`.
Quando um objecto dispara um evento, ele irá primeiro chamar manipuladores de nível de instância, seguido pelos manipuladores de nível de classe.
Você pode disparar um evento de *nível de classe* chamando o método estático [[yii\base\Event::trigger()]]. Um evento de nível de classe não está associado com um objeto particular. Como resultado, ele fará a chamada dos manipuladores de eventos apenas a nível da classe. Por exemplo:
```php
use yii\base\Event;
Event::on(Foo::className(), Foo::EVENT_HELLO, function ($event) {
echo $event->sender; // displays "app\models\Foo"
});
Event::trigger(Foo::className(), Foo::EVENT_HELLO);
```
Note que, neste caso, `$event->sender` refere-se ao nome da classe acionando o evento em vez de uma instância do objeto.
> Nota: Porque um manipulador de nível de classe vai responder a um evento acionado por qualquer instância dessa classe, ou qualquer classe filha, você deve usá-lo com cuidado, especialmente se a classe é uma classe base de baixo nível, tal como [[yii\base\Object]].
Para desvincular um manipulador de evento de nível de classe, chame [[yii\base\Event::off()]]. Por Exemplo:
```php
// desvincula $handler
Event::off(Foo::className(), Foo::EVENT_HELLO, $handler);
// Desvincula todos os manipuladores de Foo::EVENT_HELLO
Event::off(Foo::className(), Foo::EVENT_HELLO);
```
Eventos Globais <span id="global-events"></span>
-------------
Yii suporta o assim chamado *evento global*, que na verdade é um truque com base no mecanismo de eventos acima descrito.
O evento global requer um *singleton* acessível globalmente, tal como a própria instância [application](structure-applications.md).
Para criar o evento global, um evento *remetente* chama o método singleton `trigger()` para disparar o evento, em vez de chamar o método `trigger()` do *remetente* . Da mesma forma, os manipuladores de eventos são anexados ao evento no *singleton* . Por exemplo:
```php
use Yii;
use yii\base\Event;
use app\components\Foo;
Yii::$app->on('bar', function ($event) {
echo get_class($event->sender); // Mostra na tela "app\components\Foo"
});
Yii::$app->trigger('bar', new Event(['sender' => new Foo]));
```
A vantagem de usar eventos globais é que você não precisa de um objeto ao anexar um manipulador para o evento que será acionado pelo objeto. Em vez disso, a inclusão do manipulador e o evento acionado são ambos feitos através do *singleton*. (Por exemplo uma instância de application).
Contudo, porque o namespace dos eventos globais é compartilhado com todos, você deve nomear os eventos globais sabiamente, tais como a introdução de algum tipo de namespace (por exemplo. "frontend.mail.sent", "backend.mail.sent").

61
docs/guide-pt-BR/concept-properties.md

@ -0,0 +1,61 @@
Propriedades
===========
No PHP, atributos da classe são sempre chamadas de *propriedades*. Esses atributos fazem parte da definição da classe e são usadas para representar o estado de uma instância da classe (para diferenciar uma instância da classe de outra). Na prática, muitas vezes você pode querer lidar com a leitura ou a escrita de propriedades de maneiras especiais. Por Exemplo, você pode querer trimar uma string sempre que for atribuído um valor para a propriedade `label`. Você *poderia* usar o código a seguir para realizar esta tarefa:
```php
$object->label = trim($label);
```
A desvantagem do código acima é que você teria que chamar `trim ()` em todos os lugares onde você definir a propriedade `label` no seu código. Se, no futuro, a propriedade `label` receber um novo requisito, tais como a primeira letra deve ser capitalizado, você teria que modificar novamente todos os pedaços de código que atribui um valor para a propriedade `label`. A repetição de código leva a erros, e é uma prática que você deve evitar sempre que possível.
Para resolver este problema, Yii introduz uma classe base chamada [[yii\base\Object]] que suporta definições de propriedades baseadas nos métodos *getter* e *setter* da classe. Se uma classe precisa dessa funcionalidade, ela deve estender de [[yii\base\Object]], ou de uma classe-filha.
> Informação: Quase todas as classes nativas (core) do framework Yii estendem de [[yii\base\Object]] ou de uma classe-filha. Isto significa que sempre que você vê um método *getter* ou *setter* em uma classe nativa (core), você pode usá-lo como uma propriedade.
Um método getter é um método cujo nome inicia com a palavra `get`; um método setter inicia com `set`.
O nome depois do prefixo `get` ou `set` define o nome da propriedade. Por exemplo, um getter `getLabel()` e/ou um setter `setLabel()` define a propriedade chamada `label`, como mostrado no código a seguir:
```php
namespace app\components;
use yii\base\Object;
class Foo extends Object
{
private $_label;
public function getLabel()
{
return $this->_label;
}
public function setLabel($value)
{
$this->_label = trim($value);
}
}
```
(Para ser claro, os métodos getter e setter criam a propriedade `label`, que neste caso internamente refere-se ao atributo privado chamado `_label`.)
Propriedades definidas por getters e setters podem ser usados como atributos da classe. A principal diferença é que quando tal propriedade é iniciada para leitura, O método getter correspondente será chamado; quando a propriedade é iniciada atribuindo um valor, o método setter correspondente será chamado. Por Exemplo:
```php
// equivalent to $label = $object->getLabel();
$label = $object->label;
// equivalent to $object->setLabel('abc');
$object->label = 'abc';
```
A propriedade definida por um método getter sem um método setter é *somente de leitura*. Tentando atribuir um valor a tal propriedade causará uma exceção [[yii\base\InvalidCallException|InvalidCallException]]. Semelhantemente, uma propriedade definida por um método setter sem um método getter é *somente de gravação *, e tentar ler tal propriedade também causará uma exceção. Não é comum ter propriedade *somente de gravação*.
Existem várias regras especiais para, e limitações sobre, as propriedades definidas via getters e setters:
* Os nomes dessas propriedades são *case-insensitive*. Por exemplo, `$object->label` e `$object->Label` são a mesma coisa. Isso ocorre porque nomes de métodos no PHP são case-insensitive.
* Se o nome de uma tal propriedade é o mesmo que um atributo da classe, esta última terá precedência. Por exemplo, se a classe `Foo` descrita acima tiver um atributo `label`, então a atribuição `$object->label = 'abc'` afetará o *atributo* 'label'; esta linha não executaria `setLabel()` método setter.
* Essas propriedades não suportam visibilidade. Não faz nenhuma diferença para a definição dos métodos getter ou setter se a propriedade é pública, protegida ou privada.
* As propriedades somente podem ser definidas por getters e/ou setters *não estáticos*. Os métodos estáticos não serão tratados da mesma maneira.
Voltando para o problema descrito no início deste guia, em vez de chamar `trim()` em todos os lugares que um valor for atribuído a `label`, `trim()`Agora, só precisa ser invocado dentro do setter `setLabel()`.E se uma nova exigência faz com que seja necessário que o 'label' seja inicializado capitalizado, o método `setLabel()` pode rapidamente ser modificado sem tocar em nenhum outro código. Esta única mudança afetará de forma global cada atribuição à propriedade `label`.

421
docs/guide-pt-BR/db-migrations.md

@ -0,0 +1,421 @@
Migrações de Dados (Migrations)
==================
Durante o curso de desenvolvimento e manutenção de uma aplicação orientada a banco de dados, a estrutura
de banco sendo usada evolui ao mesmo tempo em que o código. Por exemplo, durante o desenvolvimento de
uma aplicação, a criação de uma nova tabela pode ser necessária; após ser feito o deploy da aplicação em produção,
pode ser descoberto que um índice deveria ser criado para melhorar a performance de alguma query; entre
outros. Como a mudança de uma estrutura de banco de dados normalmente necessita de alguma mudança no código,
Yii suporta a então chamada funcionalidade de *migração de dados* que permite que você mantenha um registro
das mudanças feitas no banco de dados em termos de *migrações de dados* que são versionadas em conjunto
com o código fonte da aplicação.
Os seguintes passos mostram como uma migração de dados pode ser usada pela equipe durante o desenvolvimento:
1. João cria uma nova migração (ex. cria uma nova tabela, muda a definição de uma coluna, etc.).
2. João comita a nova migração no sistema de controle de versão (ex. Git, Mercurial).
3. Pedro atualiza seu repositório a partir do sistema de controle de versão e recebe a nova migração.
4. Pedro aplica a nova migração ao seu banco de dados local em seu ambiente de desenvolvimento, e assim, sincronizando seu banco de dados para refletir as mudanças que João fez.
E os seguintes passos mostram como fazer o deploy para produção de uma nova versão:
1. Luiz cria uma nova tag para o repositório do projeto que contem algumas novas migrações de dados.
2. Luiz atualiza o código fonte no servidor em produção para a tag criada.
3. Luiz aplica todas as migrações de dados acumuladas para o banco de dados em produção.
Yii oferece um conjunto de ferramentas de linha de comando que permitem que você:
* crie novas migrações;
* aplique migrações;
* reverta migrações;
* reaplique migrações;
* exiba um histórico das migrações;
Todas estas ferramentas são acessíveis através do comando `yii migrate`. Nesta seção nós iremos descrever
em detalhes como realizar várias tarefas usando estas ferramentas. Você também pode descobrir como usar
cada ferramenta através do comando de ajuda `yii help migrate`.
> Observação: os migrations (migrações) podem afetar não só o esquema do banco de dados,
mas também ajustar os dados existentes para se conformar ao novo esquema, como
criar novas hierarquias de RBAC ou limpar dados de cache.
## Criando Migrações <span id="creating-migrations"></span>
Para criar uma nova migração, execute o seguinte comando:
```
yii migrate/create <nome>
```
O argumento obrigatório `nome` serve como uma breve descricão sobre a nova migração. Por exemplo, se
a migração é sobre a criação de uma nova tabela chamada *noticias*, você pode usar o nome `criar_tabela_noticias`
e executar o seguinte comando:
```
yii migrate/create criar_tabela_noticias
```
> Nota: Como o argumento `nome` será usado como parte do nome da classe de migração gerada, este deve
conter apenas letras, dígitos, e/ou underline.
O comando acima irá criar um novo arquivo contendo uma classe PHP chamada `m150101_185401_criar_tabela_noticias.php`
na pasta `@app/migrations`. O arquivo contem o seguinte codigo que declara a classe de migração
`m150101_185401_criar_tabela_noticias` com o código esqueleto:
```php
<?php
use yii\db\Schema;
use yii\db\Migration;
class m150101_185401_criar_tabela_noticias extends Migration
{
public function up()
{
}
public function down()
{
echo "m101129_185401_criar_tabela_noticias cannot be reverted.\n";
return false;
}
}
```
Cada migração de dados é definida como uma classe PHP extendida de [[yii\db\Migration]]. O nome da
classe de migração é automaticamente gerado no formato `m<YYMMDD_HHMMSS>_<Nome>`, onde
* `<YYMMDD_HHMMSS>` refere-se a data UTC em que o comando de criação da migração foi executado.
* `<Nome>` é igual ao valor do argumento `nome` que você passou no comando.
Na classe de migração, é esperado que você escreva no método `up()` as mudanças a serem feitas na estrutura do banco de dados.
Você também pode escrever código no método `down()` para reverter as mudanças feitas por `up()`. O método `up()` é invocado quando você atualiza o seu banco de dados com esta migração, enquanto o método `down()` é invocado quando você reverte as mudanças no banco. O seguinte código mostra como você pode implementar a classe de migração para criar a tabela `noticias`:
```php
use yii\db\Schema;
use yii\db\Migration;
class m150101_185401_criar_tabela_noticias extends \yii\db\Migration
{
public function up()
{
$this->createTable('noticias', [
'id' => Schema::TYPE_PK,
'titulo' => Schema::TYPE_STRING . ' NOT NULL',
'conteudo' => Schema::TYPE_TEXT,
]);
}
public function down()
{
$this->dropTable('noticias');
}
}
```
> Observação: Nem todas as migrações são reversíveis. Por exemplo, se o método `up()` deleta um registro de uma tabela,
você possívelmente não será capaz de recuperar este registro com o método `down()`. Em alguns casos, você pode ter
tido muita preguiça e não ter implementado o método `down()`, porque não é muito comum reverter migrações de dados.
Neste caso, você deve retornar `false` no método `down()` para indicar que a migração não é reversível.
A classe base de Migração [[yii\db\Migration]] expõe a conexão ao banco através da propriedade [[yii\db\Migration::db|db]].
Você pode usá-la para manípular o esquema do banco de dados usando os métodos como descritos em
[Trabalhando com um Esquema de Banco de Dados](db-dao.md#working-with-database-schema-).
Ao invés de usar típos físicos, ao criar uma tabela ou coluna, você deve usar *tipos abstratos* para que
suas migrações sejam independentes do SGBD. A classe [[yii\db\Schema]] define uma gama de constantes para
representar os tipos abstratos suportados. Estas constantes são nomeadas no formato `TYPE_<NOME>`. Por exemplo,
`TYPE_PK` refere-se ao tipo chave primária auto-incrementavel; `TYPE_STRING` refere-se ao típo string.
Quando a migração for aplicada a um banco de dados em particular, os tipos abstratos serão traduzidos nos
respectívos tipos físicos. No caso do MySQL, `TYPE_PK` será traduzida para
`int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY`, enquanto `TYPE_STRING` será `varchar(255)`.
Você pode adicionar algumas constraints ao usar tipos abstratos. No exemplo acíma, ` NOT NULL` é adicionado
a `Schema::TYPE_STRING` para especificar que a coluna não pode ser nula.
> Observação: O mapeamento entre tipos abstratos e tipos físicos é especificado pela propriedade [[yii\db\QueryBuilder::$typeMap|$typeMap]] em cada classe `QueryBuilder`.
### Migrações Transacionais <span id="transactional-migrations"></span>
Ao realizar migrações de dados complexas, é importante assegurar que cada migração irá ter sucesso ou irá falhar
por completo para que o banco não perca sua integridade e consistencia. Para atingir este objetivo, recomenda-se que
você encapsule suas operações de banco de dados de cada migração em uma [transação](db-dao.md#performing-transactions-).
Um jeito mais fácil de implementar uma migração transacional é colocar o seu código de migração nos métodos `safeUp()` e `safeDown()`. Estes métodos diferem de `up()` e `down()` por que eles estão implicitamente encapsulados em uma transação. Como resultado, se qualquer operação nestes métodos falhar, todas as operações anteriores sofrerão roll back
automaticamente.
No exemplo a seguir, além de criar a tabela `noticias` nós também inserimos um registro inicial a esta tabela.
```php
use yii\db\Schema;
use yii\db\Migration;
class m150101_185401_criar_tabela_noticias extends Migration
{
public function safeUp()
{
$this->createTable('noticias', [
'id' => 'pk',
'titulo' => Schema::TYPE_STRING . ' NOT NULL',
'conteudo' => Schema::TYPE_TEXT,
]);
$this->insert('noticias', [
'titulo' => 'título 1',
'conteudo' => 'conteúdo 1',
]);
}
public function safeDown()
{
$this->delete('noticias', ['id' => 1]);
$this->dropTable('noticias');
}
}
```
Note que normalmente quando você realiza multiplas operações em `safeUp()`, você deverá reverter a ordem de execução
em `safeDown()`. No exemplo acima nós primeiramente criamos a tabela e depois inserimos uma túpla em `safeUp()`; enquanto
em `safeDown()` nós primeiramente apagamos o registro e depois eliminamos a tabela.
> Nota: Nem todos os SGBDs suportam transações. E algumas requisições de banco não podem ser encapsuladas em uma transação. Para alguns exemplos, referir a [commit implicito(inglês)](http://dev.mysql.com/doc/refman/5.1/en/implicit-commit.html). Se este for o caso, implemente os métodos `up()` e `down()`.
### Métodos de acesso ao Banco de Dados <span id="db-accessing-methods"></span>
A classe base migração [[yii\db\Migration]] entrega vários métodos que facilitam o acesso e a manipulação de
bancos de dados. Você deve achar que estes métodos são nomeados similarmente a [métodos DAO](db-dao.md) encontrados
na classe [[yii\db\Command]]. Por exemplo, o método [[yii\db\Migration::createTable()]] permite que você crie uma
nova tabela assim como [[yii\db\Command::createTable()]] o faz.
O benefício ao usar os métodos encontrados em [[yii\db\Migration]] é que você não precisa criar explícitamente
instancias de [[yii\db\Command]] e a execução de cada método automaticamente exibirá mensagens úteis que dirão
a você quais operações estão sendo feitas e quanto tempo elas estão durando.
Abaixo está uma lista de todos estes métodos de acesso ao banco de dados:
* [[yii\db\Migration::execute()|execute()]]: executando um SQL
* [[yii\db\Migration::insert()|insert()]]: inserindo um novo regístro
* [[yii\db\Migration::batchInsert()|batchInsert()]]: inserindo vários registros
* [[yii\db\Migration::update()|update()]]: atualizando registros
* [[yii\db\Migration::delete()|delete()]]: apagando registros
* [[yii\db\Migration::createTable()|createTable()]]: criando uma tabela
* [[yii\db\Migration::renameTable()|renameTable()]]: renomeando uma tabela
* [[yii\db\Migration::dropTable()|dropTable()]]: removendo uma tabela
* [[yii\db\Migration::truncateTable()|truncateTable()]]: removendo todos os registros em uma tabela
* [[yii\db\Migration::addColumn()|addColumn()]]: adicionando uma coluna
* [[yii\db\Migration::renameColumn()|renameColumn()]]: renomeando uma coluna
* [[yii\db\Migration::dropColumn()|dropColumn()]]: removendo uma coluna
* [[yii\db\Migration::alterColumn()|alterColumn()]]: alterando uma coluna
* [[yii\db\Migration::addPrimaryKey()|addPrimaryKey()]]: adicionando uma chave primária
* [[yii\db\Migration::dropPrimaryKey()|dropPrimaryKey()]]: removendo uma chave primária
* [[yii\db\Migration::addForeignKey()|addForeignKey()]]: adicionando uma chave estrangeira
* [[yii\db\Migration::dropForeignKey()|dropForeignKey()]]: removendo uma chave estrangeira
* [[yii\db\Migration::createIndex()|createIndex()]]: criando um índice
* [[yii\db\Migration::dropIndex()|dropIndex()]]: removendo um índice
> Observação: [[yii\db\Migration]] não possui um método de consulta ao banco de dados. Isto porque você normalmente não irá precisar exibir informações extras ao recuperar informações de um banco de dados. E além disso você pode usar o poderoso [Query Builder](db-query-builder.md) para construir e executar consultas complexas.
## Aplicando migrações <span id="applying-migrations"></span>
Para atualizar um banco de dados para a sua estrutura mais atual, você deve aplicar todas as migracões disponíveis usando o seguinte comando:
```
yii migrate
```
Este comando irá listar todas as migrações que não foram alicadas até agora. Se você confirmar que deseja aplicar
estas migrações, cada nova classe de migração irá executar os métodos `up()` ou `safeUp()` um após o outro, na
ordem relacionada à data marcada em seus nomes. Se qualquer uma das migrações falhar, o comando terminará sem aplicar
o resto das migrações.
Para cada migração aplicada com sucesso, o comando irá inserir um registro numa tabela no banco de dados chamada
`migration` para registrar uma aplicação de migração. Isto irá permitir que a ferramenta de migração identifique
quais migrações foram aplicadas e quais não foram.
> Observação: Esta ferramenta de migração irá automaticamente criar a tabela `migration` no banco de dados especificado pela opção do comando [[yii\console\controllers\MigrateController::db|db]]. Por padrão, o banco de dados é especificado por `db` em [Componentes de Aplicação](structure-application-components.md).
Eventualmente, você desejará aplicar apenas uma ou algumas migrações, em vez de todas as disponíveis.
Você pode fazê-lo especificando o número de migrações que deseja aplicar ao executar o comando.
Por exemplo, o comando a seguir irá tentar aplicar as próximas 3 migrações disponíveis:
```
yii migrate 3
```
Você também pode especificar para qual migração em particular o banco de dados deve ser migrado
usando o comando `migrate/to` em um dos formatos seguintes:
```
yii migrate/to 150101_185401 # usando a marcação de data para especificar a migração
yii migrate/to "2015-01-01 18:54:01" # usando uma string que pode ser analisada por strtotime()
yii migrate/to m150101_185401_criar_tabela_noticias # usando o nome completo
yii migrate/to 1392853618 # usando uma marcação de data no estilo UNIX
```
Se existirem migrações mais recentes do que a especificada, elas serão todas aplicadas antes da migração definida.
Se a migração especificada ja tiver sido aplicada, qualquer migração posterior já aplicada será revertida.
## Revertendo Migrações <span id="reverting-migrations"></span>
Para reverter uma ou multiplas migrações que tenham sido aplicadas antes, você pode executar o seguinte comando:
```
yii migrate/down # reverter a última migração aplicada
yii migrate/down 3 # reverter as 3 últimas migrações aplicadas
```
> Nota: Nem todas as migrações são reversíveis. Tentar reverter tais migrações irá causar um erro que irá cancelar todo o processo de reversão.
## Refazendo Migrações <span id="redoing-migrations"></span>
Refazer as migrações significa primeiramente reverter migrações especificadas e depois aplicá-las novamente.
Isto pode ser feito da seguinte maneira:
```
yii migrate/redo # refazer a última migração aplicada
yii migrate/redo 3 # refazer as 3 últimas migrações aplicadas
```
> Nota: Se a migração não for reversível, você não poderá refazê-la.
## Listando Migrações <span id="listing-migrations"></span>
Para listar quais migrações foram aplicadas e quais não foram, você deve usar os seguintes comandos:
```
yii migrate/history # exibir as 10 últimas migrações aplicadas
yii migrate/history 5 # exibir as 5 últimas migrações aplicadas
yii migrate/history all # exibir todas as migrações aplicadas
yii migrate/new # exibir as 10 primeiras novas migrações
yii migrate/new 5 # exibir as 5 primeiras novas migrações
yii migrate/new all # exibir todas as novas migrações
```
## Modificando o Histórico das Migrações <span id="modifying-migration-history"></span>
Ao invés de aplicar ou reverter migrações, pode ser que você queira apenas definir que o seu banco de dados
foi atualizado para uma migração em particular. Isto normalmente acontece quando você muda manualmente o banco
de dados para um estado em particular, e não deseja que as mudanças para aquela migração sejam reaplicadas
posteriormente. Você pode alcancar este objetivo com o seguinte comando:
```
yii migrate/mark 150101_185401 # usando a marcação de data para especificar a migração
yii migrate/mark "2015-01-01 18:54:01" # usando uma string que pode ser analisada por strtotime()
yii migrate/mark m150101_185401_criar_tabela_noticias # usando o nome completo
yii migrate/mark 1392853618 # usando uma marcação de data no estilo UNIX
```
O comando irá modificar a tabela `migration` adicionando ou deletando certos registros para indicar que o banco
de dados sofreu as migrações especificadas. Nenhuma migração será aplicada ou revertida por este comando.
## Customizando Migrações <span id="customizing-migrations"></span>
Existem várias maneiras de customizar o comando de migração.
### Usando Opções na Linha de Comando <span id="using-command-line-options"></span>
O comando de migração vem com algumas opções de linha de comando que podem ser usadas para customizar o seu comportamento:
* `interactive`: boolean (o padrão é true), especifica se as migrações serão executadas em modo interativo.
Quando for true, ao usuario será perguntado se a execução deve continuar antes de o comando executar certas ações.
Você provavelmente marcará isto para falso se o comando estiver sendo feito em algum processo em segundo plano.
* `migrationPath`: string (o padrão é `@app/migrations`), especifica o diretório em que os arquivos das classes de migração estão. Isto pode ser especificado ou como um diretório ou como um [alias](concept-aliases.md).
Note que o diretório deve existir, ou o comando irá disparar um erro.
* `migrationTable`: string (o padrão é `migration`), especifica o nome da tabela no banco de dados para armazenar o histórico das migrações. A tabela será automaticamente criada pelo comando caso não exista.
Você também pode criá-la manualmente usando a estrutura `version varchar(255) primary key, apply_time integer`.
* `db`: string (o padrão é `db`), especifica o banco de dados [componente de aplicação](structure-application-components.md).
Representa qual banco sofrerá as migrações usando este comando.
* `templateFile`: string (o padrão é `@yii/views/migration.php`), especifica o caminho do arquivo de modelo que é usado para gerar um esqueleto para os arquivos das classes de migração. Isto pode ser especificado por um caminho de arquivo ou por um [alias](concept-aliases.md). O arquivo modelo é um script PHP em que você pode usar uma variaval pré-definida `$className` para obter o nome da classe de migração.
O seguinte exemplo exibe como você pode usar estas opções.
Por exemplo, se nós quisermos migrar um módulo `forum` cujo os arquivos de migração estão localizados dentro da pasta `migrations` do módulo, nós podemos usar o seguinte comando:
```
# migrate the migrations in a forum module non-interactively
yii migrate --migrationPath=@app/modules/forum/migrations --interactive=0
```
### Configurando o Comando Globalmente <span id="configuring-command-globally"></span>
Ao invés de fornecer opções todas as vezes que você executar o comando de migração,
você pode configurá-lo de uma vez por todas na configuração da aplicação como exibido abaixo:
```php
return [
'controllerMap' => [
'migrate' => [
'class' => 'yii\console\controllers\MigrateController',
'migrationTable' => 'backend_migration',
],
],
];
```
Com a configuração acima, toda a vez que você executar o comando de migração, a tabela `backend_migration`
será usada para gravar o histórico de migração. Você não irá mais precisar fornecê-la através da opção `migrationTable`.
## Migrando Multiplos Bancos De Dados <span id="migrating-multiple-databases"></span>
Por padrão, as migrações são aplicadas no mesmo banco de dados especificado por `db` [componente de aplicação](structure-application-components.md).
Se você quiser que elas sejam aplicadas em um banco de dados diferente, você deve especificar na opção `db` como exibido abaixo,
```
yii migrate --db=db2
```
O comando acima irá aplicar as migrações para o banco de dados `db2`.
Algumas vezes pode ocorrer que você queira aplicar *algumas* das migrações para um banco de dados, e outras para
outro banco de dados. Para atingir este objetivo, ao implementar uma classe de migração você deve especificar a
ID do componente DB que a migração irá usar, como o seguinte:
```php
use yii\db\Schema;
use yii\db\Migration;
class m150101_185401_criar_tabela_noticias extends Migration
{
public function init()
{
$this->db = 'db2';
parent::init();
}
}
```
A migração acima será aplicada a `db2`, mesmo que você especifique um banco de dados diferente através da opção `db`. Note que o histórico da migração continuará sendo registrado no banco especificado pela opção `db`.
Se você tiver multiplas migrações que usam o mesmo banco de dados, é recomenda-se criar uma classe de migração
base com o codigo acima em `init()`. Então cada classe de migração poderá ser extendida desta classe base.
> Dica: Apesas de definir a propriedade [[yii\db\Migration::db|db]], você também pode operar em diferentes bancos
de dados ao criar novas conexões de banco para eles em sua classe de migração. Você então usará os [métodos DAO](db-dao.md)
com estas conexões para manipular diferentes bancos de dados.
Outra estratégia que você pode seguir para migrar multiplos bancos de dados é manter as migrações para diferentes bancos
de dados em diferentes pastas de migrações. Então você poderá migrar estes bancos de dados em comandos separados como os seguintes:
```
yii migrate --migrationPath=@app/migrations/db1 --db=db1
yii migrate --migrationPath=@app/migrations/db2 --db=db2
...
```
O primeiro comando irá aplicar as migrações em `@app/migrations/db1` para o banco de dados `db1`, e o segundo comando
irá aplicar as migrações em `@app/migrations/db2` para `db2`, e assim sucessivamente.

10
docs/guide-pt-BR/intro-upgrade-from-v1.md

@ -120,8 +120,8 @@ $object = Yii::createObject([
], [$param1, $param2]);
```
Mais detalhes sobre configurações podem ser encontradas na seção
[Configurações de Objetos](concept-configurations.md).
Mais detalhes sobre configurações podem ser encontradas na seção de
[Configurações](concept-configurations.md).
Eventos
@ -537,11 +537,11 @@ User e IdentityInterface
A classe `CWebUser` do 1.1 agora foi substituída pela [[yii\web\User]], e não há
mais a classe `CUserIdentity`. Ao invés disso, você deve implementar a interface
[[yii\web\IdentityInterface]] que é muito mais simples de usar. O template de
aplicação avançado dá um exemplo disso.
[[yii\web\IdentityInterface]] que é muito mais simples de usar. O template avançado
de projetos dá um exemplo disso.
Por favor consulte as seções [Autenticação](security-authentication.md),
[Autorização](security-authorization.md), e [Template Avançado de Aplicação](tutorial-advanced-app.md)
[Autorização](security-authorization.md), e [Template Avançado de Projetos](tutorial-advanced-app.md)
para mais detalhes.

4
docs/guide-pt-BR/intro-yii.md

@ -37,7 +37,7 @@ Se já estiver familiarizado com um outro framework, você pode gosta se saber c
que podem ser redistribuídas.
- A alta performance é sempre um objetivo principal do Yii.
O Yii não é um show de um homem só, ele é apoiado por uma [forte equipe de desenvolvedores do core][]
O Yii não é um show de um homem só, ele é apoiado por uma [forte equipe de desenvolvedores do core][about_yii]
bem como por uma ampla comunidade de muitos profissionais constantemente
contribuindo com o desenvolvimento do Yii. A equipe de desenvolvedores do Yii
acompanha de perto às últimas tendências do desenvolvimento Web, e às
@ -46,7 +46,7 @@ As melhores práticas e funcionalidades mais relevantes encontradas em outros lu
são incorporadas regularmente no core do framework e expostas via interfaces
simples e elegantes.
[forte equipe desenvolvedores do core]: http://www.yiiframework.com/about/
[about_yii]: http://www.yiiframework.com/about/
Versões do Yii
--------------

162
docs/guide-pt-BR/runtime-requests.md

@ -0,0 +1,162 @@
Requisições
===========
As requisições realizadas na aplicação são representadas pelo objeto [[yii\web\Request]]
que fornece informações como os parâmetros da requisição, cabeçalhos HTTP, cookies
e etc. Em uma determinada requisição, você pode acessar o objeto da requisição
correspondente através do [componente da aplicação](structure-application-components.md)
`request`, que é uma instância de [[yii\web\Request]], por padrão. Nesta seção,
descreveremos como você pode usar este componente em sua aplicação.
## Parâmetros da Requisição <span id="request-parameters"></span>
Para obter os parâmetros da requisição, você pode chamar os métodos
[[yii\web\Request::get()|get()]] e [[yii\web\Request::post()|post()]] do
componente `request`. Estes métodos retornam os valores de `$_GET` e `$_POST`,
respectivamente. Por exemplo,
```php
$request = Yii::$app->request;
$get = $request->get();
// equivalente à: $get = $_GET;
$id = $request->get('id');
// equivalente à: $id = isset($_GET['id']) ? $_GET['id'] : null;
$id = $request->get('id', 1);
// equivalente à: $id = isset($_GET['id']) ? $_GET['id'] : 1;
$post = $request->post();
// equivalente à: $post = $_POST;
$name = $request->post('name');
// equivalente à: $name = isset($_POST['name']) ? $_POST['name'] : null;
$name = $request->post('name', '');
// equivalente à: $name = isset($_POST['name']) ? $_POST['name'] : '';
```
> Informação: Ao invés de acessar diretamente o `$_GET` e o `$_POST` para recuperar
os parâmetros da requisição, é recomendável que os utilizem através do componente
`request`, como mostrado nos exemplos acima. Isto permite que você escreva testes
de forma mais simples, utilizando um componente da requisição que retornem valores
pré-determinados.
Ao implementar o [RESTful APIs](rest-quick-start.md), muitas vezes você precisará
recuperar os parâmetros que foram enviados pelos [métodos de requisição](#request-methods)
PUT, PATCH ou outro. Você pode recuperá-los chamando o método [[yii\web\Request::getBodyParam()]].
Por exemplo,
```php
$request = Yii::$app->request;
// retorna todos os parâmetros
$params = $request->bodyParams;
// retorna o parâmetro "id"
$param = $request->getBodyParam('id');
```
> Informação: Tirando os parâmetros `GET`, os parâmetros `POST`, `PUT`, `PATCH`
e etc são enviados no corpo da requisição. O componente `request` analisará
estes parâmetros quando você acessá-los através dos métodos descritos acima.
Você pode personalizar a forma como estes parâmetros são analisados pela
configuração da propriedade [[yii\web\Request::parsers]].
## Métodos da Requisição <span id="request-methods"></span>
Você pode obter o método HTTP usado pela requisição atual através da expressão
`Yii::$app->request->method`. Um conjunto de propriedades booleanas também são
fornecidos para que você consiga verificar se o método atual é o correto.
Por exemplo,
```php
$request = Yii::$app->request;
if ($request->isAjax) { /* a requisição é uma requisição Ajax */ }
if ($request->isGet) { /* o método da requisição é GET */ }
if ($request->isPost) { /* o método da requisição é POST */ }
if ($request->isPut) { /* o método da requisição é PUT */ }
```
## URLs da Requisição <span id="request-urls"></span>
O componente `request` fornece muitas formas de inspecionar a atual URL da requisição.
Assumindo que a URL da requisição seja `http://example.com/admin/index.php/product?id=100`,
você pode obter várias partes desta URL através das propriedades explicadas a seguir:
* [[yii\web\Request::url|url]]: retorna `/admin/index.php/product?id=100`, que é
a URL sem as informações de protocolo e de domínio.
* [[yii\web\Request::absoluteUrl|absoluteUrl]]: retorna `http://example.com/admin/index.php/product?id=100`,
que é a URL completa, incluindo as informações de protocolo e de domínio.
* [[yii\web\Request::hostInfo|hostInfo]]: retorna `http://example.com`, que são
as informações de protocolo e de domínio da URL.
* [[yii\web\Request::pathInfo|pathInfo]]: retorna `/product`, que é a informação
depois do script de entrada e antes da interrogação (da query string).
* [[yii\web\Request::queryString|queryString]]: retorna `id=100`, que é a
informação depois da interrogação.
* [[yii\web\Request::baseUrl|baseUrl]]: retorna `/admin`, que é a informação
depois do domínio e antes do script de entrada.
* [[yii\web\Request::scriptUrl|scriptUrl]]: retorna `/admin/index.php`, que é a
informação depois do domínio até o script de entrada, inclusive.
* [[yii\web\Request::serverName|serverName]]: retorna `example.com`, que é o
domínio da URL.
* [[yii\web\Request::serverPort|serverPort]]: retorna 80, que é a porta usada
pelo servidor Web.
## Cabeçalho HTTP <span id="http-headers"></span>
Você pode obter as informações do cabeçalho HTTP através da
[[yii\web\HeaderCollection|coleção de cabeçalho]] retornado pela propriedade
[[yii\web\Request::headers]]. Por exemplo,
```php
// $headers é um objeto de yii\web\HeaderCollection
$headers = Yii::$app->request->headers;
// retorna o valor do cabeçalho Accept
$accept = $headers->get('Accept');
if ($headers->has('User-Agent')) { /* existe o cabeçalho User-Agent */ }
```
O componente `request` também fornece suporte para fácil acesso de alguns
cabeçalhos mais utilizados, incluindo:
* [[yii\web\Request::userAgent|userAgent]]: retorna o valor do cabeçalho `User-Agent`.
* [[yii\web\Request::contentType|contentType]]: retorna o valor do cabeçalho
`Content-Type` que indica o tipo MIME dos dados do corpo da requisição.
* [[yii\web\Request::acceptableContentTypes|acceptableContentTypes]]: retorna os
tipos MIME acessíveis pelos usuários. Os tipos retornados são ordenados pela
sua pontuação de qualidade. Tipos com mais pontuação aparecerão nas primeiras posições.
* [[yii\web\Request::acceptableLanguages|acceptableLanguages]]: retorna os idiomas
acessíveis pelos usuários. Os idiomas retornados são ordenados pelo nível de
preferência. O primeiro elemento representa o idioma de maior preferência.
Se a sua aplicação suportar diversos idiomas e quiser exibir páginas no idioma
de maior preferência do usuário, você pode usar o método de negociação
[[yii\web\Request::getPreferredLanguage()]]. Este método pega uma lista de
idiomas suportadas pela sua aplicação e compara com
[[yii\web\Request::acceptableLanguages|acceptableLanguages]], para retornar o
idioma mais adequado.
> Dica: Você também pode utilizar o filtro [[yii\filters\ContentNegotiator|ContentNegotiator]]
para determinar dinamicamente qual tipo de conteúdo e idioma que deve ser utilizado
na resposta. O filtro implementa negociação de conteúdo em cima das propriedades
e métodos descritos acima.
## Informações do Cliente <span id="client-information"></span>
Você pode obter o nome do domínio ou endereço IP da máquina do cliente através
das propriedades [[yii\web\Request::userHost|userHost]] e
[[yii\web\Request::userIP|userIP]], respectivamente. Por exemplo,
```php
$userHost = Yii::$app->request->userHost;
$userIP = Yii::$app->request->userIP;
```

752
docs/guide-pt-BR/runtime-routing.md

@ -0,0 +1,752 @@
Roteamento e Criação de URL
===========================
Quando uma aplicação Yii começa a processar uma URL requerida, o primeiro passo
necessário é obter a rota pela análise da URL. A rota é usada para instanciar o
[controlador (controller) da ação](structure-controllers.md) correspondente para
manipular a requisição. Todo este processo é chamado de *roteamento*.
O processo inverso do roteamento é chamada de *criação de URL*, onde é criado uma
URL a partir de uma determinada rota e seus parâmetros. Quando a URL criada for
exigida em outro momento, o processo de roteamento pode resolve-la de volta para
a rota original e seus parâmetros.
O ponto central responsável pelo roteamento e pela criação de URL é o
[[yii\web\UrlManager|gerenciador de URL]], na qual é registrado como o
[componente da aplicação](structure-application-components.md) `urlManager`. O
[[yii\web\UrlManager|gerenciador de URL]] fornece o método
[[yii\web\UrlManager::parseRequest()|parseRequest()]] para analisar um requisição
de entrada a fim de obter uma rota e seus parâmetros associados; e o método
[[yii\web\UrlManager::createUrl()|createUrl()]] para criar uma URL a partir de
uma rota e seus parâmetros associados.
Ao configurar o componente `urlManager` na configuração da aplicação, poderá
fazer com que sua aplicação reconheça de forma arbitrária diversos formatos de
URL sem modificar o código existente da aplicação. Por exemplo, você pode usar o
código a seguir para criar uma URL a partir da ação `post/view`:
```php
use yii\helpers\Url;
// Url::to() chama UrlManager::createUrl() para criar uma URL
$url = Url::to(['post/view', 'id' => 100]);
```
Dependendo da configuração da propriedade `urlManager`, a URL criada pode ser
parecida com um dos formatos a seguir (ou até mesmo com outro formato). E se a
URL criada for requerida, ainda será analisada a fim de obter a rota e os valores
dos parâmetros originais.
```
/index.php?r=post/view&id=100
/index.php/post/100
/posts/100
```
## Formatos de URL <span id="url-formats"></span>
O [[yii\web\UrlManager|gerenciador de URL]] suporta dois formatos de URL: o
formato de URL padrão e o formato de URL amigável (pretty URL).
O formato de URL padrão usa um parâmetro chamado `r` para representar a rota e
os demais parâmetros representam os parâmetros associados a rota. Por exemplo, a
URL `/index.php?r=post/view&id=100` representa a rota `post/view` e o parâmetro
`id` com o valor 100. O formato de URL padrão não exige qualquer tipo de
configuração no [[yii\web\UrlManager|gerenciador de URL]] e trabalha em qualquer
servidor Web.
O formato de URL amigável (pretty URL) usa um caminho adicional após o nome do
script de entrada para representar a rota e seus parâmetros. Por exemplo, o
caminho adicional na URL `/index.php/post/100` é `/post/100`, onde pode
representar, em uma adequada [[yii\web\UrlManager::rules|regra de URL]], a rota
`post/view` e o parâmetro `id` com o valor 100. Para usar o formato de URL
amigável (pretty URL), você precisará escrever um conjunto de
[[yii\web\UrlManager::rules|regras de URLs]] de acordo com a necessidade sobre
como as URLs devem parecer.
Você pode alterar entre os dois formatos de URLs, alternando a propriedade
[[yii\web\UrlManager::enablePrettyUrl|enablePrettyUrl]] do
[[yii\web\UrlManager|gerenciador de URL]] sem alterar qualquer código na aplicação.
## Roteamento <span id="routing"></span>
O roteamento envolve duas etapas. Na primeira etapa, a requisição de entrada é
transformada em uma rota e seus parâmetros. Na segunda etapa, a
[ação do controller (controlador)](structure-controllers.md) correspondente a
rota analisada será criada para processar a requisição.
Ao utilizar o formato de URL padrão, a análise de uma requisição para obter uma
rota é tão simples como pegar o valor via `GET` do parâmetro `r`.
Ao utilizar o formato de URL amigável (pretty URL), o
[[yii\web\UrlManager|gerenciado de URL]] examinará as
[[yii\web\UrlManager::rules|regras de URLs]] registradas para encontrar alguma
correspondência que poderá resolver a requisição em uma rota. Se tal regra não
for encontrada, uma exceção [[yii\web\NotFoundHttpException]] será lançada.
Uma vez que a requisição analisada apresentar uma rota, é hora de criar a ação
do controller (controlador) identificado pela rota.
A rota é dividida em várias partes pelo separador barra (“/”). Por exemplo, a
rota `site/index` será dividida em duas partes: `site` e `index`. Cada parte é
um ID que pode referenciar a um módulo, um controller (controlador) ou uma ação.
A partir da primeira parte da rota, a aplicação executará as seguintes etapas para
criar o módulo (se existir), o controller (controlador) e a ação:
1. Define a aplicação como o módulo atual.
2. Verifica se o [[yii\base\Module::controllerMap|mapa do controller (controlador)]]
do módulo contém o ID atual. Caso exista, um objeto do controller (controlador)
será criado de acordo com a configuração do controller (controlador) encontrado
no mapa e a etapa 3 e 4 não serão executadas.
3. Verifica se o ID referência a um módulo listado na propriedade
[[yii\base\Module::modules|modules]] do módulo atual. Caso exista, um módulo
será criado de acordo com as configurações encontradas na lista e a etapa 2
será executada como etapa seguinte do processo, no âmbito de usar o contexto
do módulo recém-criado.
4. Trata o ID como um ID do controller (controlador) e cria um objeto do controller
(controlador). Siga para a próxima etapa, como parte restante do processo.
5. O controller (controlador) procura o ID atual em seu
[[yii\base\Controller::actions()|mapa de ações]]. Caso exista, será criado uma
ação de acordo com a configuração encontrada no mapa. Caso contrário, o
controller (controlador) tentará criar uma ação inline que é definida por um
método da ação correspondente ao ID atual.
Nas etapas acima, se ocorrer qualquer erro, uma exceção [[yii\web\NotFoundHttpException]]
será lançada, indicando a falha no processo de roteamento.
### Rota Padrão <span id="default-route"></span>
Quando uma requisição analisada apresentar uma rota vazia, a assim chamada
*rota padrão* será usada em seu lugar. A rota padrão é `site/index` é utilizada
como padrão, que referencia a ação `index` do controller (controlador) `site`.
Você pode personalizar esta configuração pela propriedade
[[yii\web\Application::defaultRoute|defaultRoute]] na configuração da aplicação
como mostrado a seguir:
```php
[
// ...
'defaultRoute' => 'main/index',
];
```
### Rota `catchAll` <span id="catchall-route"></span>
Às vezes você pode querer colocar sua aplicação Web em modo de manutenção
temporariamente e exibir uma mesma página com informações para todas as requisições.
Existem muitas maneiras de atingir este objetivo. Mas uma das maneiras mais simples
é apenas configurar a propriedade [[yii\web\Application::catchAll]] na configuração
da aplicação como mostrado a seguir:
```php
[
// ...
'catchAll' => ['site/offline'],
];
```
Na configuração acima, a ação `site/offline` será utilizado para lidar com todas
as requisições recebidas.
A propriedade `catchAll` deve receber um array, o primeiro elemento especifica a
rota e o restante dos elementos (pares de nomes e seus valores) especificam os
parâmetros a serem [associados a ação](structure-controllers.md#action-parameters).
## Criando URLs <span id="creating-urls"></span>
O Yii fornece um método de ajuda [[yii\helpers\Url::to()]] para criar vários tipos
de URLs a partir de determinadas rotas e seus parâmetros. Por exemplo,
```php
use yii\helpers\Url;
// cria uma URL para uma rota: /index.php?r=post/index
echo Url::to(['post/index']);
// cria uma URL para uma rota com parâmetros: /index.php?r=post/view&id=100
echo Url::to(['post/view', 'id' => 100]);
// cria uma URL ancorada: /index.php?r=post/view&id=100#content
echo Url::to(['post/view', 'id' => 100, '#' => 'content']);
// cria uma URL absoluta: http://www.example.com/index.php?r=post/index
echo Url::to(['post/index'], true);
// cria uma URL absoluta usando https: https://www.example.com/index.php?r=post/index
echo Url::to(['post/index'], 'https');
```
Observe que nos exemplos acima, assumimos o formato de URL padrão. Se o formato
de URL amigável (pretty URL) estiver habilitado, as URLs criadas serão diferentes
de acordo com as [[yii\web\UrlManager::rules|regra de URL]] em uso.
A rota passada para o método [[yii\helpers\Url::to()]] é sensível ao contexto.
Ele pode ser tanto uma rota *relativa* quanto uma rota *absoluta* que será
normalizada de acordo com as regras a seguir:
- Se a rota for uma string vazia, a requisição atual [[yii\web\Controller::route|route]] será usada;
- Se a rota não contivér barras (“/”), ele será considerado um ID da ação do
controller (controlador) atual e será antecedido pelo valor da propriedade
[[\yii\web\Controller::uniqueId|uniqueId]] do controller (controlador) atual;
- Se a rota não contivér uma barra (“/”) inicial, será considerado como uma rota
relativa ao módulo atual e será antecedido pelo valor da propriedade
[[\yii\base\Module::uniqueId|uniqueId]] do módulo atual.
A partir da versão 2.0.2, você pode especificar uma rota usando
[alias](concept-aliases.md). Se for este o caso, a alias será a primeira a ser
convertida em uma rota real e em seguida será transformada em uma rota absoluta
de acordo com as regras informadas anteriormente.
Por exemplo, assumindo que o módulo atual é `admin` e o controller (controlador)
atual é `post`,
```php
use yii\helpers\Url;
// rota atual requerida: /index.php?r=admin/post/index
echo Url::to(['']);
// uma rota relativa com apenas o ID da ação: /index.php?r=admin/post/index
echo Url::to(['index']);
// uma rota relativa: /index.php?r=admin/post/index
echo Url::to(['post/index']);
// uma rota absoluta: /index.php?r=post/index
echo Url::to(['/post/index']);
// /index.php?r=post/index assumindo que a alias "@posts" foi definida como "/post/index"
echo Url::to(['@posts']);
```
O método [[yii\helpers\Url::to()]] é implementado através das chamadas dos métodos
[[yii\web\UrlManager::createUrl()|createUrl()]] e
[[yii\web\UrlManager::createAbsoluteUrl()|createAbsoluteUrl()]] do
[[yii\web\UrlManager|gerenciador de URL]].
Nas próximas subseções, iremos explicar como configurar o
[[yii\web\UrlManager|gerenciador de URL]] para personalizar os formatos das URLs criadas.
O método [[yii\helpers\Url::to()]] também suporta a criação de URLs NÃO relacionadas
a uma rota em particular. Neste caso, ao invés de passar um array como seu primeiro
parâmetro, você pode passar uma string. Por exemplo,
```php
use yii\helpers\Url;
// rota atual requerida: /index.php?r=admin/post/index
echo Url::to();
// uma alias da URL: http://example.com
Yii::setAlias('@example', 'http://example.com/');
echo Url::to('@example');
// uma URL absoluta: http://example.com/images/logo.gif
echo Url::to('/images/logo.gif', true);
```
Além do método `to()`, a classe auxiliar [[yii\helpers\Url]] também fornece uma
série de métodos referentes a criação de URLs. Por exemplo,
```php
use yii\helpers\Url;
// URL da página inicial: /index.php?r=site/index
echo Url::home();
// URL base, útil se a aplicação for implementada em uma subpasta da pasta raiz do servidor Web
echo Url::base();
// A URL canônica da requisição atual
// Veja mais detalhes em https://en.wikipedia.org/wiki/Canonical_link_element
echo Url::canonical();
// Obtêm a URL da requisição anterior para reutilizá-la em requisições futuras
Url::remember();
echo Url::previous();
```
## Usando URLs Amigáveis (Pretty URLs) <span id="using-pretty-urls"></span>
Para utilizar as URLs amigáveis (pretty URLs), configure o componente `urlManager`
na configuração da aplicação conforme o exemplo a seguir:
```php
[
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => false,
'rules' => [
// ...
],
],
],
]
```
A propriedade [[yii\web\UrlManager::enablePrettyUrl|enablePrettyUrl]] é obrigatória
para habilitar o formato de URL amigável (pretty URL).
O restante das propriedades são opcionais. No entanto, a configuração utilizada
acima é a mais utilizada.
* [[yii\web\UrlManager::showScriptName|showScriptName]]: esta propriedade determina
se o script de entrada deve ser incluído ou não nas URLs criadas. Por exemplo,
ao invés de criar uma URL `/index.php/post/100`, definindo esta propriedade
como `false`, a URL `/post/100` será gerada.
* [[yii\web\UrlManager::enableStrictParsing|enableStrictParsing]]: esta propriedade
habilita uma análise rigorosa (strict parsing) da requisição. Caso a análise
rigorosa estiver habilitada, a URL da requisição deve corresponder pelo menos
a uma das regras definidas pela propriedade [[yii\web\UrlManager::rules|rules]]
a fim de ser tratado como uma requisição válida, caso contrário a exceção
[[yii\web\NotFoundHttpException]] será lançada. Caso a análise rigorosa estiver
desabilitada, as regras definidas pela propriedade
[[yii\web\UrlManager::rules|rules]] NÃO serão verificadas e as informações
obtidas pela URL serão tratadas como a rota da requisição.
* [[yii\web\UrlManager::rules|rules]]: esta propriedade contém uma lista de
regras especificando como serão analisadas e criadas as URLs. Esta é a principal
propriedade que você deve trabalhar para criar URLs cujos formatos satisfaçam
a sua exigência em particular.
> Observação: A fim de esconder o nome do script de entrada nas URLs criadas,
além de definir a propriedade [[yii\web\UrlManager::showScriptName|showScriptName]]
como `false`, você também pode precisar configurar o seu servidor Web para
identificar corretamente o script PHP quando uma URL da requisição não
especificar um explicitamente. Caso você estejam utilizando um servidor Web
com Apache, você pode consultar a configuração recomendada, conforme descrito
na seção [Installation](start-installation.md#recommended-apache-configuration).
### Regras de URLs <span id="url-rules"></span>
Uma regra de URL é uma instância de [[yii\web\UrlRule]] ou de classes que as estendam.
Cada regra de URL consiste de um padrão usado para combinar as partes do caminho
das URLs, como uma rota e alguns parâmetros. Uma regra de URL pode ser usado para
analisar uma URL da requisição somente se o padrão corresponder com a esta URL.
Uma regra de URL pode ser usada para criar uma URL para corresponder a uma
determinada rota e seus parâmetros.
Quando uma formato de URL amigável (pretty URL) estiver habilitada, o
[[yii\web\UrlManager|gerenciador de URL]] utilizará as regras de URLs declaradas
na propriedade [[yii\web\UrlManager::rules|rules]] para analisar as requisições
e para criar URLs. Em particular, para analisar uma requisição, o
[[yii\web\UrlManager|gerenciador de URL]] verificará as regras na ordem em que
foram declaradas e só enxergará a *primeira* regra que corresponda a URL da
requisição. A regra que foi correspondida é então utilizada para obter a rota e
seus parâmetros a partir de sua análise. A mesma coisa acontece na criação de
URLs, o [[yii\web\UrlManager|gerenciador de URL]] enxergará apenas a primeira
regra que corresponda a rota e seus parâmetros para serem utilizados na criação
de uma URL.
Você pode configurar a propriedade [[yii\web\UrlManager::rules]] com um array
composto de pares de chave-valor, onde a chave é o padrão da regra e o valor
serão as rotas. Cada par de padrão-rota define uma regra de URL. Por exemplo,
as [[yii\web\UrlManager::rules|regras]] a seguir configuram duas regras de URL.
A primeira regra corresponde a uma URL chamada `posts` sendo mapeado para utilizar
a rota `post/index`.
A segunda regra corresponde a uma URL que combine com expressão regular
`post/(\d+)` seguido de um parâmetro chamado `id` sendo mapeado para utilizar a
rota `post/view`.
```php
[
'posts' => 'post/index',
'post/<id:\d+>' => 'post/view',
]
```
> Informação: O padrão em uma regra é usado para identificar o caminho de uma URL.
Por exemplo, o caminho da URL `/index.php/post/100?source=ad` é `post/100`
(as barras (“/”) iniciais e finais serão ignoradas) combinando com o padrão `post/(\d+)`.
Além de declarar regras de URL como pares de padrão-rota, você também pode declarar
como array. Cada array é utilizado para configurar um único objeto da regra de URL.
Isto se faz necessário quando você deseja configurar outras propriedades de uma
regra de URL. Por exemplo,
```php
[
// ...outras regras de URL...
[
'pattern' => 'posts',
'route' => 'post/index',
'suffix' => '.json',
],
]
```
Por padrão, se você não especificar a opção `class` na configuração de uma regra,
será utilizado a classe [[yii\web\UrlRule]].
### Parâmetros Nomeados <span id="named-parameters"></span>
Uma regra de URL pode ser associado a alguns parâmetros nomeados que são
especificados no padrão `<ParamName:RegExp>`, onde o `ParamName` especifica o
nome do parâmetro e o `RegExp` especifica uma expressão regular opcional usada
para corresponder ao valor do parâmetro. Se o `RegExp` são for especificado,
significará que o valor do parâmetro será uma string sem barras (“/”).
> Observação: Você apenas pode especificar expressões regulares para os parâmetros.
As demais partes de um padrão serão considerados como um texto simples.
Quando esta regra for utilizada para analisar uma URL, os parâmetros associados
serão preenchidos com os valores que foram correspondidos pela regra e estes
parâmetros serão disponibilizados logo a seguir no `$_GET` pelo componente da
aplicação `request`.
Vamos utilizar alguns exemplos para demonstrar como os parâmetros nomeados
funcionam. Supondo que declaramos as três regras a seguir:
```php
[
'posts/<year:\d{4}>/<category>' => 'post/index',
'posts' => 'post/index',
'post/<id:\d+>' => 'post/view',
]
```
Quando as regras forem utilizadas para analisar as URLs:
- `/index.php/posts` obterá a rota `post/index` usando a segunda regra;
- `/index.php/posts/2014/php` obterá a rota `post/index`, o parâmetro `year`
cujo o valor é 2014 e o parâmetro `category` cujo valor é `php` usando a primeira regra;
- `/index.php/post/100` obterá a rota `post/view` e o parâmetro `id` cujo valor
é 100 usando a terceira regra;
- `/index.php/posts/php` causará uma exceção [[yii\web\NotFoundHttpException]]
quando a propriedade [[yii\web\UrlManager::enableStrictParsing]] for `true`,
por não ter correspondido a nenhum dos padrões. Se a propriedade
[[yii\web\UrlManager::enableStrictParsing]] for `false` (o valor padrão), o
caminho `posts/php` será retornado como uma rota.
E quando as regras fores utilizadas para criar as URLs:
- `Url::to(['post/index'])` cria `/index.php/posts` usando a segunda regra;
- `Url::to(['post/index', 'year' => 2014, 'category' => 'php'])` cria `/index.php/posts/2014/php` usando a primeira regra;
- `Url::to(['post/view', 'id' => 100])` cria `/index.php/post/100` usando a terceira regra;
- `Url::to(['post/view', 'id' => 100, 'source' => 'ad'])` cria `/index.php/post/100?source=ad` usando a terceira regra.
Pela razão do parâmetro `source` não foi especificado na regra, ele será acrescentado como uma query string na criação da URL.
- `Url::to(['post/index', 'category' => 'php'])` cria `/index.php/post/index?category=php` usando nenhuma das regras.
Observe que, se nenhuma das regras forem aplicadas, a URL será criada simplesmente
como a rota sendo o caminho e todos os parâmetros como query string.
### Parametrizando Rotas <span id="parameterizing-routes"></span>
Você pode incorporar nomes de parâmetros na rota de uma regra de URL. Isto permite
que uma regra de URL seja utilizada para combinar diversas rotas. Por exemplo, a
regra a seguir incorpora os parâmetros `controller` e `action` nas rotas.
```php
[
'<controller:(post|comment)>/<id:\d+>/<action:(create|update|delete)>' => '<controller>/<action>',
'<controller:(post|comment)>/<id:\d+>' => '<controller>/view',
'<controller:(post|comment)>s' => '<controller>/index',
]
```
Para analisar uma URL `/index.php/comment/100/create`, a primeira regra será
aplicada, na qual foi definida o parâmetro `controller` para ser `comment` e o
parâmetro `action` para ser `create`. Sendo assim, a rota `<controller>/<action>`
é resolvida como `comment/create`.
De forma similar, para criar uma URL com a rota `comment/index`, a terceira regra
será aplicada, criando um URL `/index.php/comments`.
> Informação: Pela parametrização de rotas, é possível reduzir significativamente
o número de regras de URL, que também pode melhorar o desempenho do
[[yii\web\UrlManager|gerenciador de URL]].
Por padrão, todos os parâmetros declarados nas regras são obrigatórios. Se uma
URL da requisição não contiver um dos parâmetros em particular, ou se a URL está
sendo criado sem um dos parâmetros em particular, a regra não será aplicada. Para
fazer com que algum parâmetro em particular seja opcional, você pode configurar
a propriedade [[yii\web\UrlRule::defaults|defaults]] da regra. Os parâmetros
listados nesta propriedade são opcionais e serão utilizados quando os mesmos não
forem fornecidos.
A declaração da regra a seguir, ambos os parâmetros `page` e `tag` são opcionais
e utilizarão o valor 1 e a string vazia, respectivamente, quando não forem fornecidos.
```php
[
// ...outras regras...
[
'pattern' => 'posts/<page:\d+>/<tag>',
'route' => 'post/index',
'defaults' => ['page' => 1, 'tag' => ''],
],
]
```
A regra anterior pode ser usado para analisar ou criar qualquer uma das seguintes URLs:
* `/index.php/posts`: `page` é 1, `tag` é ''.
* `/index.php/posts/2`: `page` é 2, `tag` is ''.
* `/index.php/posts/2/news`: `page` é 2, `tag` é `'news'`.
* `/index.php/posts/news`: `page` é 1, `tag` é `'news'`.
Sem o uso dos parâmetros opcionais, você deveria criar 4 regras para alcançar o
mesmo resultado.
### Regras com Domínios <span id="rules-with-server-names"></span>
É possível incluir domínios nos padrões das regras de URL. Isto é útil quando sua
aplicação se comporta de forma diferente em diferentes domínios. Por exemplo, a
regra a seguir obtém a rota `admin/user/login` pela análise da URL
`http://admin.example.com/login` e a rota `site/login` pela análise da URL
`http://www.example.com/login`.
```php
[
'http://admin.example.com/login' => 'admin/user/login',
'http://www.example.com/login' => 'site/login',
]
```
Você também pode incorporar parâmetros nos domínios para extrair informações
dinamicamente a partir deles. Por exemplo, a regra a seguir obtém a rota
`post/index` e o parâmetro `language=en` pela análise da URL `http://en.example.com/posts`
```php
[
'http://<language:\w+>.example.com/posts' => 'post/index',
]
```
> Observação: Regras com domínios NÃO devem ser incluídos com subpastas do script
de entrada em seus padrões. Por exemplo, se a aplicação estiver sob
`http://www.example.com/sandbox/blog`, você deve usar o padrão
`http://www.example.com/posts` ao invés de `http://www.example.com/sandbox/blog/posts`.
Isto permite que sua aplicação seja implantado sob qualquer diretório sem a
necessidade de alterar o código da aplicação.
### Sufixos da URL <span id="url-suffixes"></span>
Você pode querer adicionar sufixos nas URLs para diversos fins. Por exemplo,
você pode adicionar o `.html` nas URLs para que se pareçam com páginas estáticas.
Você também pode adicionar o `.json` nas URLs para indicar o tipo de conteúdo
esperado na resposta. Você pode alcançar este objetivo configurando a propriedade
[[yii\web\UrlManager::suffix]] na configuração da aplicação conforme o exemplo a seguir:
```php
[
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => true,
'suffix' => '.html',
'rules' => [
// ...
],
],
],
]
```
A configuração anterior permitirá que o [[yii\web\UrlManager|gerenciador de URL]]
reconheçam as URLs solicitadas e que também criem URLs com o prefixo `.html`.
> Dica: Você pode definir `/` como o sufixo para que todas as URLs terminem com barra.
> Observação: Ao configurar um sufixo da URL e a URL da requisição não conter um,
será considerado como uma URL não válida. Isto é uma prática recomendada no
SEO (otimização para mecanismos de pesquisa, do *inglês search engine optimization*).
Ás vezes você poder querer utilizar diferentes sufixos para diferentes URLs.
Isto pode ser alcançado pela configuração da propriedade
[[yii\web\UrlRule::suffix|suffix]] individualmente para cada regra de URL.
Quando uma regra de URL possuir esta propriedade definida, sobrescreverá o
sufixo que foi definido da camada do [[yii\web\UrlManager|gerenciador de URL]].
Por exemplo, a configuração a seguir contém uma regra de URL personalizada que
usa o `.json` como sufixo ao invés do sufixo `.html` definido globalmente.
```php
[
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => true,
'suffix' => '.html',
'rules' => [
// ...
[
'pattern' => 'posts',
'route' => 'post/index',
'suffix' => '.json',
],
],
],
],
]
```
### Métodos HTTP <span id="http-methods"></span>
Ao implementar RESTful API, é necessário que sejam obtidas rotas diferentes pela
análise de uma mesma URL de acordo com o método HTTP utilizado. Isto pode ser
alcançado facilmente adicionando o prefixo do método HTTP suportado, separando
os nomes dos métodos por vírgulas. Por exemplo, a regra a seguir possui o mesmo
padrão `post/<id:\d+>` com suporte a diferentes métodos HTTP. A análise de uma
requisição `PUT post/100` obterá a rota `post/create`, enquanto a requisição
`GET post/100` obterá a rota `post/view`.
```php
[
'PUT,POST post/<id:\d+>' => 'post/create',
'DELETE post/<id:\d+>' => 'post/delete',
'post/<id:\d+>' => 'post/view',
]
```
> Observação: Se uma regra de URL contiver método(s) HTTP, esta regra só será
utilizada para análises de URLs. A regra será ignorada quando o
[[yii\web\UrlManager|gerenciador de URL]] for chamado para criar URLs.
> Dica: Para simplificar o roteamento do RESTful APIs, o Yii fornece uma classe
especial [[yii\rest\UrlRule]] de regras que é muito diferente. Esta classe
suporta muitos recursos como a pluralização automática de IDs do controller
(controlador). Para mais detalhes, por favor, consulte a seção
[Routing](rest-routing.md) sobre o desenvolvimento de RESTful APIs.
### Regras Personalizadas <span id="customizing-rules"></span>
Nos exemplo anteriores, as regras de URL são declaradas principalmente no formato
de pares de padrão-rota. Este é um formato de atalho bastante utilizado. Em
alguns cenários, você pode querer personalizar uma regra de URL configurando
outras propriedades, tais como o [[yii\web\UrlRule::suffix]]. Isto pode ser
feito utilizando um array de configuração para especificar uma regra. O exemplo
a seguir foi retirado da subseção [Sufixos da URL](#url-suffixes),
```php
[
// ...outras regras de URL...
[
'pattern' => 'posts',
'route' => 'post/index',
'suffix' => '.json',
],
]
```
> Informações: Por padrão, se você não especificar a opção `class` na configuração
de uma regra, será usado como padrão a classe [[yii\web\UrlRule]].
### Adicionando Regras Dinamicamente <span id="adding-rules"></span>
As regras de URL podem ser adicionadas dinamicamente ao [[yii\web\UrlManager|gerenciador de URL]].
Esta técnica muitas vezes se faz necessária em [módulos](structure-modules.md) que
são redistribuídos e que desejam gerenciar as suas próprias regras de URL. Para
que estas regras sejam adicionadas dinamicamente e terem efeito durante o processo
de roteamento, você pode adiciona-los durante a [inicialização (bootstrapping)](runtime-bootstrapping.md).
Para os módulos, significa que deve implementar a interface [[yii\base\BootstrapInterface]]
e adicionar as regras no método [[yii\base\BootstrapInterface::bootstrap()|bootstrap()]]
conforme o exemplo a seguir:
```php
public function bootstrap($app)
{
$app->getUrlManager()->addRules([
// declare as regras aqui
], false);
}
```
Observe que você também deve listar estes módulos no [[yii\web\Application::bootstrap]]
para que eles sejam usados no processo de [inicialização (bootstrapping)](runtime-bootstrapping.md)
### Criando Classes de Regras <span id="creating-rules"></span>
Apesar do fato que a classe padrão [[yii\web\UrlRule]] é flexível o suficiente
para a maior parte dos projetos, há situações em que você terá que criar a sua
própria classe de regra. Por exemplo, em um site de venda de carros, você pode
querer dar suporte a um formato de URL como `/Manufacturer/Model`, que tanto o
`Manufacturer` quanto o `Model` devem coincidir com os dados armazenados em uma
tabela do banco de dados. A classe de regra padrão não vai funcionar nesta
situação pois vão se basear em padrões estaticamente declarados.
Podemos criar uma classe de regra de URL para resolver este formato.
```php
namespace app\components;
use yii\web\UrlRuleInterface;
use yii\base\Object;
class CarUrlRule extends Object implements UrlRuleInterface
{
public function createUrl($manager, $route, $params)
{
if ($route === 'car/index') {
if (isset($params['manufacturer'], $params['model'])) {
return $params['manufacturer'] . '/' . $params['model'];
} elseif (isset($params['manufacturer'])) {
return $params['manufacturer'];
}
}
return false; // esta regra não se aplica
}
public function parseRequest($manager, $request)
{
$pathInfo = $request->getPathInfo();
if (preg_match('%^(\w+)(/(\w+))?$%', $pathInfo, $matches)) {
// checa o $matches[1] e $matches[3] para verificar
// se coincidem com um *fabricante* e um *modelo* no banco de dados.
// Caso coincida, define o $params['manufacturer'] e/ou $params['model']
// e retorna ['car/index', $params]
}
return false; // esta regra não se aplica
}
}
```
E utilize esta nova classe de regra na configuração [[yii\web\UrlManager::rules]]:
```php
[
// ...outras regras...
[
'class' => 'app\components\CarUrlRule',
// ...configurar outras propriedades...
],
]
```
## Considerando Performance <span id="performance-consideration"></span>
Ao desenvolver uma aplicação Web complexa, é importante otimizar as regras de URL
para que leve menos tempo na análise de requisições e criação de URLs.
Utilizando rotas parametrizadas, você reduz o número de regras de URL, na qual
pode melhorar significativamente o desempenho.
Na análise e criação de URLs, o [[yii\web\UrlManager|gerenciador de URL]] examina
as regras de URL na ordem em que foram declaradas.
Portanto, você pode considerar ajustar a ordem destas regras, fazendo com que as
regras mais específicas e/ou mais comuns sejam colocadas antes que os menos.
Se algumas regras de URL compartilharem o mesmo prefixo em seus padrões ou rotas,
você pode considerar utilizar o [[yii\web\GroupUrlRule]] para que sejam examinados
de forma mais eficiente pelo [[yii\web\UrlManager|gerenciador de URL]] como um
grupo. Normalmente é o caso de aplicações compostos por módulos, onde cada módulo
possui o seu próprio conjunto de regras de URL utilizando o ID do módulo como
prefixo comum.

1
docs/guide-pt-BR/start-forms.md

@ -29,6 +29,7 @@ detalhes sobre convenção de nomenclatura dos arquivos de classes.
namespace app\models;
use Yii;
use yii\base\Model;
class EntryForm extends Model

6
docs/guide-pt-BR/start-gii.md

@ -1,7 +1,7 @@
Gerando Código com Gii
========================
Essa seção irá descrever como usar o [Gii](tool-gii.md) para automaticamente gerar código que implementa algumas funcionalidades comuns de sites. Usar o Gii para gerar código é simples, trata-se apenas de uma questão de entrar com as informações corretas de acordo com as instruções mostradas nas páginas do Gii.
Essa seção irá descrever como usar o [Gii](https://github.com/yiisoft/yii2-gii/blob/master/docs/guide-pt-BR/README.md) para automaticamente gerar código que implementa algumas funcionalidades comuns de sites. Usar o Gii para gerar código é simples, trata-se apenas de uma questão de entrar com as informações corretas de acordo com as instruções mostradas nas páginas do Gii.
Através desse tutorial, você irá aprender a:
@ -14,7 +14,7 @@ Através desse tutorial, você irá aprender a:
Começando a usar o Gii <span id="starting-gii"></span>
------------
O [Gii](tool-gii.md) é fornecido com o Yii como um [módulo](structure-modules.md). Você pode habilitar o Gii ao configurá-lo na propriedade [[yii\base\Application::modules|modules]] da aplicação. Dependendo de como você criou sua aplicação, você pode já encontrar o seguinte código no arquivo de configuração `config/web.php`:
O [Gii](https://github.com/yiisoft/yii2-gii/blob/master/docs/guide-pt-BR/README.md) é fornecido com o Yii como um [módulo](structure-modules.md). Você pode habilitar o Gii ao configurá-lo na propriedade [[yii\base\Application::modules|modules]] da aplicação. Dependendo de como você criou sua aplicação, você pode já encontrar o seguinte código no arquivo de configuração `config/web.php`:
```php
$config = [ ... ];
@ -116,7 +116,7 @@ Essa é uma lista de arquivos gerados pelo Gii, caso você queira investigar com
* Modelo: `models/Country.php` e `models/CountrySearch.php`
* Views: `views/country/*.php`
> Informação: o Gii é projetado para ser uma ferramenta altamente adaptável e extensível. Usando-o sabiamente, você irá acelerar o desenvolvimento da sua aplicação. Para mais detalhes, por favor siga para a seção [Gii](tool-gii.md).
> Informação: o Gii é projetado para ser uma ferramenta altamente adaptável e extensível. Usando-o sabiamente, você irá acelerar o desenvolvimento da sua aplicação. Para mais detalhes, por favor siga para a seção [Gii](https://github.com/yiisoft/yii2-gii/blob/master/docs/guide-pt-BR/README.md).
Resumo <span id="summary"></span>

4
docs/guide-pt-BR/start-hello.md

@ -62,7 +62,7 @@ trata os IDs de ações. Os IDs das ações são sempre referenciados em minúsc
Se o ID de uma ação necessitar de múltiplas palavras, elas serão concatenadas
por hífens (por exemplo, `create-comment`). Os nomes de métodos de ações são mapeados
para os IDs das ações removendo-se os hífens dos IDs, colocando em maiúsculo a
primeira letra de cada palavra, e prefixando o resultado com `action`. Por exemplo,
primeira letra de cada palavra, e prefixando o resultado com a palavra `action`. Por exemplo,
o ID de ação `create-comment` corresponde ao método de ação `actionCreateComment`.
O método de ação em nosso exemplo recebe um parâmetro `$message`, cujo valor
@ -86,7 +86,7 @@ Criando uma Visão <span id="creating-view"></span>
As [visões](structure-views.md) são scripts que você escreve para gerar o conteúdo
de uma resposta. Para a tarefa "Hello", você criará uma visão `say` que imprime o
parâmetro `message` recebido do método da ação, e passado pela ação para a visão:
parâmetro `message` recebido do método da ação:
```php
<?php

24
docs/guide-pt-BR/start-installation.md

@ -1,27 +1,27 @@
Instalando o Yii
================
Você pode instalar o Yii de duas maneiras, usando o [Composer](http://getcomposer.org/)
Você pode instalar o Yii de duas maneiras, usando o gerenciador de pacotes [Composer](https://getcomposer.org/)
ou baixando um arquivo compactado. O primeiro modo é o preferido, já que permite
que você instale novas [extensões](structure-extensions.md) ou atualize o
Yii simplesmente executando um único comando.
A instalação do Yii padrão resulta no download e instalação tanto do framework
quanto de um template de aplicação.
Um template de aplicação é uma aplicação do Yii implementando algumas recursos básicos,
quanto de um template de projetos.
Um template de projetos é uma aplicação do Yii implementando algumas recursos básicos,
como a autenticação, o formulário de contato, etc.
Este código é organizado de uma forma recomendada. No entanto, ele pode servir
como ponto de partida para seus projetos.
Nesta e nas próximas seções, iremos descrever como instalar o *Template Básico de
Aplicação* do Yii e como implementar novas funcionalidades em cima deste template.
O Yii também fornece um outro template chamado de [Template Avançado de Aplicação](tutorial-advanced-app.md) que é melhor usado em uma equipe de desenvolvimento que desenvolvem
Nesta e nas próximas seções, iremos descrever como instalar o *Template Básico
de Projetos* do Yii e como implementar novas funcionalidades em cima deste template.
O Yii também fornece um outro template chamado de [Template Avançado de Projetos](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide-pt-BR/README.md) que é melhor usado em uma equipe de desenvolvimento que desenvolvem
aplicações de multiplas camadas.
> Informação: O Template Básico de Aplicação é adequado para o desenvolvimento de
> Informação: O Template Básico de Projetos é adequado para o desenvolvimento de
cerca de 90% das aplicações Web. Este template difere do Template Avançado de
Aplicação principalmente na forma de como o seu código é organizado. Se você é
novo no Yii, recomendamos fortemente em escolher o Template Básico de Aplicação
Projetos principalmente na forma de como o seu código é organizado. Se você é
novo no Yii, recomendamos fortemente em escolher o Template Básico de Projetos
pela sua simplicidade além de ter funcionalidades o suficiente.
@ -32,7 +32,7 @@ Se você já não tiver o Composer instalado, você pode fazê-lo seguindo as in
em [getcomposer.org](https://getcomposer.org/download/). No Linux e no Mac OS X,
você executará os seguintes comandos:
curl -s http://getcomposer.org/installer | php
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
No Windows, você baixará e executará o [Composer-Setup.exe](https://getcomposer.org/Composer-Setup.exe).
@ -46,7 +46,7 @@ Você pode atualizar o Composer executando o comando `composer self-update`.
Com o Composer instalado, você pode instalar o Yii executando o seguinte comando
em um diretório acessível pela Web:
composer global require "fxp/composer-asset-plugin:1.0.0"
composer global require "fxp/composer-asset-plugin:~1.0.0"
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
O primeiro comando instaka o [composer asset plugin](https://github.com/francoispluchino/composer-asset-plugin/)
@ -101,7 +101,7 @@ No entanto, existem outras opções de instalação disponíveis:
[Construindo uma Aplicação a Partir do Zero](tutorial-start-from-scratch.md).
* Se você quiser começar com uma aplicação mais sofisticada, mais adequada ao
ambiente de desenvolvimento de equipes, você pode considerar instalar o
[Modelo de Aplicação Avançada](tutorial-advanced-app.md).
[Template Avançado de Projetos](https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide-pt-BR/README.md).
Verificando a Instalação <span id="verifying-installation"></span>

10
docs/guide-pt-BR/start-workflow.md

@ -9,15 +9,19 @@ em geral.
> Info: Por questões de simplicidade, por todo este tutorial de "Primeiros Passos"
assume-se que você definiu `basic/web` como a raiz de documentos do seu
servidor Web, e configurou a URL de acesso de sua aplicação como `http://hostname/index.php`
servidor Web e configurou a URL de acesso de sua aplicação como `http://hostname/index.php`
ou algo semelhantes. Por favor ajuste as URLs em nossas descrições às suas
necessidades.
Observe que ao contrário do próprio framework, após a instalação de um dos templates
de projetos, você está livre para adicionar, remover ou sobrescrever qualquer código
que precisar.
Funcionalidade <span id="functionality"></span>
--------------
A aplicação básica instalada contém quatro páginas:
O template básico de projetos instalado contém quatro páginas:
* A página inicial, exibida quando você acessa a URL `http://hostname/index.php`,
* a página "About" (Sobre),
@ -38,7 +42,7 @@ status de respostas, as consultas de banco de dados executadas, e assim por dian
Além da aplicação Web, existe um script console chamado `yii`, que está localizado
na pasta base da aplicação.
Este script pode ser usado para executar rotinas em segundo plano e tarefas de
manutenção da aplicação, descritas na [seção Comandos de Console](tutoral-console.md).
manutenção da aplicação, descritas na [seção Comandos de Console](tutorial-console.md).
Estrutura da Aplicação <span id="application-structure"></span>
----------------------

38
docs/guide-pt-BR/structure-applications.md

@ -67,7 +67,7 @@ caracteres alfanuméricos ao especificar um ID de aplicação.
A propriedade [[yii\base\Application::basePath|basePath]] especifica o diretório
raiz de um sistema. É o diretório que contém todo o código fonte protegido de um
sistema. Sob este diretório, você normalmente verá subdiretórios tais como
`models`, `views`, `controllers`, que contém o código fonte correspondente ao
`models`, `views` e `controllers`, que contém o código fonte correspondente ao
padrão MVC.
Você pode configurar a propriedade [[yii\base\Application::basePath|basePath]]
@ -92,7 +92,7 @@ configuradas porque elas variam em diferentes aplicações.
Esta propriedade permite que você defina um conjunto de
[aliases](concept-aliases.md) em termos de um array. As chaves do array representam
os nomes de alias, e os valores são as definições correspondentes. Por exemplo,
os nomes de alias, e os valores são as definições correspondentes. Por exemplo:
```php
[
@ -103,8 +103,8 @@ os nomes de alias, e os valores são as definições correspondentes. Por exempl
]
```
Essa propriedade está disponível de modo que você possa definir aliases em termos
de configurações da aplicação ao invés de chamadas ao método [[Yii::setAlias()]].
Esta propriedade é fornecida para que você possa definir aliases na configuração
da aplicação ao invés de chamar o método [[Yii::setAlias()]].
#### [[yii\base\Application::bootstrap|bootstrap]] <span id="bootstrap"></span>
@ -124,7 +124,7 @@ seguintes formatos:
- um array de configuração.
- uma função anônima que cria e retorna um componente.
Por exemplo,
Por exemplo:
```php
[
@ -166,9 +166,9 @@ Durante o processo de inicialização, cada componente será instanciado. Se a c
do componente implementa [[yii\base\BootstrapInterface]], seu método [[yii\base\BootstrapInterface::bootstrap()|bootstrap()]]
também será chamado.
Outro exemplo prático está na configuração do [Modelo Básico de Aplicação](start-installation.md),
Outro exemplo prático está na configuração do [Template Básico de Projetos](start-installation.md),
onde os módulos `debug` e `gii` estão configurados como componentes de inicialização
quando a aplicação está rodando no ambiente de desenvolvimento,
quando a aplicação está rodando no ambiente de desenvolvimento:
```php
if (YII_ENV_DEV) {
@ -196,7 +196,7 @@ em modo de manutenção e precisa tratar todas as requisições através de uma
A configuração é um array, cujo primeiro elemento especifica a rota para a action.
O restante dos elementos do array (pares de chave-valor) especificam os parâmetros
que devem ser atrelados à action. Por exemplo,
que devem ser atrelados à action. Por exemplo:
```php
[
@ -213,7 +213,7 @@ que devem ser atrelados à action. Por exemplo,
Essa é a propriedade mais importante. Ela permite que você registre uma lista
de componentes chamados [componentes de aplicação](structure-application-components.md)
que você pode usar em outros lugares. Por exemplo,
que você pode usar em outros lugares. Por exemplo:
```php
[
@ -284,7 +284,7 @@ diretório correspondente ao namespace. Por exemplo, dado um ID de controller
É importante que as classes completas e qualificadas possam ser [carregadas automaticamente](concept-autoloading.md)
e que o namespace das suas classes de controller correspondam ao valor dessa
propriedade. Doutra forma, você receberia um erro "Página Não Encontrada" ao
propriedade. Doutra forma, você receberia um erro de "Página Não Encontrada" ao
acessar a aplicação.
Caso você queira quebrar a convenção conforme descrito acima, você pode configurar
@ -318,7 +318,7 @@ Essa propriedade especifica os [módulos](structure-modules.md) que uma aplicaç
contém.
A propriedade recebe um array de classes de módulos ou [configurações](concept-configurations.md)
com as chaves do array sendo os IDs dos módulos. Por exemplo,
com as chaves do array sendo os IDs dos módulos. Por exemplo:
```php
[
@ -401,7 +401,7 @@ Essa propriedade é disponibilizada como uma maneira alternativa de definir a
timezone do PHP em tempo de execução. Ao confiugrar essa propriedade, você está
essencialmente chamando a função
[date_default_timezone_set()](http://php.net/manual/en/function.date-default-timezone-set.php)
do PHP. Por exemplo,
do PHP. Por exemplo:
```php
[
@ -413,8 +413,8 @@ do PHP. Por exemplo,
#### [[yii\base\Application::version|version]] <span id="version"></span>
Essa propriedade especifica a versão da aplicação. Seu valor padrão é `'1.0'`.
Você nem sempre precisa configurar essa propriedade se nenhuma parte do seu código
a está usando.
Você não precisa configurar esta propriedade se nenhuma parte do seu código
estiver utilizando-a.
### Propriedades Úteis <span id="useful-properties"></span>
@ -457,7 +457,7 @@ informação de ajuda.
Essa propriedade especifica a lista de [extensões](structure-extensions.md) que
estão instaladas e são usadas pela aplicação. Por padrão, ela receberá o array
retornado pelo arquivo `@vendor/yiisoft/extensions.php`. O arquivo `extensions.php`
é gerado e mantido automaticamente quando você usa o [Composer](http://getcomposer.org)
é gerado e mantido automaticamente quando você usa o [Composer](https://getcomposer.org)
para instalar extensões. Então na maioria dos casos você não precisa configurar
essa propriedade.
@ -543,7 +543,7 @@ caminho.
#### [[yii\base\Application::vendorPath|vendorPath]] <span id="vendorPath"></span>
Essa propriedade especifica o diretório vendor gerenciado pelo [Composer](http://getcomposer.org).
Essa propriedade especifica o diretório vendor gerenciado pelo [Composer](https://getcomposer.org).
Ele contém todas as bibliotecas de terceiros usadas pela sua aplicação, incluindo
o framework do Yii. O valor padrão é o diretório representado pelo alias `@app/vendor`.
@ -581,7 +581,7 @@ A sintaxe de uso de `on eventName` é descrita na seção
Alternativamente, você pode vincular manipuladores de evento durante o
[processo de inicialização](runtime-bootstrapping.md) após a instância da aplicação
ser criada. Por exemplo,
ser criada. Por exemplo:
```php
\Yii::$app->on(\yii\base\Application::EVENT_BEFORE_REQUEST, function ($event) {
@ -622,7 +622,7 @@ O nome do evento é `beforeAction`.
O parâmetro do evento é uma instância de [[yii\base\ActionEvent]]. Um manipulador
de evento pode definir o valor da propriedade [[yii\base\ActionEvent::isValid]]
como `false` para interromper a execução da action. Por exemplo,
como `false` para interromper a execução da action. Por exemplo:
```php
[
@ -649,7 +649,7 @@ O nome do evento é `afterAction`.
O parâmetro do evento é uma instância de [[yii\base\ActionEvent]]. Através da
propriedade [[yii\base\ActionEvent::result]], um manipulador de evento pode
acessar ou modificar o resultado da action. Por exemplo,
acessar ou modificar o resultado da action. Por exemplo:
```php
[

6
docs/guide-pt-BR/structure-assets.md

@ -33,7 +33,7 @@ especificado onde os asset estão localizados, quais arquivos CSS e JavaScript
possuem e como o bundle depende de outro bundles.
O código a seguir define o asset bundle principal que é usado pelo
[template básico de aplicação](start-installation.md):
[template básico de projetos](start-installation.md):
```php
<?php
@ -343,8 +343,8 @@ nomes das classes (sem a barra invertida) dos asset bundles e os valores do
array devem corresponder aos [arrays de configuração](concept-configurations.md).
> Dica: Você pode, de forma condicional, escolher os assets que queira usar em
um asset bundle. O exemplo a seguir mostra como usar o `jquery.js` no ambiente
de desenvolvimento e o `jquery.min.js` em outra situação:
> um asset bundle. O exemplo a seguir mostra como usar o `jquery.js` no ambiente
> de desenvolvimento e o `jquery.min.js` em outra situação:
>
> ```php
> 'yii\web\JqueryAsset' => [

53
docs/guide-pt-BR/structure-controllers.md

@ -119,7 +119,7 @@ Por exemplo, você pode usar o `article` como o ID do um controller para tratar
dados de artigos.
Por padrão, os IDs dos controllers devem conter apenas esses caracteres:
letras inglesas em caixa baixa, números, underscores (underline), traços e barras.
letras inglesas em caixa baixa, números, underscores (underline), hífens e barras.
Por exemplo, `article` e `post-comment` são ambos IDs de controllers válidos,
enquanto `article?`, `PostComment`, `admin\post` não são.
@ -134,22 +134,22 @@ barras são usadas para separar os níveis dos subdiretórios (por exemplo, `pan
### Nomenclatura da Classe do Controller <span id="controller-class-naming"></span>
Os nomes da classes dos controllers podem ser derivadas dos IDs dos controllers
de acordo com as seguintes regras:
de acordo com as seguintes procedimentos:
* Colocar em caixa alta a primeira letra de cada palavra separadas por traço.
Observe que se o ID do controller possuir barras, a regra é aplicada apenas na
parte após a última barra no ID.
* Remover os traços e substituir todas as barras por barras invertidas.
* Adicionar `Controller` como sufixo.
* E preceder ao [[yii\base\Application::controllerNamespace|namespace controller]].
1. Colocar em caixa alta a primeira letra de cada palavra separadas por traço.
Observe que se o ID do controller possuir barras, a regra é aplicada apenas na
parte após a última barra no ID.
2. Remover os traços e substituir todas as barras por barras invertidas.
3. Adicionar `Controller` como sufixo.
4. Preceder ao [[yii\base\Application::controllerNamespace|namespace do controller]].
Segue alguns exemplos, assumindo que o [[yii\base\Application::controllerNamespace|namespace do controller]]
tenha por padrão o valor `app\controllers`:
* `article` deriva-se de `app\controllers\ArticleController`;
* `post-comment` deriva-se de `app\controllers\PostCommentController`;
* `admin/post-comment` deriva-se de `app\controllers\admin\PostCommentController`;
* `adminPanels/post-comment` deriva-se de `app\controllers\adminPanels\PostCommentController`.
* `article` torna-se `app\controllers\ArticleController`;
* `post-comment` torna-se `app\controllers\PostCommentController`;
* `admin/post-comment` torna-se `app\controllers\admin\PostCommentController`;
* `adminPanels/post-comment` torna-se `app\controllers\adminPanels\PostCommentController`.
As classes dos controllers devem ser [autoloadable](concept-autoloading.md).
Por esta razão, nos exemplos anteriores, o controller `article` deve ser salvo
@ -165,11 +165,11 @@ categorias e não quiser usar [módulos](structure-modules.md).
Você pode configurar um [[yii\base\Application::controllerMap|mapeamento de controllers]]
para superar as barreiras impostas pelos IDs de controllers e pelos nomes de classes
descritos acima. Isto é útil principalmente quando quiser esconder alguns controllers
descritos acima. Isto é útil principalmente quando quiser esconder controllers
de terceiros na qual você não tem controle sobre seus nomes de classes.
Você pode configurar o [[yii\base\Application::controllerMap|mapeamento de controllers]]
na [configuração da aplicação](structure-applications.md#application-configurations) como o seguinte exemplo:
na [configuração da aplicação](structure-applications.md#application-configurations). Por exemplo:
```php
[
@ -194,8 +194,7 @@ Quando uma requisição não especificar uma [rota](#id-da-rota), será utilizad
rota especificada pela propriedade.
Para as [[yii\web\Application|aplicações Web]], este valor é `'site'`, enquanto
para as [[yii\console\Application|aplicações console]] é `help`. Portanto, se uma
URL `http://hostname/index.php` for usada, significa que o controller `site` será
usado nesta requisição.
URL for `http://hostname/index.php`, o controller `site` será utilizado nesta requisição.
Você pode alterar o controller padrão como a seguinte [configuração da aplicação](structure-applications.md#application-configurations):
@ -240,13 +239,13 @@ um recurso. Por esta razão, os IDs das ações geralmente são verbos, tais com
Por padrão, os IDs das ações devem conter apenas esses caracteres: letras inglesas
em caixa baixa, números, underscores (underline) e traços. Os traços em um ID da
ação são usados para separar palavras. Por exemplo, `view`, `update2`, `comment-post`
todos são IDs válidos, enquanto `view?`, `Update` não são.
ação são usados para separar palavras. Por exemplo, `view`, `update2` e `comment-post`
são IDs válidos, enquanto `view?` e `Update` não são.
Você pode criar ações de duas maneiras: ações inline (em sequência) e
ações standalone (autônomas). Uma ação inline é definida pelo método
de uma classe controller, enquanto uma ação standalone é uma classe que estende de
[[yii\base\Action]] ou de suas classes filhas. As ações inline exigem menos esforço
[[yii\base\Action]] ou de uma classe-filha. As ações inline exigem menos esforço
para serem criadas e muitas vezes as preferidas quando não se tem a intenção de
reutilizar estas ações. Ações standalone, por outro lado, são criados principalmente
para serem utilizados em diferentes controllers ou para serem distribuídos como
@ -258,11 +257,11 @@ para serem utilizados em diferentes controllers ou para serem distribuídos como
As ações inline referem-se a os chamados métodos de ação, que foram descritos anteriormente.
Os nomes dos métodos de ações são derivadas dos IDs das ações de acordo com os
seguintes critérios:
seguintes procedimentos:
* Colocar em caixa alta a primeira letra de cada palavra do ID da ação;
* Remover os traços;
* Adicionar o prefixo `action`.
1. Colocar em caixa alta a primeira letra de cada palavra do ID da ação;
2. Remover os traços;
3. Adicionar o prefixo `action`.
Por exemplo, `index` torna-se `actionIndex` e `hello-world` torna-se `actionHelloWorld`.
@ -280,7 +279,7 @@ lugares ou se deseja distribuir uma ação, deve considerar defini-la como uma *
### Ações Standalone <span id="standalone-actions"></span>
Ações standalone são definidas por classes de ações que estendem de [[yii\base\Action]]
ou de suas classes filhas.
ou de uma classe-filha.
Por example, nas versões do Yii, existe a [[yii\web\ViewAction]] e a [[yii\web\ErrorAction]], ambas são ações standalone.
Para usar uma ação standalone, você deve *mapear as ações* sobrescrevendo o método
@ -457,7 +456,7 @@ ao seguinte ciclo de vida para concluir a requisição:
* Se o ID da ação for encontrada para corresponder a um método de ação, uma ação inline será criada;
* Caso contrário, uma exceção [[yii\base\InvalidRouteException]] será lançada.
3. De forma sequencial, o controller chama o método `beforeAction()` da aplicação, o módulo (se o controller pertencer a um módulo) e o controller.
* Se uma das chamadas retornar false, o restante dos métodos `beforeAction()` serão ignoradas e a execução da ação será cancelada.
* Se uma das chamadas retornar false, o restante dos métodos subsequentes `beforeAction()` serão ignoradas e a execução da ação será cancelada.
* Por padrão, cada método `beforeAction()` desencadeia a execução de um evento chamado `beforeAction` na qual você pode associar a uma função (handler).
4. O controller executa a ação:
* Os parâmetros da ação serão analizados e populados a partir dos dados obtidos pela requisição;
@ -466,14 +465,14 @@ ao seguinte ciclo de vida para concluir a requisição:
6. A aplicação obterá o resultado da ação e irá associá-lo na [resposta](runtime-responses.md).
## Best Practices <span id="best-practices"></span>
## Boas Práticas <span id="best-practices"></span>
Em uma aplicação bem projetada, frequentemente os controllers são bem pequenos na
qual cada ação possui poucas linhas de códigos.
Se o controller for um pouco complicado, geralmente indica que terá que refaze-lo
e passar algum código para outro classe.
Em resumo, os controllers:
Segue algumas boas práticas em destaque. Os controllers:
* podem acessar os dados de uma [requisição](runtime-requests.md);
* podem chamar os métodos dos [models](structure-models.md) e outros componentes

6
docs/guide-pt-BR/structure-entry-scripts.md

@ -3,7 +3,7 @@ Scripts de Entrada
Scripts de entrada são o primeiro passo no processo de inicialização da aplicação.
Uma aplicação (seja uma aplicação Web ou uma aplicação console) possui um único script de
entrada. Os usuários finais fazem requisições a scripts de entrada que criam
entrada. Os usuários finais fazem requisições nos scripts de entrada que criam
as instâncias da aplicação e redirecionam as requisições para elas.
Os scripts de entrada para aplicações Web devem estar armazenados em diretórios
@ -20,7 +20,7 @@ possam executar aplicações do console através do comando
O trabalho principal dos scripts de entrada é o seguinte:
* Definir constantes globais;
* Registrar o [autoloader do Composer](http://getcomposer.org/doc/01-basic-usage.md#autoloading);
* Registrar o [autoloader do Composer](https://getcomposer.org/doc/01-basic-usage.md#autoloading);
* Incluir o arquivo da classe [[Yii]];
* Carregar a configuração da aplicação;
* Criar e configurar uma instância da [aplicação](structure-applications.md);
@ -29,7 +29,7 @@ O trabalho principal dos scripts de entrada é o seguinte:
## Aplicações Web <span id="web-applications"></span>
Este é o código no script de entrada para o [Modelo Básico de Aplicação Web](start-installation.md).
Este é o código no script de entrada para o [Template Básico de Projetos](start-installation.md).
```php
<?php

2
docs/guide-pt-BR/structure-models.md

@ -568,7 +568,7 @@ estenderá a classe model (modelo) base que a corresponde. A classe model (model
concreta irá conter apenas as regras e lógicas que são específicas de uma aplicação
ou módulo.
Por exemplo, no [Template Avançado de Aplicação](tutorial-advanced-app.md), você
Por exemplo, no [Template Avançado de Projetos](tutorial-advanced-app.md), você
pode definir uma classe model (modelo) base `common\models\Post`. Em seguida,
para a aplicação front-end, você define uma classe model (modelo) concreta
`frontend\models\Post` que estende de `common\models\Post`. E de forma similar

31
docs/guide-ru/README.md

@ -36,11 +36,11 @@ All Rights Reserved.
* [Компоненты приложения](structure-application-components.md)
* [Контроллеры](structure-controllers.md)
* [Представления](structure-views.md)
* **TBD** [Модели](structure-models.md)
* [Модели](structure-models.md)
* [Фильтры](structure-filters.md)
* [Виджеты](structure-widgets.md)
* [Модули](structure-modules.md)
* **TBD** [Ресурсы](structure-assets.md)
* [Ресурсы](structure-assets.md)
* [Расширения](structure-extensions.md)
@ -48,11 +48,10 @@ All Rights Reserved.
------------------
* [Bootstrapping](runtime-bootstrapping.md)
* [Роутинг](runtime-routing.md)
* [Разбор и генерация URL](runtime-routing.md)
* [Запросы](runtime-requests.md)
* [Ответы](runtime-responses.md)
* **TBD** [Сессии и куки](runtime-sessions-cookies.md)
* [Разбор и генерация URL](runtime-routing.md)
* [Сессии и куки](runtime-sessions-cookies.md)
* [Обработка ошибок](runtime-handling-errors.md)
* [Логирование](runtime-logging.md)
@ -74,10 +73,10 @@ All Rights Reserved.
Работа с базами данных
----------------------
* **TBD** [Объекты доступа к данным (DAO)](db-dao.md) - Соединение с базой данных, простые запросы, транзакции и работа со схемой.
* **TBD** [Построитель запросов](db-query-builder.md) - Запросы к базе данных через простой слой абстракции.
* [Объекты доступа к данным (DAO)](db-dao.md) - Соединение с базой данных, простые запросы, транзакции и работа со схемой.
* [Построитель запросов](db-query-builder.md) - Запросы к базе данных через простой слой абстракции.
* **TBD** [Active Record](db-active-record.md) - Получение объектов AR, работа с ними и определение связей.
* **TBD** [Миграции](db-migrations.md) - Контроль версий схемы данных при работе в команде.
* [Миграции](db-migrations.md) - Контроль версий схемы данных при работе в команде.
* **TBD** [Sphinx](db-sphinx.md)
* **TBD** [Redis](db-redis.md)
* **TBD** [MongoDB](db-mongodb.md)
@ -87,17 +86,17 @@ All Rights Reserved.
Получение данных от пользователя
--------------------------------
* **TBD** [Создание форм](input-forms.md)
* [Создание форм](input-forms.md)
* [Валидация](input-validation.md)
* **TBD** [Загрузка файлов](input-file-upload.md)
* [Загрузка файлов](input-file-upload.md)
* **TBD** [Работа с несколькими моделями](input-multiple-models.md)
Отображение данных
------------------
* **TBD** [Форматирование данных](output-formatting.md)
* [Постраничная разбивка](output-pagination.md)
* [Форматирование данных](output-formatting.md)
* [Постраничная разбивка](output-pagination.md)
* [Сортировка](output-sorting.md)
* **TBD** [Провайдеры данных](output-data-providers.md)
* **TBD** [Виджеты для данных](output-data-widgets.md)
@ -107,11 +106,11 @@ All Rights Reserved.
Безопасность
------------
* **TBD** [Аутентификация](security-authentication.md)
* **TBD** [Авторизация](security-authorization.md)
* **TBD** [Работа с паролями](security-passwords.md)
* [Аутентификация](security-authentication.md)
* [Авторизация](security-authorization.md)
* [Работа с паролями](security-passwords.md)
* **TBD** [Клиенты авторизации](security-auth-clients.md)
* **TBD** [Лучшие практики](security-best-practices.md)
* [Лучшие практики](security-best-practices.md)
Кеширование

12
docs/guide-ru/caching-data.md

@ -129,7 +129,7 @@ Yii поддерживает множество хранилищ кэша:
[[yii\caching\Cache::mget()|mget()]] и [[yii\caching\Cache::madd()|madd()]]. В случае, если хранилище не поддерживает
эту функцию, она будет имитироваться.
Так как [[yii\caching\Cache]] реализует `ArrayAccess`, компонент кэша можно испльзовать как массив:
Так как [[yii\caching\Cache]] реализует `ArrayAccess`, компонент кэша можно использовать как массив:
```php
$cache['var1'] = $value1; // эквивалентно: $cache->set('var1', $value1);
@ -210,7 +210,7 @@ if ($data === false) {
// Создать зависимость от времени модификации файла example.txt.
$dependency = new \yii\caching\FileDependency(['fileName' => 'example.txt']);
// Данные устаревеют через 30 секунд.
// Данные устаревают через 30 секунд.
// Данные могут устареть и раньше, если example.txt будет изменён.
$cache->set($key, $data, 30, $dependency);
@ -232,7 +232,7 @@ $data = $cache->get($key);
## Кэширование запросов <span id="query-caching"></span>
Кэширование запросов - это специальная функция кэширования, построеная на основе кэширования данных.
Кэширование запросов - это специальная функция кэширования, построенная на основе кэширования данных.
Она предназначена для кэширования результатов запросов к базе данных.
Кэширование запросов требует [[yii\db\Connection|DB connection]] и приложения действительный `cache`. Простое использование
@ -248,7 +248,7 @@ $result = $db->cache(function ($db) {
});
```
Кэширование запросов может быть использованно как для [DAO](db-dao.md), так и для [ActiveRecord](db-active-record.md):
Кэширование запросов может быть использовано как для [DAO](db-dao.md), так и для [ActiveRecord](db-active-record.md):
```php
$result = Customer::getDb()->cache(function ($db) {
@ -318,7 +318,7 @@ $result = $db->cache(function ($db) {
```
Если вы просто хотите использовать кэширование для одного запроса, вы можете вызвать [[yii\db\Command::cache()]] при
построении конманды. Например:
построении команды. Например:
```php
// использовать кэширование запросов и установить срок действия кэша на 60 секунд
@ -348,4 +348,4 @@ $result = $db->cache(function ($db) {
типа столбца `BLOB` в некоторых СУБД, в качестве результата запроса будет выведен ресурс обработчик данных столбца.
Некоторые кэш хранилища имеют ограничение в размере данных. Например, Memcache ограничивает максимальный размер каждой
записи до 1 Мб. Таким образом, если результат запроса превышает этот предел, данные не будут закэшированны.
записи до 1 Мб. Таким образом, если результат запроса превышает этот предел, данные не будут закешированы.

2
docs/guide-ru/concept-autoloading.md

@ -30,7 +30,7 @@ $classFile = Yii::getAlias('@' . str_replace('\\', '/', $className) . '.php');
При использовании [шаблона приложения basic](start-installation.md) вы можете хранить свои классы в пространстве имён `app`.
В этом случае они будут загружаться автоматически без создания нового псевдонима. Это работает потому как `@app`
является [заранее определённым псевдонимом](concept-aliases.md#predefined-aliases) и такое имя класса как
`app\components\MyClass` в соответствии с описанным выше алготимом преобразуется в путь
`app\components\MyClass` в соответствии с описанным выше алгоритмом преобразуется в путь
`директорияПриложения/components/MyClass.php`.
В [шаблоне приложения advanced](tutorial-advanced-app.md) каждый уровень приложения обладает собственным корневым

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

@ -121,7 +121,7 @@ $foo = $container->get('Foo');
------------------------
Вы можете использовать [[yii\di\Container::set()]] для регистрации зависимостей. При регистрации требуется имя зависимости, а так же определение зависимости.
Именем зависимости может быть имя класса, интерфейса или алиас, так же определением зависимости может быть имя класса, конфигурационным массивом, или PHP calback'ом.
Именем зависимости может быть имя класса, интерфейса или алиас, так же определением зависимости может быть имя класса, конфигурационным массивом, или PHP callback'ом.
```php
$container = new \yii\di\Container;

6
docs/guide-ru/concept-events.md

@ -226,9 +226,9 @@ Event::off(Foo::className(), Foo::EVENT_HELLO);
Глобальные события <span id="global-events"></span>
-------------
Yii поддерживает так называемые *глобальные события*, которые на самом деле основаны на нестандартном использовании описанного выше механизма событий. Для глобальных событий нужен глобально доступный объект-синглетон, например, экземпляр приложения - [application](structure-applications.md).
Yii поддерживает так называемые *глобальные события*, которые на самом деле основаны на нестандартном использовании описанного выше механизма событий. Для глобальных событий нужен глобально доступный объект-синглтон, например, экземпляр приложения - [application](structure-applications.md).
Чтобы создать глобальное событие, отправитель сообщения вызывает метод `trigger()` синглетона, а не свой собственный метод `trigger()`. Аналогичным образом обработчики события также присоединяются к событиям синглетона. Например:
Чтобы создать глобальное событие, отправитель сообщения вызывает метод `trigger()` синглтона, а не свой собственный метод `trigger()`. Аналогичным образом обработчики события также присоединяются к событиям синглтона. Например:
```php
use Yii;
@ -242,6 +242,6 @@ Yii::$app->on('bar', function ($event) {
Yii::$app->trigger('bar', new Event(['sender' => new Foo]));
```
Преимущество глобальных событий в том, что им не нужен объект, к событию которого бы присоединялся обработчик и объект, с помощью котрого бы это событие инициировалось. Вместо этого и для присоединения обработчика, и для инициирования события используется синглетон (например, экземпляр приложения).
Преимущество глобальных событий в том, что им не нужен объект, к событию которого бы присоединялся обработчик и объект, с помощью которого бы это событие инициировалось. Вместо этого и для присоединения обработчика, и для инициирования события используется синглтон (например, экземпляр приложения).
Тем не менее, так как пространство имен глобальных событий едино для всего приложения, их имена нельзя назначать бездумно. Например, полезными могут быть искусственные пространства имен ("frontend.mail.sent", "backend.mail.sent").

2
docs/guide-ru/concept-properties.md

@ -75,7 +75,7 @@ $object->label = 'abc';
значение свойства `label`. А метод `setLabel()` не будет вызван.
* Свойства, объявленные таким образом, не поддерживают модификаторы видимости. Это значит, что объявление геттера или
сеттера как public, protected или private никак не скажется на области видимости свойства.
* Свойства могут быть объявлены только с помощью *нестатичных* геттеров и/или сеттеров. Статичные методы не будут
* Свойства могут быть объявлены только с помощью *не статичных* геттеров и/или сеттеров. Статичные методы не будут
обрабатываться подобным образом.
Возвращаясь к проблеме необходимости вызова функции `trim()` во всех местах, где присваивается значение свойству `label`,

2
docs/guide-ru/concept-service-locator.md

@ -84,7 +84,7 @@ return [
];
```
Есть алтернативный приведённому выше способ настройки компонента "search". Вмето анонимной функции, котрая
Есть альтернативный приведённому выше способ настройки компонента "search". Вместо анонимной функции, которая
отдаёт экземпляр `SolrService` можно использовать статический метод, возвращающий такую анонимную функцию:
```php

636
docs/guide-ru/db-dao.md

@ -0,0 +1,636 @@
Объекты доступа к данным (DAO)
==============================
Построенные поверх [PDO](http://php.net/manual/ru/book.pdo.php), Yii DAO (объекты доступа к данным) обеспечивают
объектно-ориентированный API для доступа к реляционным базам данных. Это основа для других, более продвинутых, методов
доступа к базам данных, включая [построитель запросов](db-query-builder.md) и [active record](db-active-record.md).
При использовании Yii DAO вы в основном будете использовать чистый SQL и массивы PHP. Как результат, это самый
эффективный способ доступа к базам данных. Тем не менее, так как синтаксис SQL может отличаться для разных баз данных,
используя Yii DAO вам нужно будет приложить дополнительные усилия, чтобы сделать приложение не зависящим от конкретной
базы данных.
Yii DAO из коробки поддерживает следующие базы данных:
- [MySQL](http://www.mysql.com/)
- [MariaDB](https://mariadb.com/)
- [SQLite](http://sqlite.org/)
- [PostgreSQL](http://www.postgresql.org/)
- [CUBRID](http://www.cubrid.org/): версии 9.3 или выше.
- [Oracle](http://www.oracle.com/us/products/database/overview/index.html)
- [MSSQL](https://www.microsoft.com/en-us/sqlserver/default.aspx): версии 2008 или выше.
## Создание подключения к базе данных <span id="creating-db-connections"></span>
Для доступа к базе данных, вы сначала должны подключится к ней, создав экземпляр класса [[yii\db\Connection]]:
```php
$db = new yii\db\Connection([
'dsn' => 'mysql:host=localhost;dbname=example',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
]);
```
Так как подключение к БД часто нужно в нескольких местах, распространённой практикой является его настройка как
[компонента приложения](structure-application-components.md):
```php
return [
// ...
'components' => [
// ...
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=example',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
],
],
// ...
];
```
Теперь вы можете получить доступ к подключению к БД с помощью выражения `Yii::$app->db`.
> Подсказка: Вы можете настроить несколько компонентов подключения, если в вашем приложении используется несколько баз данных.
При настройке подключения, вы должны обязательно указывать Имя Источника Данных (DSN) через параметр [[yii\db\Connection::dsn|dsn]].
Формат DSN отличается для разных баз данных. По
The format of DSN varies for different databases. Дополнительное описание смотрите в [справочнике PHP](http://php.net/manual/ru/pdo.construct.php).
Ниже представлены несколько примеров:
* MySQL, MariaDB: `mysql:host=localhost;dbname=mydatabase`
* SQLite: `sqlite:/path/to/database/file`
* PostgreSQL: `pgsql:host=localhost;port=5432;dbname=mydatabase`
* CUBRID: `cubrid:dbname=demodb;host=localhost;port=33000`
* MS SQL Server (via sqlsrv driver): `sqlsrv:Server=localhost;Database=mydatabase`
* MS SQL Server (via dblib driver): `dblib:host=localhost;dbname=mydatabase`
* MS SQL Server (via mssql driver): `mssql:host=localhost;dbname=mydatabase`
* Oracle: `oci:dbname=//localhost:1521/mydatabase`
Заметьте, что если вы подключаетесь к базе данных через ODBC, вам необходимо указать свойство [[yii\db\Connection::driverName]],
чтобы Yii знал какой тип базы данных используется. Например:
```php
'db' => [
'class' => 'yii\db\Connection',
'driverName' => 'mysql',
'dsn' => 'odbc:Driver={MySQL};Server=localhost;Database=test',
'username' => 'root',
'password' => '',
],
```
Кроме свойства [[yii\db\Connection::dsn|dsn]], вам необходимо указать [[yii\db\Connection::username|username]]
и [[yii\db\Connection::password|password]]. Смотрите [[yii\db\Connection]] для того, чтоб посмотреть полный список свойств.
> Информация: При создании экземпляра соединения к БД, фактическое соединение с базой данных будет установлено только
при выполнении первого SQL запроса или при явном вызове метода [[yii\db\Connection::open()|open()]].
> Подсказка: Иногда может потребоваться выполнить некоторые запросы сразу после соединения с базой данных, для инициализации
> переменных окружения. Вы можете зарегистрировать обработчик для события [[yii\db\Connection::EVENT_AFTER_OPEN|afterOpen]].
> Вы можете зарегистрировать обработчик прямо в конфигурации приложения:
>
> ```php
> 'db' => [
> // ...
> 'on afterOpen' => function($event) {
> $event->sender->createCommand("YOUR SQL HERE")->execute();
> }
> ]
> ```
## Выполнение SQL запросов <span id="executing-sql-queries"></span>
После создания экземпляра соединения, вы можете выполнить SQL запрос, выполнив следующие шаги:
1. Создать [[yii\db\Command]] с текстом SQL;
2. Привязать параметры (не обязательно);
3. Вызвать один из методов выполнения SQL из [[yii\db\Command]].
Следующий пример показывает различные способы получения данных из базы дынных:
```php
$db = new yii\db\Connection(...);
// возвращает набор строк. каждая строка - это ассоциативный массив с именами столбцов и значений.
// если выборка ничего не вернёт, то будет возвращён пустой массив.
$posts = $db->createCommand('SELECT * FROM post')
->queryAll();
// вернёт одну строку (первую строку)
// ложь, если ничего не будет выбрано
$post = $db->createCommand('SELECT * FROM post WHERE id=1')
->queryOne();
// вернёт один столбец (первый столбец)
// пустой массив, при отсутствии результата
$titles = $db->createCommand('SELECT title FROM post')
->queryColumn();
// вернёт значение
// ложь, при отсутствии результата
$count = $db->createCommand('SELECT COUNT(*) FROM post')
->queryScalar();
```
> Примечание: Чтобы сохранить точность, данные извлекаются как строки, даже если тип поля в базе данных является числовым.
> Подсказка: Если вам необходимо выполнить SQL запрос сразу после установки соединения (например, для установки
> временной зоны или кодировки), вы можете сделать это в обработчике события [[yii\db\Connection::EVENT_AFTER_OPEN]].
> Например:
```php
return [
// ...
'components' => [
// ...
'db' => [
'class' => 'yii\db\Connection',
// ...
'on afterOpen' => function($event) {
// $event->sender ссылка на соединение с базой данных
$event->sender->createCommand("SET time_zone = 'UTC'")->execute();
}
],
],
// ...
];
```
### Привязка параметров <span id="binding-parameters"></span>
При создании команды из SQL запроса с параметрами, вы почти всегда должны использовать привязку параметров для
предотвращения атак через SQL инъекции. Например:
```php
$post = $db->createCommand('SELECT * FROM post WHERE id=:id AND status=:status')
->bindValue(':id', $_GET['id'])
->bindValue(':status', 1)
->queryOne();
```
В SQL запрос, вы можете встраивать один или несколько маркеров (например `:id` в примере выше). Маркеры должны быть
строкой начинающейся с двоеточия. Далее вам нужно вызвать один из следующих методов для привязки значений к параметрам:
* [[yii\db\Command::bindValue()|bindValue()]]: привязка одного параметра по значению
* [[yii\db\Command::bindValues()|bindValues()]]: привязка нескольких параметров в одном вызове
* [[yii\db\Command::bindParam()|bindParam()]]: похоже на [[yii\db\Command::bindValue()|bindValue()]] но привязка
происходит по ссылке.
Следующий пример показывает альтернативный путь привязки параметров:
```php
$params = [':id' => $_GET['id'], ':status' => 1];
$post = $db->createCommand('SELECT * FROM post WHERE id=:id AND status=:status')
->bindValues($params)
->queryOne();
$post = $db->createCommand('SELECT * FROM post WHERE id=:id AND status=:status', $params)
->queryOne();
```
Привязка переменных реализована через [подготавливаемые запросы](http://php.net/manual/ru/mysqli.quickstart.prepared-statements.php).
Помимо предотвращения атак путём SQL инъекций, это увеличивает производительность, так как запрос подготавливается
один раз, а потом выполняется много раз с разными параметрами. Например:
```php
$command = $db->createCommand('SELECT * FROM post WHERE id=:id');
$post1 = $command->bindValue(':id', 1)->queryOne();
$post2 = $command->bindValue(':id', 2)->queryOne();
```
Так как [[yii\db\Command::bindParam()|bindParam()]] поддерживает привязку параметров по ссылке, следующий код может
быть написан следующим образом:
```php
$command = $db->createCommand('SELECT * FROM post WHERE id=:id')
->bindParam(':id', $id);
$id = 1;
$post1 = $command->queryOne();
$id = 2;
$post2 = $command->queryOne();
```
Обратите внимание что вы связываете маркер `$id` с переменной перед выполнением запроса, и затем меняете это значение
перед каждым последующим выполнением (часто это делается в цикле). Выполнении запросов таким образом может быть значительно
более эффективным, чем выполнение запроса для каждого значения параметра.
### Выполнение Не-SELECT запросов <span id="non-select-queries"></span>
В методах `queryXyz()`, описанных в предыдущих разделах, вызываются SELECT запросы для извлечения данных из базы.
Для запросов не возвращающих данные, вы должны использовать метод [[yii\db\Command::execute()]]. Например:
```php
$db->createCommand('UPDATE post SET status=1 WHERE id=1')
->execute();
```
Метод [[yii\db\Command::execute()]] возвращает количество строк обработанных SQL запросом.
Для запросов INSERT, UPDATE и DELETE, вместо написания чистого SQL, вы можете вызвать методы [[yii\db\Command::insert()|insert()]],
[[yii\db\Command::update()|update()]], [[yii\db\Command::delete()|delete()]], соответственно, для создания указанных
SQL конструкций. Например:
```php
// INSERT (table name, column values)
$db->createCommand()->insert('user', [
'name' => 'Sam',
'age' => 30,
])->execute();
// UPDATE (table name, column values, condition)
$db->createCommand()->update('user', ['status' => 1], 'age > 30')->execute();
// DELETE (table name, condition)
$db->createCommand()->delete('user', 'status = 0')->execute();
```
Вы можете также вызвать [[yii\db\Command::batchInsert()|batchInsert()]] для вставки множества строк за один вызов.
Это более эффективно чем вставлять записи по одной за раз:
```php
// table name, column names, column values
$db->createCommand()->batchInsert('user', ['name', 'age'], [
['Tom', 30],
['Jane', 20],
['Linda', 25],
])->execute();
```
## Экранирование имён таблиц и столбцов <span id="quoting-table-and-column-names"></span>
При написании независимого от базы данных кода, правильно экранировать имена таблиц и столбцов довольно трудно, так как
в разных базах данных правила экранирования разные. Чтоб преодолеть данную проблему вы можете использовать следующий
синтаксис экранирования используемый в Yii:
* `[[column name]]`: заключайте имя столбца в двойные квадратные скобки;
* `{{table name}}`: заключайте имя таблицы в двойные фигурные скобки.
Yii DAO будет автоматический преобразовывать подобные конструкции в SQL в правильно экранированные имена таблиц и столбцов.
Например,
```php
// executes this SQL for MySQL: SELECT COUNT(`id`) FROM `employee`
$count = $db->createCommand("SELECT COUNT([[id]]) FROM {{employee}}")
->queryScalar();
```
### Использование префиксов таблиц <span id="using-table-prefix"></span>
Если большинство ваших таблиц использует общий префикс в имени, вы можете использовать свойство Yii DAO для указания префикса.
Сначала, укажите префикс таблиц через свойство [[yii\db\Connection::tablePrefix]]:
```php
return [
// ...
'components' => [
// ...
'db' => [
// ...
'tablePrefix' => 'tbl_',
],
],
];
```
Затем в коде, когда вам нужно ссылаться на таблицу, имя которой содержит такой префикс, используйте синтаксис `{{%table name}}`.
Символ процента будет автоматический заменён на префикс таблицы, который вы указали во время конфигурации соединения с
базой данных. Например:
```php
// для MySQL будет выполнен следующий SQL: SELECT COUNT(`id`) FROM `tbl_employee`
$count = $db->createCommand("SELECT COUNT([[id]]) FROM {{%employee}}")
->queryScalar();
```
## Исполнение транзакций <span id="performing-transactions"></span>
Когда вы выполняете несколько зависимых запросов последовательно, вам может потребоваться обернуть их в транзакцию
для обеспечения целостности вашей базы данных. Если в любом из запросов произойдёт ошибка, база данных откатится на
состояние, которое было до выполнения запросов.
Следующий код показывает типичное использование транзакций:
```php
$db->transaction(function($db) {
$db->createCommand($sql1)->execute();
$db->createCommand($sql2)->execute();
// ... executing other SQL statements ...
});
```
Код выше эквивалентен следующему:
```php
$transaction = $db->beginTransaction();
try {
$db->createCommand($sql1)->execute();
$db->createCommand($sql2)->execute();
// ... executing other SQL statements ...
$transaction->commit();
} catch(\Exception $e) {
$transaction->rollBack();
throw $e;
}
```
При вызове метода [[yii\db\Connection::beginTransaction()|beginTransaction()]], будет запущена новая транзакция.
Транзакция представлена объектом [[yii\db\Transaction]] сохранённым в переменной `$transaction`. Потом, запросы будут
выполняться в блоке `try...catch...`. Если запросы будут выполнены удачно, будет выполнен метод [[yii\db\Transaction::commit()|commit()]].
Иначе, будет вызвано исключение, и будет вызван метод [[yii\db\Transaction::rollBack()|rollBack()]] для отката
изменений сделанных до неудачно выполненного запроса внутри транзакции.
### Указание уровня изоляции <span id="specifying-isolation-levels"></span>
Yii поддерживает настройку [уровня изоляции] для ваших транзакций. По умолчанию, при старте транзакции, будет использован
уровень изоляции настроенный в вашей базе данных. Вы можете переопределить уровень изоляции по умолчанию, как
указано ниже:
```php
$isolationLevel = \yii\db\Transaction::REPEATABLE_READ;
$db->transaction(function ($db) {
....
}, $isolationLevel);
// or alternatively
$transaction = $db->beginTransaction($isolationLevel);
```
Yii предоставляет четыре константы для наиболее распространённых уровней изоляции:
- [[\yii\db\Transaction::READ_UNCOMMITTED]] - низший уровень, «Грязное» чтение, не повторяющееся чтение и фантомное чтение.
- [[\yii\db\Transaction::READ_COMMITTED]] - предотвращает «Грязное» чтение.
- [[\yii\db\Transaction::REPEATABLE_READ]] - предотвращает «Грязное» чтение и не повторяющееся чтение.
- [[\yii\db\Transaction::SERIALIZABLE]] - высший уровень, предотвращает все вышеуказанные проблемы.
Помимо использования приведённых выше констант для задания уровня изоляции, вы можете также использовать строки с
поддерживаемые вашим СУБД. Например, в PostgreSQL, вы можете использовать `SERIALIZABLE READ ONLY DEFERRABLE`.
Заметьте что некоторые СУБД допускают настраивать уровень изоляции только для всего соединения. Следующие транзакции
будут получать тот же уровень изоляции, даже если вы его не укажете. При использовании этой функции может потребоваться
установить уровень изоляции для всех транзакции, чтоб избежать явно конфликтующих настроек.
На момент написания этой статьи страдали от этого только MSSQL и SQLite.
> Примечание: SQLite поддерживает только два уровня изоляции, таким образом вы можете использовать только
`READ UNCOMMITTED` и `SERIALIZABLE`. Использование других уровней изоляции приведёт к генерации исключения.
> Примечание: PostgreSQL не допускает установки уровня изоляции до старта транзакции, так что вы не сможете установить
уровень изоляции прямо при старте транзакции. Вы можете использовать [[yii\db\Transaction::setIsolationLevel()]] в
таком случае после старта транзакции.
[Уровни изоляции]: https://ru.wikipedia.org/wiki/%D0%A3%D1%80%D0%BE%D0%B2%D0%B5%D0%BD%D1%8C_%D0%B8%D0%B7%D0%BE%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D0%B8_%D1%82%D1%80%D0%B0%D0%BD%D0%B7%D0%B0%D0%BA%D1%86%D0%B8%D0%B9
### Вложенные транзакции <span id="nesting-transactions"></span>
Если ваша СУБД поддерживает Savepoint, вы можете вкладывать транзакции как показано ниже:
```php
$db->transaction(function ($db) {
// outer transaction
$db->transaction(function ($db) {
// inner transaction
});
});
```
Или так,
```php
$outerTransaction = $db->beginTransaction();
try {
$db->createCommand($sql1)->execute();
$innerTransaction = $db->beginTransaction();
try {
$db->createCommand($sql2)->execute();
$innerTransaction->commit();
} catch (Exception $e) {
$innerTransaction->rollBack();
}
$outerTransaction->commit();
} catch (Exception $e) {
$outerTransaction->rollBack();
}
```
## Репликация и разделение запросов на чтение и запись <span id="read-write-splitting"></span>
Многие СУБД поддерживают [репликацию баз данных](http://en.wikipedia.org/wiki/Replication_(computing)#Database_replication)
для лучшей доступности базы данных и уменьшения времени ответа сервера. С репликацией базы данных, данные копируются
из *master servers* на *slave servers*. Все вставки и обновления должны происходить на основном сервере, хотя чтение
может производится и с подчинённых серверов.
Чтоб воспользоваться преимуществами репликации и достичь разделения чтения и записи, вам необходимо настроить компонент
[[yii\db\Connection]] как указано ниже:
```php
[
'class' => 'yii\db\Connection',
// настройки для мастера
'dsn' => 'dsn for master server',
'username' => 'master',
'password' => '',
// общие настройки для подчинённых
'slaveConfig' => [
'username' => 'slave',
'password' => '',
'attributes' => [
// используем небольшой таймаут для соединения
PDO::ATTR_TIMEOUT => 10,
],
],
// список настроек для подчинённых серверов
'slaves' => [
['dsn' => 'dsn for slave server 1'],
['dsn' => 'dsn for slave server 2'],
['dsn' => 'dsn for slave server 3'],
['dsn' => 'dsn for slave server 4'],
],
]
```
Вышеуказанная конфигурация определяет систему с одним мастером и несколькими подчинёнными. Один из подчинённых
будет подключен и использован для чтения, в то время как мастер будет использоваться для запросов записи.
Такое разделение чтения и записи будет осуществлено автоматический с указанной конфигурацией. Например:
```php
// создание экземпляра соединения, использующего вышеуказанную конфигурацию
$db = Yii::createObject($config);
// запрос к одному из подчинённых
$rows = $db->createCommand('SELECT * FROM user LIMIT 10')->queryAll();
// запрос к мастеру
$db->createCommand("UPDATE user SET username='demo' WHERE id=1")->execute();
```
> Информация: Запросы выполненные через [[yii\db\Command::execute()]] определяются как запросы на запись, а все
остальные запросы через один из "query" методов [[yii\db\Command]] воспринимаются как запросы на чтение.
Вы можете получить текущий статус соединения к подчинённому серверу через `$db->slave`.
Компонент `Connection` поддерживает балансировку нагрузки и переключение при сбое для подчинённых серверов.
При выполнении первого запроса на чтение, компонент `Connection` будет случайным образом выбирать подчинённый сервер
и попытается подключиться к нему. Если сервер окажется "мёртвым", он попробует подключиться к другому. Если ни один
из подчинённых серверов не будет доступен, он подключится к мастеру. Если настроить
[[yii\db\Connection::serverStatusCache|кеш статуса серверов]], то недоступность серверов может быть запомнена, чтоб не
использоваться в течении [[yii\db\Connection::serverRetryInterval|заданного промежутка времени]].
> Информация: В конфигурации выше, таймаут соединения к подчинённому серверу настроен на 10 секунд.
Это означает, что если сервер не ответит за 10 секунд, он будет считаться "мёртвым". Вы можете отрегулировать
этот параметр исходя из настроек вашей среды.
Вы также можете настроить несколько основных и несколько подчинённых серверов. Например:
```php
[
'class' => 'yii\db\Connection',
// общая конфигурация для основных серверов
'masterConfig' => [
'username' => 'master',
'password' => '',
'attributes' => [
// используем небольшой таймаут для соединения
PDO::ATTR_TIMEOUT => 10,
],
],
// список настроек для основных серверов
'masters' => [
['dsn' => 'dsn for master server 1'],
['dsn' => 'dsn for master server 2'],
],
// общие настройки для подчинённых
'slaveConfig' => [
'username' => 'slave',
'password' => '',
'attributes' => [
// используем небольшой таймаут для соединения
PDO::ATTR_TIMEOUT => 10,
],
],
// список настроек для подчинённых серверов
'slaves' => [
['dsn' => 'dsn for slave server 1'],
['dsn' => 'dsn for slave server 2'],
['dsn' => 'dsn for slave server 3'],
['dsn' => 'dsn for slave server 4'],
],
]
```
Конфигурация выше, определяет два основных и четыре подчинённых серверов. Компонент `Connection` поддерживает
балансировку нагрузки и переключение при сбое между основными серверами, также как и между подчинёнными. Различие
заключается в том, что когда ни к одному из основных серверов не удастся подключиться будет выброшено исключение.
> Примечание: Когда вы используете свойство [[yii\db\Connection::masters|masters]] для настройки одного или нескольких
основных серверов, все остальные свойства для настройки соединения с базой данных (такие как `dsn`, `username`, `password`)
будут проигнорированы компонентом `Connection`.
По умолчанию, транзакции используют соединение с основным сервером. И в рамках транзакции, все операции с БД будут
использовать соединение с основным сервером. Например,
```php
// Транзакция запускается на основном сервере
$transaction = $db->beginTransaction();
try {
// оба запроса выполняются на основном сервере
$rows = $db->createCommand('SELECT * FROM user LIMIT 10')->queryAll();
$db->createCommand("UPDATE user SET username='demo' WHERE id=1")->execute();
$transaction->commit();
} catch(\Exception $e) {
$transaction->rollBack();
throw $e;
}
```
Если вы хотите запустить транзакцию на подчинённом сервере, вы должны указать это явно, как показано ниже:
```php
$transaction = $db->slave->beginTransaction();
```
Иногда может потребоваться выполнить запрос на чтение через подключение к основному серверу. Это может быть достигнуто
с использованием метода `useMaster()`:
```php
$rows = $db->useMaster(function ($db) {
return $db->createCommand('SELECT * FROM user LIMIT 10')->queryAll();
});
```
Вы также можете явно установить `$db->enableSlaves` в ложь, чтоб направлять все запросы к соединению с мастером.
## Работа со схемой базы данных <span id="database-schema"></span>
Yii DAO предоставляет целый набор методов для управления схемой базы данных, таких как создание новых таблиц, удаление
столбцов из таблицы, и т.д.. Эти методы описаны ниже:
* [[yii\db\Command::createTable()|createTable()]]: создание таблицы
* [[yii\db\Command::renameTable()|renameTable()]]: переименование таблицы
* [[yii\db\Command::dropTable()|dropTable()]]: удаление таблицы
* [[yii\db\Command::truncateTable()|truncateTable()]]: удаление всех записей в таблице
* [[yii\db\Command::addColumn()|addColumn()]]: добавление столбца
* [[yii\db\Command::renameColumn()|renameColumn()]]: переименование столбца
* [[yii\db\Command::dropColumn()|dropColumn()]]: удаление столбца
* [[yii\db\Command::alterColumn()|alterColumn()]]: преобразование столбца
* [[yii\db\Command::addPrimaryKey()|addPrimaryKey()]]: добавление первичного ключа
* [[yii\db\Command::dropPrimaryKey()|dropPrimaryKey()]]: удаление первичного ключа
* [[yii\db\Command::addForeignKey()|addForeignKey()]]: добавление внешнего ключа
* [[yii\db\Command::dropForeignKey()|dropForeignKey()]]: удаление внешнего ключа
* [[yii\db\Command::createIndex()|createIndex()]]: создания индекса
* [[yii\db\Command::dropIndex()|dropIndex()]]: удаление индекса
Эти методы могут быть использованы, как указано ниже:
```php
// CREATE TABLE
$db->createCommand()->createTable('post', [
'id' => 'pk',
'title' => 'string',
'text' => 'text',
]);
```
Вы также сможете получить описание схемы таблицы через вызов метода [[yii\db\Connection::getTableSchema()|getTableSchema()]].
Например:
```php
$table = $db->getTableSchema('post');
```
Метод вернёт объект [[yii\db\TableSchema]], который содержит информацию о столбцах таблицы, первичных ключах, внешних
ключах, и т.д.. Вся эта информация используется главным образом для [построителя запросов](db-query-builder.md) и
[active record](db-active-record.md), чтоб помочь вам писать независимый от базы данных код.

14
docs/guide-ru/db-migrations.md

@ -5,7 +5,7 @@
В связи с тем, что изменение структуры базы данных часто требует изменение исходного кода, yii поддерживает так
называемую возможность *миграции баз данных*, которая позволяет отслеживать изменения в базах данных при помощи терминов *миграции баз данных*, которые являются системой контроля версий вместе с исходным кодом.
Следующие шаги показывают, как миграции базы данных могут быть использованны командой разработчиков в процессе разработки:
Следующие шаги показывают, как миграции базы данных могут быть использованы командой разработчиков в процессе разработки:
1. Илья создает новую миграцию (например, создается новая таблица или изменяется определение столбца и т.п.).
2. Илья фиксирует новую миграцию в системе управления версиями (например, в Git, Mercurial).
@ -42,7 +42,7 @@ yii migrate/create <name>
yii migrate/create create_news_table
```
> Примечание: Поскольку аргумент `name` будет использован как часть имени класса создавамой миграции, он должен содержать только буквы, цифры и/или символы подчеркивания.
> Примечание: Поскольку аргумент `name` будет использован как часть имени класса создаваемой миграции, он должен содержать только буквы, цифры и/или символы подчеркивания.
Приведенная выше команда создаст новый PHP класс с именем файла `m150101_185401_create_news_table.php` в директории `@app/migrations`. Файл содержит следующий код, который главным образом декларирует класс миграции `m150101_185401_create_news_table` с следующим каркасом кода:
@ -99,7 +99,7 @@ class m150101_185401_create_news_table extends \yii\db\Migration
}
```
> Для справки: Не все миграции являются обратимыми. Например, если метод `up()` удаляет строку из таблицы, возможно что у вас уже не будет возможности вернуть эту строку методом `down()`. Иногда Вам может быть просто слишком лень реализовывать метод `down()`, в связи с тем, что это не очень распространенно - откатывать миграции базы данных. В этом случае вы должны в методе `down()` вернуть `false`, чтобы указать, что миграция не является обратимой.
> Для справки: Не все миграции являются обратимыми. Например, если метод `up()` удаляет строку из таблицы, возможно что у вас уже не будет возможности вернуть эту строку методом `down()`. Иногда Вам может быть просто слишком лень реализовывать метод `down()`, в связи с тем, что это не очень распространено - откатывать миграции базы данных. В этом случае вы должны в методе `down()` вернуть `false`, чтобы указать, что миграция не является обратимой.
Базовый класс миграций [[yii\db\Migration]] предоставляет подключение к базе данных через свойство [[yii\db\Migration::db|db]]. Вы можете использовать его для манипулирования схемой базы данных используя методы описанные в [работе со схемой базы данных](db-dao.md#database-schema).
@ -224,7 +224,7 @@ yii migrate/to 1392853618 # используя врем
Чтобы отменить (откатить) одну или несколько миграций, которые применялись ранее, нужно запустить следующую команду:
```
yii migrate/down # отменяет самую последнюю применёную миграцию
yii migrate/down # отменяет самую последнюю применённую миграцию
yii migrate/down 3 # отменяет 3 последних применённых миграции
```
@ -292,11 +292,11 @@ yii migrate/mark 1392853618 # используя вре
Например, если мы хотим перенести модуль `forum`, чьи файлы миграций расположены в каталоге `migrations` данного модуля, для этого мы можем использовать следующую команду:
```
# неинтерактивная миграция модуля форума
# не интерактивная миграция модуля форума
yii migrate --migrationPath=@app/modules/forum/migrations --interactive=0
```
### Глобальная Настройка Комманд <span id="configuring-command-globally"></span>
### Глобальная Настройка Команд <span id="configuring-command-globally"></span>
Вместо того, чтобы каждый раз вводить одинаковые значения параметров миграции, когда вы запускаете команду миграции, можно настроить её раз и навсегда в конфигурации приложения, как показано ниже:
@ -311,7 +311,7 @@ return [
];
```
С приведённой выше конфигурацией, каждый раз при запуске команды миграции, таблица `backend_migration` будет использованна для записи истории миграций. И Вам больше не нужно указывать её через параметр `migrationTable` в командной строке.
С приведённой выше конфигурацией, каждый раз при запуске команды миграции, таблица `backend_migration` будет использована для записи истории миграций. И Вам больше не нужно указывать её через параметр `migrationTable` в командной строке.
## Миграции в Несколько Баз Данных <span id="migrating-multiple-databases"></span>

644
docs/guide-ru/db-query-builder.md

@ -0,0 +1,644 @@
Построитель запросов
====================
Построенный поверх [DAO](db-dao.md), построитель запросов позволяет конструировать SQL выражения в программируемом и
независимом от СУБД виде. В сравнении с написанием чистого SQL, использование построителя помогает вам писать
более читаемый связанный с SQL код и генерировать более безопасные SQL выражения.
Использование построителя запросов, как правило, включает два этапа:
1. Создание объекта [[yii\db\Query]] представляющего различные части (такие как `SELECT`, `FROM`) SQL выражения SELECT.
2. Выполнить запрос методом [[yii\db\Query]] (таким как `all()`) для извлечения данных из базы данных.
Следующий код показывает обычное использование построителя запросов:
```php
$rows = (new \yii\db\Query())
->select(['id', 'email'])
->from('user')
->where(['last_name' => 'Smith'])
->limit(10)
->all();
```
Приведённый выше код создаёт и выполняет следующее SQL выражение, где параметр `:last_name` привязывается к строке `'Smith'`.
```sql
SELECT `id`, `email`
FROM `user`
WHERE `last_name` = :last_name
LIMIT 10
```
> Информация: В основном вы будете работать с [[yii\db\Query]] вместо [[yii\db\QueryBuilder]]. Последний вызывается
неявно при вызове одного из методов запроса. [[yii\db\QueryBuilder]] это класс отвечающий за генерацию зависимого
от СУБД SQL выражения (такие как экранирование имён таблиц/столбцов) из независимых от СУБД объектов [[yii\db\Query]].
## Построение запросов <span id="building-queries"></span>
Создав объект [[yii\db\Query]], вы можете вызвать различные методы для создания различных частей SQL выражения.
Имена методов напоминают ключевые слова SQL, используемые в соответствующих частях SQL запроса. Например,
чтобы указать `FROM` часть запроса, вам нужно вызвать метод `from()`. Все методы построителя запросов возвращают
свой объект, который позволяет объединять несколько вызовов в цепочку.
Далее будет описание каждого метода построителя запросов.
### [[yii\db\Query::select()|select()]] <span id="select"></span>
Метод [[yii\db\Query::select()|select()]] определяет фрагмент `SELECT` SQL запроса. Вы можете указать столбцы, которые
должны быть выбраны, они должны быть указаны в виде массива или строки. Имена столбцов автоматически экранируются
при создании SQL-запроса при его генерации из объекта [[yii\db\Query]].
```php
$query->select(['id', 'email']);
// эквивалентно:
$query->select('id, email');
```
Имена столбцов могут быть выбраны вместе с префиксами таблиц и/или алиасами столбцов, также как при записи обычного SQL.
Например,
```php
$query->select(['user.id AS user_id', 'email']);
// эквивалентно:
$query->select('user.id AS user_id, email');
```
Если вы используете формат массива для указания столбцов, вы можете также указать ключи массива для указания алиасов столбцов.
Например, приведённый выше код может быть переписан:
```php
$query->select(['user_id' => 'user.id', 'email']);
```
Если вы не вызываете метод [[yii\db\Query::select()|select()]] при создании запроса, будет использована `*`, что означает
выбрать *все* столбцы.
Кроме имён столбцов, вы можете также использовать SQL выражения. Вы должны использовать формат массива для использования
выражений, которые содержат запятые для предотвращения некорректного автоматического экранирования. Например:
```php
$query->select(["CONCAT(first_name, ' ', last_name) AS full_name", 'email']);
```
Начиная с версии 2.0.1, вы также можете использовать подзапросы. Вы должны указывать каждый подзапрос в выражении как
объект [[yii\db\Query]]. Например:
```php
$subQuery = (new Query())->select('COUNT(*)')->from('user');
// SELECT `id`, (SELECT COUNT(*) FROM `user`) AS `count` FROM `post`
$query = (new Query())->select(['id', 'count' => $subQuery])->from('post');
```
Чтоб выбрать конкретные строки, вы можете вызвать метод [[yii\db\Query::distinct()|distinct()]]:
```php
// SELECT DISTINCT `user_id` ...
$query->select('user_id')->distinct();
```
Вы можете вызвать [[yii\db\Query::addSelect()|addSelect()]] для добавления полей. Например:
```php
$query->select(['id', 'username'])
->addSelect(['email']);
```
### [[yii\db\Query::from()|from()]] <span id="from"></span>
Метод [[yii\db\Query::from()|from()]] указывает фрагмент `FROM` SQL запроса. Например:
```php
// SELECT * FROM `user`
$query->from('user');
```
Вы можете указать имена таблиц в виде строки или массива. Имена таблиц могут содержать префикс схемы и/или алиасы
таблиц, как при написании обычного SQL. Например:
```php
$query->from(['public.user u', 'public.post p']);
// эквивалентно:
$query->from('public.user u, public.post p');
```
Если вы используете формат массива, вы можете использовать ключи массива для указания алиасов:
```php
$query->from(['u' => 'public.user', 'p' => 'public.post']);
```
Кроме имён таблиц, вы можете, также как и в select, указывать подзапросы в виде объекта [[yii\db\Query]].
```php
$subQuery = (new Query())->select('id')->from('user')->where('status=1');
// SELECT * FROM (SELECT `id` FROM `user` WHERE status=1) u
$query->from(['u' => $subQuery]);
```
### [[yii\db\Query::where()|where()]] <span id="where"></span>
Метод [[yii\db\Query::where()|where()]] определяет фрагмент `WHERE` SQL выражения. Вы можете использовать один из
трёх форматов:
- строковый формат, например: `'status=1'`
- формат массива, например: `['status' => 1, 'type' => 2]`
- формат операторов, например: `['like', 'name', 'test']`
#### Строковый формат <span id="string-format"></span>
Строковый формат - это лучший выбор для простых условий. Он работает так, будто вы просто пишете SQL запрос. Например:
```php
$query->where('status=1');
// или используя привязку параметров
$query->where('status=:status', [':status' => $status]);
```
Не встраивайте переменные непосредственно в условие, особенно если значение переменной получено от пользователя,
потому что это делает ваше приложение подверженным атакам через SQL инъекции.
```php
// Опасность! Не делайте так если вы не уверены, что $status это действительно число.
$query->where("status=$status");
```
При использовании привязки параметров, вы можете вызывать [[yii\db\Query::params()|params()]] или
[[yii\db\Query::addParams()|addParams()]] для раздельного указания параметров.
```php
$query->where('status=:status')
->addParams([':status' => $status]);
```
#### Формат массива <span id="hash-format"></span>
Формат массива лучше всего использовать для указания нескольких объединяемых через `AND` условий, каждое из которых
является простым равенством. Он описывается в виде массива, ключами которого являются имена столбцов, а значения
соответствуют значениям столбцов.
```php
// ...WHERE (`status` = 10) AND (`type` IS NULL) AND (`id` IN (4, 8, 15))
$query->where([
'status' => 10,
'type' => null,
'id' => [4, 8, 15],
]);
```
Как вы можете видеть, построитель запросов достаточно умен, чтобы правильно обрабатывать значения NULL или массивов.
Вы также можете использовать подзапросы:
```php
$userQuery = (new Query())->select('id')->from('user');
// ...WHERE `id` IN (SELECT `id` FROM `user`)
$query->where(['id' => $userQuery]);
```
#### Формат операторов <span id="operator-format"></span>
Формат оператора позволяет задавать произвольные условия в программном стиле. Он имеет следующий вид:
```php
[operator, operand1, operand2, ...]
```
Операнды могут быть заданы в виде строкового формата, формата массива или формата операторов рекурсивно, в то время
как оператор может быть одним из следующих:
- `and`: операнды должны быть объединены с помощью оператора `AND`. Например,
`['and', 'id=1', 'id=2']` сгенерирует `id=1 AND id=2`. Если операнд массив,
он будет сконвертирован в строку по правилам описанным ниже. Например,
`['and', 'type=1', ['or', 'id=1', 'id=2']]` сгенерирует `type=1 AND (id=1 OR id=2)`.
Этот метод не производит никакого экранирования.
- `or`: похож на оператор `and` за исключением того, что будет использоваться оператор `OR`.
- `between`: первый операнд должен быть именем столбца, а второй и третий оператор должны быть начальным и конечным
значением диапазона. Например, `['between', 'id', 1, 10]` сгенерирует `id BETWEEN 1 AND 10`.
- `not between`: похож на `between` за исключением того, что `BETWEEN` заменяется на `NOT BETWEEN`
в сгенерированном условии.
- `in`: первый операнд должен быть столбцом или выражением БД. Второй операнд может быть либо массивом, либо объектом `Query`.
Будет сгенерировано условие `IN`. Если второй операнд массив, он будет представлять набор значений, которым может быть
равен столбец или выражение БД; Если второй операнд объект `Query`, будет сформирован подзапрос, который будет использован
как диапазон для столбца или выражения БД. Например, `['in', 'id', [1, 2, 3]]` сформирует `id IN (1, 2, 3)`.
Метод будет правильно экранировать имя столбца и значения диапазона. Оператор `in` также поддерживает составные столбцы.
В этом случае, первый операнд должен быть массивом названий столбцом, в то время как операнд 2 должен быть массивом
массивов или объектом `Query` представляющим диапазоны для столбцов.
- `not in`: похож на оператор `in`, кроме того что `IN` будет заменён на `NOT IN` в сформированном условии.
- `like`: первый операнд должен быть столбцом или выражением БД, а второй операнд будет строкой или массивом представляющим
значения, на которые должны быть похожи столбцы или выражения БД. Например, `['like', 'name', 'tester']`
сформирует `name LIKE '%tester%'`.
Когда диапазон значений задан в виде массива, несколько `LIKE` утверждений будут сформированы и соединены с помощью `AND`.
Например, `['like', 'name', ['test', 'sample']]` сформирует `name LIKE '%test%' AND name LIKE '%sample%'`.
Вы также можете передать третий необязательный операнд, для указания способа экранирования специальных символов в значениях.
Операнд должен быть представлен массивом соответствия специальных символов их экранированным аналогам. Если этот
операнд не задан, то будет использовано соответствие по умолчанию. Вы можете также использовать значение `false`
или пустой массив, чтоб указать что значения уже экранированы. Обратите внимание, что при использовании массива соответствия
экранирования (или если третий операнд не передан), значения будут автоматически заключены в символы процентов.
> Примечание: При использовании PostgreSQL вы можете использовать также [`ilike`](http://www.postgresql.org/docs/8.3/static/functions-matching.html#FUNCTIONS-LIKE)
> вместо `like` для регистронезависимого поиска.
- `or like`: похож на оператор `like`, только утверждения `LIKE` будут объединяться с помощью оператора `OR`, если
второй операнд будет представлен массивом.
- `not like`: похож на оператор `like`, только `LIKE` будет заменён на `NOT LIKE` в сгенерированном условии.
- `or not like`: похож на оператор `not like`, только утверждения `NOT LIKE` будут объединены с помощью `OR`.
- `exists`: требует один операнд, который должен быть экземпляром [[yii\db\Query]] представляющим подзапрос. Будет
сгенерировано выражение `EXISTS (sub-query)`.
- `not exists`: похож на оператор `exists` и сформирует выражение `NOT EXISTS (sub-query)`.
- `>`, `<=`, или другие валидные операторы БД, которые требуют двух операндов: первый операнд должен быть именем
столбца, второй операнд это значение. Например, `['>', 'age', 10]` сформирует `age>10`.
#### Добавление условий <span id="appending-conditions"></span>
Вы можете использовать [[yii\db\Query::andWhere()|andWhere()]] или [[yii\db\Query::orWhere()|orWhere()]] для добавления
дополнительных условий. Вы можете использовать эти вызовы несколько раз для добавления нескольких условий.
Например:
```php
$status = 10;
$search = 'yii';
$query->where(['status' => $status]);
if (!empty($search)) {
$query->andWhere(['like', 'title', $search]);
}
```
Если `$search` не пустое, то будет сформировано следующее выражение:
```sql
... WHERE (`status` = 10) AND (`title` LIKE '%yii%')
```
#### Условия для фильтров <span id="filter-conditions"></span>
Когда условие `WHERE` формируется на основе пользовательского ввода, обычно хочется проигнорировать не заданные значения.
Например, в форме поиска, которая позволяет осуществлять поиск по имени пользователя или email, вы хотели бы игнорировать
username/email условие, если пользователь ничего не ввёл в поле ввода. Вы можете достичь этого используя метод
[[yii\db\Query::filterWhere()|filterWhere()]].
```php
// $username и $email вводит пользователь
$query->filterWhere([
'username' => $username,
'email' => $email,
]);
```
Единственное отличие между [[yii\db\Query::filterWhere()|filterWhere()]] и [[yii\db\Query::where()|where()]]
заключается в игнорировании пустых значений переданных в условие в [форме массива](#hash-format). Таким образом
если `$email` будет пустым, а `$username` нет, то приведённый выше код сформирует `...WHERE username=:username`.
> Информация: значение признаётся пустым, если это null, пустой массив, пустая строка или строка состоящая из одних пробельных символов.
Также вместо [[yii\db\Query::andWhere()|andWhere()]] и [[yii\db\Query::orWhere()|orWhere()]], вы можете использовать
[[yii\db\Query::andFilterWhere()|andFilterWhere()]] и [[yii\db\Query::orFilterWhere()|orFilterWhere()]]
для добавления дополнительных условий фильтрации.
### [[yii\db\Query::orderBy()|orderBy()]] <span id="order-by"></span>
Метод [[yii\db\Query::orderBy()|orderBy()]] определяет фрагмент `ORDER BY` SQL выражения. Например,
```php
// ... ORDER BY `id` ASC, `name` DESC
$query->orderBy([
'id' => SORT_ASC,
'name' => SORT_DESC,
]);
```
В данном коде, ключи массива это имена столбцов, а значения массива это соответствующее направление сортировки.
PHP константа `SORT_ASC` определяет сортировку по возрастанию и `SORT_DESC` сортировка по умолчанию.
Если `ORDER BY` содержит только простые имена столбцов, вы можете определить их с помощью столбцов, также
как и при написании обычного SQL. Например,
```php
$query->orderBy('id ASC, name DESC');
```
> Примечание: Вы должны использовать массив для указания `ORDER BY` содержащих выражения БД.
Вы можете вызывать [[yii\db\Query::addOrderBy()|addOrderBy()]] для добавления столбцов в фрагмент `ORDER BY`.
```php
$query->orderBy('id ASC')
->addOrderBy('name DESC');
```
### [[yii\db\Query::groupBy()|groupBy()]] <span id="group-by"></span>
Метод [[yii\db\Query::groupBy()|groupBy()]] определяет фрагмент `GROUP BY` SQL запроса.
```php
// ... GROUP BY `id`, `status`
$query->groupBy(['id', 'status']);
```
Если фрагмент `GROUP BY` содержит только простые имена столбцов, вы можете указать их используя строку, также как в
обычном SQL.
```php
$query->groupBy('id, status');
```
> Примечание: Вы должны использовать массив для указания `GROUP BY` содержащих выражения БД.
Вы можете вызывать [[yii\db\Query::addGroupBy()|addGroupBy()]] для добавления имён столбцов в фрагмент `GROUP BY`.
For example,
```php
$query->groupBy(['id', 'status'])
->addGroupBy('age');
```
### [[yii\db\Query::having()|having()]] <span id="having"></span>
Метод [[yii\db\Query::having()|having()]] определяет фрагмент `HAVING` SQL запроса. Он принимает условия, которое
может быть определено тем же способом, что и для [where()](#where).
```php
// ... HAVING `status` = 1
$query->having(['status' => 1]);
```
Пожалуйста, обратитесь к документации для [where()](#where) для более подробной информации о определении условий.
Вы можете вызывать [[yii\db\Query::andHaving()|andHaving()]] или [[yii\db\Query::orHaving()|orHaving()]] для добавления
дополнительных условий в фрагмент `HAVING`.
```php
// ... HAVING (`status` = 1) AND (`age` > 30)
$query->having(['status' => 1])
->andHaving(['>', 'age', 30]);
```
### [[yii\db\Query::limit()|limit()]] и [[yii\db\Query::offset()|offset()]] <span id="limit-offset"></span>
Методы [[yii\db\Query::limit()|limit()]] и [[yii\db\Query::offset()|offset()]] определяют фрагменты `LIMIT`
и `OFFSET` SQL запроса.
```php
// ... LIMIT 10 OFFSET 20
$query->limit(10)->offset(20);
```
Если вы определяете неправильный limit или offset (например отрицательное значение), они будут проигнорированы.
> Информация: Для СУБД, которые не поддерживают `LIMIT` и `OFFSET` (такие как MSSQL), построитель запросов будет
генерировать SQL выражения, которые эмулирует поведение `LIMIT`/`OFFSET`.
### [[yii\db\Query::join()|join()]] <span id="join"></span>
Метод [[yii\db\Query::join()|join()]] определяет фрагмент `JOIN` SQL запроса.
```php
// ... LEFT JOIN `post` ON `post`.`user_id` = `user`.`id`
$query->join('LEFT JOIN', 'post', 'post.user_id = user.id');
```
Метод [[yii\db\Query::join()|join()]] принимает четыре параметра:
- `$type`: тип объединения, например, `'INNER JOIN'`, `'LEFT JOIN'`.
- `$table`: имя таблицы, которая должна быть присоединена.
- `$on`: необязательное условие объединения, то есть фрагмент `ON`. Пожалуйста, обратитесь к документации для
[where()](#where) для более подробной информации о определении условий.
- `$params`: необязательные параметры присоединяемые к условию объединения.
Вы можете использовать следующие сокращающие методы для указания `INNER JOIN`, `LEFT JOIN` и `RIGHT JOIN`, в указанном порядке.
- [[yii\db\Query::innerJoin()|innerJoin()]]
- [[yii\db\Query::leftJoin()|leftJoin()]]
- [[yii\db\Query::rightJoin()|rightJoin()]]
Например,
```php
$query->leftJoin('post', 'post.user_id = user.id');
```
Для соединения с несколькими таблицами, вызовите вышеуказанные методы несколько раз.
Кроме соединения с таблицами, вы можете также присоединять подзапросы. Чтоб это сделать, укажите объединяемый подзапрос
как объект [[yii\db\Query]].
```php
$subQuery = (new \yii\db\Query())->from('post');
$query->leftJoin(['u' => $subQuery], 'u.id = author_id');
```
В этом случае, вы должны передать подзапросы в массиве и использовать ключи для определения алиасов.
### [[yii\db\Query::union()|union()]] <span id="union"></span>
Метод [[yii\db\Query::union()|union()]] определяет фрагмент `UNION` SQL запроса.
```php
$query1 = (new \yii\db\Query())
->select("id, category_id AS type, name")
->from('post')
->limit(10);
$query2 = (new \yii\db\Query())
->select('id, type, name')
->from('user')
->limit(10);
$query1->union($query2);
```
Вы можете вызвать [[yii\db\Query::union()|union()]] несколько раз для присоединения фрагментов `UNION`.
## Методы выборки <span id="query-methods"></span>
[[yii\db\Query]] предоставляет целый набор методов для разных вариантов выборки:
- [[yii\db\Query::all()|all()]]: возвращает массив строк, каждая из которых это ассоциативный массив пар ключ-значение.
- [[yii\db\Query::one()|one()]]: возвращает первую строку запроса.
- [[yii\db\Query::column()|column()]]: возвращает первый столбец результата.
- [[yii\db\Query::scalar()|scalar()]]: возвращает скалярное значение первого столбца первой строки результата.
- [[yii\db\Query::exists()|exists()]]: возвращает значение указывающее, что выборка содержит результат.
- [[yii\db\Query::count()|count()]]: возвращает результат `COUNT` запроса.
- Другие методы агрегирования запросов, включая [[yii\db\Query::sum()|sum($q)]], [[yii\db\Query::average()|average($q)]],
[[yii\db\Query::max()|max($q)]], [[yii\db\Query::min()|min($q)]]. Параметр `$q` обязателен для этих методов и могут
содержать либо имя столбца, либо выражение БД.
Например:
```php
// SELECT `id`, `email` FROM `user`
$rows = (new \yii\db\Query())
->select(['id', 'email'])
->from('user')
->all();
// SELECT * FROM `user` WHERE `username` LIKE `%test%`
$row = (new \yii\db\Query())
->from('user')
->where(['like', 'username', 'test'])
->one();
```
> Примечание: метод [[yii\db\Query::one()|one()]] вернёт только первую строку результата запроса. Он НЕ добавляет
`LIMIT 1` в генерируемый SQL. Это хорошо и предпочтительно если вы знаете, что запрос вернёт только одну или несколько
строк данных (например, при запросе по первичному ключу). Однако, если запрос потенциально может вернут много
строк данных, вы должны вызвать `limit(1)` для повышения производительности, Например:
`(new \yii\db\Query())->from('user')->limit(1)->one()`.
Все методы выборки могут получать необязательный параметр `$db`, представляющий [[yii\db\Connection|соединение с БД]],
которое должно использоваться, чтобы выполнить запрос к БД. Если вы упускаете этот параметр, будет использоваться
[компонент приложения](structure-application-components.md) `$db`. Ниже приведён ещё один пример использования метода
`count()`:
```php
// executes SQL: SELECT COUNT(*) FROM `user` WHERE `last_name`=:last_name
$count = (new \yii\db\Query())
->from('user')
->where(['last_name' => 'Smith'])
->count();
```
При вызове методов выборки [[yii\db\Query]], внутри на самом деле проводится следующая работа:
* Вызывается [[yii\db\QueryBuilder]] для генерации SQL запроса на основе текущего [[yii\db\Query]];
* Создаёт объект [[yii\db\Command]] с сгенерированным SQL запросом;
* Вызывается выбирающий метод (например `queryAll()`) из [[yii\db\Command]] для выполнения SQL запроса и извлечения данных.
Иногда вы можете захотеть увидеть или использовать SQL запрос построенный из объекта [[yii\db\Query]]. Этой цели можно
добиться с помощью следующего кода:
```php
$command = (new \yii\db\Query())
->select(['id', 'email'])
->from('user')
->where(['last_name' => 'Smith'])
->limit(10)
->createCommand();
// показать SQL запрос
echo $command->sql;
// показать привязываемые параметры
print_r($command->params);
// возвращает все строки запроса
$rows = $command->queryAll();
```
### Индексация результатов запроса <span id="indexing-query-results"></span>
При вызове [[yii\db\Query::all()|all()]] возвращается массив строк индексированный последовательными целыми числами.
Иногда вам может потребоваться индексировать его по другому, например сделать индекс по указанному столбцу или
значением выражения. Вы можете реализовать такое поведение через вызов [[yii\db\Query::indexBy()|indexBy()]] перед
вызовом [[yii\db\Query::all()|all()]].
```php
// возвращает [100 => ['id' => 100, 'username' => '...', ...], 101 => [...], 103 => [...], ...]
$query = (new \yii\db\Query())
->from('user')
->limit(10)
->indexBy('id')
->all();
```
Для индексации по значению выражения, передайте анонимную функцию в метод [[yii\db\Query::indexBy()|indexBy()]]:
```php
$query = (new \yii\db\Query())
->from('user')
->indexBy(function ($row) {
return $row['id'] . $row['username'];
})->all();
```
Анонимная функция должна принимать параметр `$row`, который содержит текущую строку запроса и должна вернуть скалярное
значение, которое будет использоваться как значение индекса для текущей строки.
### Пакетная выборка <span id="batch-query"></span>
При работе с большими объемами данных, методы на подобие [[yii\db\Query::all()]] не подходят, потому что они требуют
загрузки всех данных в память. Чтобы сохранить требования к памяти минимальными, Yii предоставляет поддержку
так называемых пакетных выборок. Пакетная выборка делает возможным курсоры данных и выборку данных пакетами.
Пакетная выборка может использоваться следующим образом:
```php
use yii\db\Query;
$query = (new Query())
->from('user')
->orderBy('id');
foreach ($query->batch() as $users) {
// $users это массив из 100 или менее строк из таблицы пользователей
}
// или если вы хотите перебрать все строки по одной
foreach ($query->each() as $user) {
// $user представляет одну строку из выборки
}
```
Метод [[yii\db\Query::batch()]] и [[yii\db\Query::each()]] возвращает объект [[yii\db\BatchQueryResult]], который
реализует интерфейс `Iterator` и может использоваться в конструкции `foreach`. Во время первой итерации будет выполнен
SQL запрос к базе данных. Данные будут выбираться пакетами в следующих итерациях. По умолчанию, размер пакета имеет
размер 100, то есть при каждой выборке будет выбираться по 100 строк. Вы можете изменить размер пакета, передав
первый параметр в метод `batch()` или `each()`.
По сравнению с [[yii\db\Query::all()]], пакетная выборка загружает только по 100 строк данных за раз в память.
Если вы обрабатываете данные и затем сразу выбрасываете их, пакетная выборка может помочь уменьшить использование памяти.
Если указать индексный столбец через [[yii\db\Query::indexBy()]], в пакетной выборке индекс будет сохранятся.
Например,
```php
$query = (new \yii\db\Query())
->from('user')
->indexBy('username');
foreach ($query->batch() as $users) {
// $users индексируется по столбцу "username"
}
foreach ($query->each() as $username => $user) {
}
```

177
docs/guide-ru/helper-url.md

@ -0,0 +1,177 @@
Url хелпер
==========
Url хелпер предоставляет набор статических методов для управления URL.
## Получение общих URL <span id="getting-common-urls"></span>
Вы можете использовать два метода получения общих URL: домашний URL (Home) и базовый URL (Base) текущего запроса.
Используйте следующий код, чтобы получить домашний URL:
```php
$relativeHomeUrl = Url::home();
$absoluteHomeUrl = Url::home(true);
$httpsAbsoluteHomeUrl = Url::home('https');
```
Если вы не передали параметров, то получите относительный URL. Вы можете передать `true`, чтобы получить абсолютный URL
для текущего протокола или явно указать протокол (`https`, `http`).
Чтобы получить базовый URL текущего запроса:
```php
$relativeBaseUrl = Url::base();
$absoluteBaseUrl = Url::base(true);
$httpsAbsoluteBaseUrl = Url::base('https');
```
Единственный параметр данного метода работает также как и `Url::home()`.
## Создание URL <span id="creating-urls"></span>
Чтобы создать URL для соответствующего роута используйте метод `Url::toRoute()`. Метод использует [[\yii\web\UrlManager]].
Для того чтобы создать URL:
```php
$url = Url::toRoute(['product/view', 'id' => 42]);
```
Вы можете задать роут строкой, например, `site/index`. А также вы можете использовать массив, если хотите задать
дополнительные параметры запроса для URL. Формат массива должен быть следующим:
```php
// сгенерирует: /index.php?r=site/index&param1=value1&param2=value2
['site/index', 'param1' => 'value1', 'param2' => 'value2']
```
Если вы хотите создать URL с якорем, то вы можете использовать параметр массива с ключом `#`. Например:
```php
// сгенерирует: /index.php?r=site/index&param1=value1#name
['site/index', 'param1' => 'value1', '#' => 'name']
```
Роут может быть и абсолютным, и относительным. Абсолютный URL начинается со слеша (например, `/site/index`),
относительный - без (например, `site/index` or `index`). Относительный URL будет сконвертирован в абсолютный по следующим
правилам:
- Если роут пустая строка, то будет использовано текущее значение [[\yii\web\Controller::route|route]];
- Если роут не содержит слешей (например, `index`), то он будет считаться экшеном текущего контролера и будет определен
с помощью [[\yii\web\Controller::uniqueId]];
- Если роут начинается не со слеша (например, `site/index`), то он будет считаться относительным роутом текущего модуля
и будет определен с помощью [[\yii\base\Module::uniqueId|uniqueId]].
Начиная с версии 2.0.2, вы можете задавать роуты с помощью [псевдонимов](concept-aliases.md). В этом случае, сначала
псевдоним будет сконвертирован в соответствующий роут, который будет преобразован в абсолютный в соответствии с вышеописанными
правилами.
Примеры использования метода:
```php
// /index.php?r=site/index
echo Url::toRoute('site/index');
// /index.php?r=site/index&src=ref1#name
echo Url::toRoute(['site/index', 'src' => 'ref1', '#' => 'name']);
// /index.php?r=post/edit&id=100 псевдоним "@postEdit" задан как "post/edit"
echo Url::toRoute(['@postEdit', 'id' => 100]);
// http://www.example.com/index.php?r=site/index
echo Url::toRoute('site/index', true);
// https://www.example.com/index.php?r=site/index
echo Url::toRoute('site/index', 'https');
```
Другой метод `Url::to()` очень похож на [[toRoute()]]. Единственное отличие: входным параметром должен быть массив.
Если будет передана строка, то она будет воспринята как URL.
Первый аргумент может быть:
- массивом: будет вызван [[toRoute()]], чтобы сгенерировать URL. Например: `['site/index']`, `['post/index', 'page' => 2]`.
В разделе [[toRoute()]] подробно описано как задавать роут;
- Строка, начинающаяся с `@`, будет обработана как псевдоним. Будет возвращено соответствующее значение псевдонима;
- Пустая строка: вернет текущий URL;
- Обычная строка: вернет строку без изменений
Когда у метода задан второй параметр `$scheme` (строка или true), то сгенерированный URL будет с протоколом
(полученным из [[\yii\web\UrlManager::hostInfo]]). Если в `$url` указан протокол, то его значение будет заменено.
Пример использования:
```php
// /index.php?r=site/index
echo Url::to(['site/index']);
// /index.php?r=site/index&src=ref1#name
echo Url::to(['site/index', 'src' => 'ref1', '#' => 'name']);
// /index.php?r=post/edit&id=100 псевдоним "@postEdit" задан как "post/edit"
echo Url::to(['@postEdit', 'id' => 100]);
// Текущий URL
echo Url::to();
// /images/logo.gif
echo Url::to('@web/images/logo.gif');
// images/logo.gif
echo Url::to('images/logo.gif');
// http://www.example.com/images/logo.gif
echo Url::to('@web/images/logo.gif', true);
// https://www.example.com/images/logo.gif
echo Url::to('@web/images/logo.gif', 'https');
```
Начиная с версии 2.0.3, вы можете использовать [[yii\helpers\Url::current()]], чтобы создавать URL на основе текущего
запрошенного роута и его GET-параметров. Вы можете изменить, удалить или добавить новые GET-параметры передав в метод
параметр `$params`. Например:
```php
// предположим $_GET = ['id' => 123, 'src' => 'google'], а текущий роут "post/view"
// /index.php?r=post/view&id=123&src=google
echo Url::current();
// /index.php?r=post/view&id=123
echo Url::current(['src' => null]);
// /index.php?r=post/view&id=100&src=google
echo Url::current(['id' => 100]);
```
## Запоминание URL <span id="remember-urls"></span>
Существуют задачи, когда вам необходимо запомнить URL и потом использовать его в процессе одного или нескольких
последовательных запросов. Это может быть достигнуто следующим образом:
```php
// Запомнить текущий URL
Url::remember();
// Запомнить определенный URL. Входные параметры смотрите на примере Url::to().
Url::remember(['product/view', 'id' => 42]);
// Запомнить URL под определенным именем
Url::remember(['product/view', 'id' => 42], 'product');
```
В следующем запросе мы можем получить сохраненный URL следующим образом:
```php
$url = Url::previous();
$productUrl = Url::previous('product');
```
## Проверить относительность URL <span id="checking-relative-urls"></span>
Чтобы проверить относительный URL или нет (например, если в нем не содержится информации о хосте), вы можете использовать
следующий код:
```php
$isRelative = Url::isRelative('test/it');
```

368
docs/guide-ru/images/rbac-access-check-1.graphml

@ -0,0 +1,368 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.12.2-->
<key for="graphml" id="d0" yfiles.type="resources"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key attr.name="Description" attr.type="string" for="graph" id="d7"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d7"/>
<node id="n0">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="36.68359375" x="33.158203125" y="25.1494140625">admin<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n1">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="38.025390625" x="32.4873046875" y="25.1494140625">author<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n2">
<data key="d6">
<y:SVGNode>
<y:Geometry height="64.53585815429688" width="56.560157775878906" x="216.21992111206055" y="-132.03585815429688"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.905467987060547" y="-27.814727783203125">John, ID=2<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.113555908203125" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="1"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n3">
<data key="d6">
<y:SVGNode>
<y:Geometry height="66.76200103759766" width="56.554100036621094" x="57.22294998168945" y="-133.14892959594727"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.908496856689453" y="-27.701656341552734">Jane, ID=1<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.000484466552734" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="2"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n4">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.71484375" x="19.142578125" y="25.1494140625">updatePost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n5">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="89.388671875" x="6.8056640625" y="25.1494140625">updateOwnPost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n6">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="352.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="61.36328125" x="20.818359375" y="25.1494140625">createPost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n7">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="29.535858154296875" width="103.0" x="193.0" y="167.96414184570312"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.03515625" x="19.482421875" y="5.4173431396484375">AuthorRule<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<edge id="e0" source="n4" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n4" target="n5">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n1" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#FF0000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e3" source="n6" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="403.5" y="23.0"/>
</y:Path>
<y:LineStyle color="#FF0000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e4" source="n1" target="n2">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e5" source="n0" target="n3">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#FF0000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e6" source="n7" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d0">
<y:Resources>
<y:Resource id="1">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="65px" viewBox="0 0 57 65" enable-background="new 0 0 57 65" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;path id="body_18_" fill="#ECECEC" stroke="#9B9B9B" stroke-miterlimit="10" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-11.244-6.146-11.244-6.146
c-1.771,1.655-5.61,3.802-10.063,3.802c-4.453,0-8.292-2.146-10.063-3.802c0,0-5.755,0.586-11.189,6.021
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;radialGradient id="SVGID_2_" cx="22.6621" cy="21.707" r="17.7954" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_2_)" stroke="#E55E03" d="M28.106,33.486c-8.112,0-12.688,4.313-12.688,10.438
c0,7.422,12.688,10.438,12.688,10.438s14.688-3.016,14.688-10.438C42.793,38.75,36.215,33.486,28.106,33.486z M26.288,53.051
c0,0-7.135-2.093-8.805-7.201c-0.222-0.682,0.147-1.156,0.795-1.521V37.8h20.188v6.663c0.235,0.352,1.109,0.737,1.229,1.387
C40.445,49.917,26.288,53.051,26.288,53.051z"/&gt;
&lt;radialGradient id="SVGID_3_" cx="15.2056" cy="831.1875" r="32.3071" gradientTransform="matrix(1 0 0 1 0.0801 -773.6914)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_3_)" stroke="#E55E03" d="M49.529,51.225c-2.239-2.24-5.041-3.724-7.396-4.67
c-2.854,5.51-14.021,7.807-14.021,7.807s-10.472-2.483-12.387-8.514c-2.439,0.771-5.787,2.287-8.749,5.25
c-5.592,5.592-6.47,11.67-6.47,11.67c0,1.938,1.575,3.492,3.523,3.492h48.51c1.946,0,3.521-1.558,3.521-3.492
C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="SVGID_4_" cx="17.0723" cy="18.4907" r="11.8931" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_4_)" stroke="#E55E03" d="M13.404,44.173c1.15-1.81,2.039-3.832,3.332-5.397
c-0.514,1.027-1.669,4.084-1.669,5.148c0,5.186,10.366,9.079,14.688,10.438c-3.472,1.627-9.134-1.498-11.334-2.359
c-3.601-1.419-4.071-3.063-5.89-4.854C12.523,47.135,12.878,45,13.404,44.173z"/&gt;
&lt;radialGradient id="SVGID_5_" cx="31.8184" cy="19.3525" r="14.63" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_5_)" stroke="#E55E03" d="M45.777,43.924c-1.317-1.568-5.11-9.424-6.604-6.617
c0.516,1.025,3.617,3.693,3.617,6.617c0,5.186-10.271,8.576-16.699,9.145c1.429,4.938,11.373,1.293,13.805-0.313
c3.563-2.354,4.563-5.133,7.854-3.705C47.754,49.045,48.006,46.574,45.777,43.924z"/&gt;
&lt;radialGradient id="SVGID_6_" cx="30.4893" cy="4.8721" r="5.2028" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_6_)" stroke="#E55E03" d="M30.777,54.167c0.357,0.836-0.153,1.983-0.352,2.813
c-0.256,1.084-0.072,2.104,0.102,3.186c0.164,1.02,0.156,2.107,0.25,3.167c0.082,0.916,0.482,1.849,0.357,2.75"/&gt;
&lt;radialGradient id="SVGID_7_" cx="23.2871" cy="5.3008" r="5.5143" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_7_)" stroke="#E55E03" d="M23.695,53.417c-0.508,0.584-0.476,2.209-0.398,3
c0.116,1.183,0.456,2.099,0.333,3.333c-0.192,1.943,0.154,4.479-0.436,6.333"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.2-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.501" y1="-12291.5195" x2="6492.1304" y2="-12384.9688" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3351.7349)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Young_Black_1_" fill="#5C5C5C" stroke="#353535" stroke-linecap="round" stroke-linejoin="round" d="M20.278,13.25
c3.417,4.333,9.333,6.917,9.333,6.917l-1.417-3.5c0,0,7.094,4.691,8.083,4.333c0.968-0.2-1.082-3.807-1.082-3.807
s3.138,1.795,4.854,3.969c1.803,2.28,4.285,3.504,4.285,3.504S47.027,2.719,27.289,2.744C8.278,2.709,12.058,27.678,12.058,27.678
L14.695,17c0,0,0.914,5.757,1.399,4.875C17.861,15.211,18.861,11.5,20.278,13.25z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
<y:Resource id="2">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="67px" viewBox="0 0 57 67" enable-background="new 0 0 57 67" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.199-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.5" y1="-12286.8594" x2="6492.1294" y2="-12380.3086" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3350.4617)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Female_1_Red_1_" fill="#FAE1AA" stroke="#E2B354" stroke-linecap="round" stroke-linejoin="round" d="M28.372,0.5
C17.537,0.5,8.269,7.748,9.153,26.125c0.563,6.563,5.862,12.042,9.366,13.531c-2.929-10.968-0.304-25.021-0.585-25.526
c-0.281-0.505,3.536,6.728,3.536,6.728l3.183-8.312c5.541,4.28,0.393,11.309,1.049,11.058c4.26-1.631,5.34-9.228,5.34-9.228
s2.729,3.657,2.701,5.504c-0.054,3.562,2.194-6.067,2.194-6.067l1.027,2.031c6.727,9.822,3.684,16.208,1.648,22.781
c15.666-0.703,12.291-10.48,9.66-18.407C43.59,6.092,39.206,0.5,28.372,0.5z"/&gt;
&lt;linearGradient id="body_1_" gradientUnits="userSpaceOnUse" x1="95.9063" y1="-3134.2153" x2="31.5133" y2="-3134.2153" gradientTransform="matrix(0.9852 0 0 -0.9852 -34.4844 -3031.9851)"&gt;
&lt;stop offset="0" style="stop-color:#49AD33"/&gt;
&lt;stop offset="1" style="stop-color:#C2DA92"/&gt;
&lt;/linearGradient&gt;
&lt;path id="body_8_" fill="url(#body_1_)" stroke="#008D33" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-8.244-5.146-8.244-5.146
c-1.444,6.983-8.555,8.786-13.007,8.786s-11.322-2.643-11.941-9.439c0,0-4.559,1.199-9.367,5.674
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
</y:Resources>
</data>
</graphml>

BIN
docs/guide-ru/images/rbac-access-check-1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

368
docs/guide-ru/images/rbac-access-check-2.graphml

@ -0,0 +1,368 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.12.2-->
<key for="graphml" id="d0" yfiles.type="resources"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key attr.name="Description" attr.type="string" for="graph" id="d7"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d7"/>
<node id="n0">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="36.68359375" x="33.158203125" y="25.1494140625">admin<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n1">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="38.025390625" x="32.4873046875" y="25.1494140625">author<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n2">
<data key="d6">
<y:SVGNode>
<y:Geometry height="64.53585815429688" width="56.560157775878906" x="216.21992111206055" y="-132.03585815429688"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.905467987060547" y="-27.814727783203125">John, ID=2<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.113555908203125" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="1"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n3">
<data key="d6">
<y:SVGNode>
<y:Geometry height="66.76200103759766" width="56.554100036621094" x="57.22294998168945" y="-133.14892959594727"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.908496856689453" y="-27.701656341552734">Jane, ID=1<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.000484466552734" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="2"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n4">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.71484375" x="19.142578125" y="25.1494140625">updatePost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n5">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="89.388671875" x="6.8056640625" y="25.1494140625">updateOwnPost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n6">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="352.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="61.36328125" x="20.818359375" y="25.1494140625">createPost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n7">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="29.535858154296875" width="103.0" x="193.0" y="167.96414184570312"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.03515625" x="19.482421875" y="5.4173431396484375">AuthorRule<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<edge id="e0" source="n4" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n4" target="n5">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#FF0000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n1" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e3" source="n6" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="403.5" y="23.0"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e4" source="n1" target="n2">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#FF0000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e5" source="n0" target="n3">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e6" source="n7" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#FF0000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d0">
<y:Resources>
<y:Resource id="1">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="65px" viewBox="0 0 57 65" enable-background="new 0 0 57 65" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;path id="body_18_" fill="#ECECEC" stroke="#9B9B9B" stroke-miterlimit="10" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-11.244-6.146-11.244-6.146
c-1.771,1.655-5.61,3.802-10.063,3.802c-4.453,0-8.292-2.146-10.063-3.802c0,0-5.755,0.586-11.189,6.021
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;radialGradient id="SVGID_2_" cx="22.6621" cy="21.707" r="17.7954" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_2_)" stroke="#E55E03" d="M28.106,33.486c-8.112,0-12.688,4.313-12.688,10.438
c0,7.422,12.688,10.438,12.688,10.438s14.688-3.016,14.688-10.438C42.793,38.75,36.215,33.486,28.106,33.486z M26.288,53.051
c0,0-7.135-2.093-8.805-7.201c-0.222-0.682,0.147-1.156,0.795-1.521V37.8h20.188v6.663c0.235,0.352,1.109,0.737,1.229,1.387
C40.445,49.917,26.288,53.051,26.288,53.051z"/&gt;
&lt;radialGradient id="SVGID_3_" cx="15.2056" cy="831.1875" r="32.3071" gradientTransform="matrix(1 0 0 1 0.0801 -773.6914)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_3_)" stroke="#E55E03" d="M49.529,51.225c-2.239-2.24-5.041-3.724-7.396-4.67
c-2.854,5.51-14.021,7.807-14.021,7.807s-10.472-2.483-12.387-8.514c-2.439,0.771-5.787,2.287-8.749,5.25
c-5.592,5.592-6.47,11.67-6.47,11.67c0,1.938,1.575,3.492,3.523,3.492h48.51c1.946,0,3.521-1.558,3.521-3.492
C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="SVGID_4_" cx="17.0723" cy="18.4907" r="11.8931" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_4_)" stroke="#E55E03" d="M13.404,44.173c1.15-1.81,2.039-3.832,3.332-5.397
c-0.514,1.027-1.669,4.084-1.669,5.148c0,5.186,10.366,9.079,14.688,10.438c-3.472,1.627-9.134-1.498-11.334-2.359
c-3.601-1.419-4.071-3.063-5.89-4.854C12.523,47.135,12.878,45,13.404,44.173z"/&gt;
&lt;radialGradient id="SVGID_5_" cx="31.8184" cy="19.3525" r="14.63" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_5_)" stroke="#E55E03" d="M45.777,43.924c-1.317-1.568-5.11-9.424-6.604-6.617
c0.516,1.025,3.617,3.693,3.617,6.617c0,5.186-10.271,8.576-16.699,9.145c1.429,4.938,11.373,1.293,13.805-0.313
c3.563-2.354,4.563-5.133,7.854-3.705C47.754,49.045,48.006,46.574,45.777,43.924z"/&gt;
&lt;radialGradient id="SVGID_6_" cx="30.4893" cy="4.8721" r="5.2028" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_6_)" stroke="#E55E03" d="M30.777,54.167c0.357,0.836-0.153,1.983-0.352,2.813
c-0.256,1.084-0.072,2.104,0.102,3.186c0.164,1.02,0.156,2.107,0.25,3.167c0.082,0.916,0.482,1.849,0.357,2.75"/&gt;
&lt;radialGradient id="SVGID_7_" cx="23.2871" cy="5.3008" r="5.5143" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_7_)" stroke="#E55E03" d="M23.695,53.417c-0.508,0.584-0.476,2.209-0.398,3
c0.116,1.183,0.456,2.099,0.333,3.333c-0.192,1.943,0.154,4.479-0.436,6.333"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.2-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.501" y1="-12291.5195" x2="6492.1304" y2="-12384.9688" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3351.7349)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Young_Black_1_" fill="#5C5C5C" stroke="#353535" stroke-linecap="round" stroke-linejoin="round" d="M20.278,13.25
c3.417,4.333,9.333,6.917,9.333,6.917l-1.417-3.5c0,0,7.094,4.691,8.083,4.333c0.968-0.2-1.082-3.807-1.082-3.807
s3.138,1.795,4.854,3.969c1.803,2.28,4.285,3.504,4.285,3.504S47.027,2.719,27.289,2.744C8.278,2.709,12.058,27.678,12.058,27.678
L14.695,17c0,0,0.914,5.757,1.399,4.875C17.861,15.211,18.861,11.5,20.278,13.25z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
<y:Resource id="2">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="67px" viewBox="0 0 57 67" enable-background="new 0 0 57 67" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.199-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.5" y1="-12286.8594" x2="6492.1294" y2="-12380.3086" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3350.4617)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Female_1_Red_1_" fill="#FAE1AA" stroke="#E2B354" stroke-linecap="round" stroke-linejoin="round" d="M28.372,0.5
C17.537,0.5,8.269,7.748,9.153,26.125c0.563,6.563,5.862,12.042,9.366,13.531c-2.929-10.968-0.304-25.021-0.585-25.526
c-0.281-0.505,3.536,6.728,3.536,6.728l3.183-8.312c5.541,4.28,0.393,11.309,1.049,11.058c4.26-1.631,5.34-9.228,5.34-9.228
s2.729,3.657,2.701,5.504c-0.054,3.562,2.194-6.067,2.194-6.067l1.027,2.031c6.727,9.822,3.684,16.208,1.648,22.781
c15.666-0.703,12.291-10.48,9.66-18.407C43.59,6.092,39.206,0.5,28.372,0.5z"/&gt;
&lt;linearGradient id="body_1_" gradientUnits="userSpaceOnUse" x1="95.9063" y1="-3134.2153" x2="31.5133" y2="-3134.2153" gradientTransform="matrix(0.9852 0 0 -0.9852 -34.4844 -3031.9851)"&gt;
&lt;stop offset="0" style="stop-color:#49AD33"/&gt;
&lt;stop offset="1" style="stop-color:#C2DA92"/&gt;
&lt;/linearGradient&gt;
&lt;path id="body_8_" fill="url(#body_1_)" stroke="#008D33" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-8.244-5.146-8.244-5.146
c-1.444,6.983-8.555,8.786-13.007,8.786s-11.322-2.643-11.941-9.439c0,0-4.559,1.199-9.367,5.674
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
</y:Resources>
</data>
</graphml>

BIN
docs/guide-ru/images/rbac-access-check-2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

368
docs/guide-ru/images/rbac-access-check-3.graphml

@ -0,0 +1,368 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.12.2-->
<key for="graphml" id="d0" yfiles.type="resources"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key attr.name="Description" attr.type="string" for="graph" id="d7"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d7"/>
<node id="n0">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="36.68359375" x="33.158203125" y="25.1494140625">admin<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n1">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="38.025390625" x="32.4873046875" y="25.1494140625">author<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n2">
<data key="d6">
<y:SVGNode>
<y:Geometry height="64.53585815429688" width="56.560157775878906" x="216.21992111206055" y="-132.03585815429688"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.905467987060547" y="-27.814727783203125">John, ID=2<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.113555908203125" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="1"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n3">
<data key="d6">
<y:SVGNode>
<y:Geometry height="66.76200103759766" width="56.554100036621094" x="57.22294998168945" y="-133.14892959594727"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.908496856689453" y="-27.701656341552734">Jane, ID=1<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.000484466552734" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="2"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n4">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#FF0000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.71484375" x="19.142578125" y="25.1494140625">updatePost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n5">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="89.388671875" x="6.8056640625" y="25.1494140625">updateOwnPost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n6">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="352.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="61.36328125" x="20.818359375" y="25.1494140625">createPost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n7">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="29.535858154296875" width="103.0" x="193.0" y="167.96414184570312"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.03515625" x="19.482421875" y="5.4173431396484375">AuthorRule<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<edge id="e0" source="n4" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#FF0000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n4" target="n5">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n1" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e3" source="n6" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="403.5" y="23.0"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e4" source="n1" target="n2">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e5" source="n0" target="n3">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#FF0000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e6" source="n7" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d0">
<y:Resources>
<y:Resource id="1">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="65px" viewBox="0 0 57 65" enable-background="new 0 0 57 65" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;path id="body_18_" fill="#ECECEC" stroke="#9B9B9B" stroke-miterlimit="10" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-11.244-6.146-11.244-6.146
c-1.771,1.655-5.61,3.802-10.063,3.802c-4.453,0-8.292-2.146-10.063-3.802c0,0-5.755,0.586-11.189,6.021
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;radialGradient id="SVGID_2_" cx="22.6621" cy="21.707" r="17.7954" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_2_)" stroke="#E55E03" d="M28.106,33.486c-8.112,0-12.688,4.313-12.688,10.438
c0,7.422,12.688,10.438,12.688,10.438s14.688-3.016,14.688-10.438C42.793,38.75,36.215,33.486,28.106,33.486z M26.288,53.051
c0,0-7.135-2.093-8.805-7.201c-0.222-0.682,0.147-1.156,0.795-1.521V37.8h20.188v6.663c0.235,0.352,1.109,0.737,1.229,1.387
C40.445,49.917,26.288,53.051,26.288,53.051z"/&gt;
&lt;radialGradient id="SVGID_3_" cx="15.2056" cy="831.1875" r="32.3071" gradientTransform="matrix(1 0 0 1 0.0801 -773.6914)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_3_)" stroke="#E55E03" d="M49.529,51.225c-2.239-2.24-5.041-3.724-7.396-4.67
c-2.854,5.51-14.021,7.807-14.021,7.807s-10.472-2.483-12.387-8.514c-2.439,0.771-5.787,2.287-8.749,5.25
c-5.592,5.592-6.47,11.67-6.47,11.67c0,1.938,1.575,3.492,3.523,3.492h48.51c1.946,0,3.521-1.558,3.521-3.492
C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="SVGID_4_" cx="17.0723" cy="18.4907" r="11.8931" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_4_)" stroke="#E55E03" d="M13.404,44.173c1.15-1.81,2.039-3.832,3.332-5.397
c-0.514,1.027-1.669,4.084-1.669,5.148c0,5.186,10.366,9.079,14.688,10.438c-3.472,1.627-9.134-1.498-11.334-2.359
c-3.601-1.419-4.071-3.063-5.89-4.854C12.523,47.135,12.878,45,13.404,44.173z"/&gt;
&lt;radialGradient id="SVGID_5_" cx="31.8184" cy="19.3525" r="14.63" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_5_)" stroke="#E55E03" d="M45.777,43.924c-1.317-1.568-5.11-9.424-6.604-6.617
c0.516,1.025,3.617,3.693,3.617,6.617c0,5.186-10.271,8.576-16.699,9.145c1.429,4.938,11.373,1.293,13.805-0.313
c3.563-2.354,4.563-5.133,7.854-3.705C47.754,49.045,48.006,46.574,45.777,43.924z"/&gt;
&lt;radialGradient id="SVGID_6_" cx="30.4893" cy="4.8721" r="5.2028" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_6_)" stroke="#E55E03" d="M30.777,54.167c0.357,0.836-0.153,1.983-0.352,2.813
c-0.256,1.084-0.072,2.104,0.102,3.186c0.164,1.02,0.156,2.107,0.25,3.167c0.082,0.916,0.482,1.849,0.357,2.75"/&gt;
&lt;radialGradient id="SVGID_7_" cx="23.2871" cy="5.3008" r="5.5143" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_7_)" stroke="#E55E03" d="M23.695,53.417c-0.508,0.584-0.476,2.209-0.398,3
c0.116,1.183,0.456,2.099,0.333,3.333c-0.192,1.943,0.154,4.479-0.436,6.333"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.2-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.501" y1="-12291.5195" x2="6492.1304" y2="-12384.9688" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3351.7349)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Young_Black_1_" fill="#5C5C5C" stroke="#353535" stroke-linecap="round" stroke-linejoin="round" d="M20.278,13.25
c3.417,4.333,9.333,6.917,9.333,6.917l-1.417-3.5c0,0,7.094,4.691,8.083,4.333c0.968-0.2-1.082-3.807-1.082-3.807
s3.138,1.795,4.854,3.969c1.803,2.28,4.285,3.504,4.285,3.504S47.027,2.719,27.289,2.744C8.278,2.709,12.058,27.678,12.058,27.678
L14.695,17c0,0,0.914,5.757,1.399,4.875C17.861,15.211,18.861,11.5,20.278,13.25z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
<y:Resource id="2">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="67px" viewBox="0 0 57 67" enable-background="new 0 0 57 67" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.199-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.5" y1="-12286.8594" x2="6492.1294" y2="-12380.3086" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3350.4617)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Female_1_Red_1_" fill="#FAE1AA" stroke="#E2B354" stroke-linecap="round" stroke-linejoin="round" d="M28.372,0.5
C17.537,0.5,8.269,7.748,9.153,26.125c0.563,6.563,5.862,12.042,9.366,13.531c-2.929-10.968-0.304-25.021-0.585-25.526
c-0.281-0.505,3.536,6.728,3.536,6.728l3.183-8.312c5.541,4.28,0.393,11.309,1.049,11.058c4.26-1.631,5.34-9.228,5.34-9.228
s2.729,3.657,2.701,5.504c-0.054,3.562,2.194-6.067,2.194-6.067l1.027,2.031c6.727,9.822,3.684,16.208,1.648,22.781
c15.666-0.703,12.291-10.48,9.66-18.407C43.59,6.092,39.206,0.5,28.372,0.5z"/&gt;
&lt;linearGradient id="body_1_" gradientUnits="userSpaceOnUse" x1="95.9063" y1="-3134.2153" x2="31.5133" y2="-3134.2153" gradientTransform="matrix(0.9852 0 0 -0.9852 -34.4844 -3031.9851)"&gt;
&lt;stop offset="0" style="stop-color:#49AD33"/&gt;
&lt;stop offset="1" style="stop-color:#C2DA92"/&gt;
&lt;/linearGradient&gt;
&lt;path id="body_8_" fill="url(#body_1_)" stroke="#008D33" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-8.244-5.146-8.244-5.146
c-1.444,6.983-8.555,8.786-13.007,8.786s-11.322-2.643-11.941-9.439c0,0-4.559,1.199-9.367,5.674
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
</y:Resources>
</data>
</graphml>

BIN
docs/guide-ru/images/rbac-access-check-3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

312
docs/guide-ru/images/rbac-hierarchy-1.graphml

@ -0,0 +1,312 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.12.2-->
<key for="graphml" id="d0" yfiles.type="resources"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key attr.name="Description" attr.type="string" for="graph" id="d7"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d7"/>
<node id="n0">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="36.68359375" x="33.158203125" y="25.1494140625">admin<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n1">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="38.025390625" x="32.4873046875" y="25.1494140625">author<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n2">
<data key="d6">
<y:SVGNode>
<y:Geometry height="64.53585815429688" width="56.560157775878906" x="216.21992111206055" y="-132.03585815429688"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.905467987060547" y="-27.814727783203125">John, ID=2<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.113555908203125" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="1"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n3">
<data key="d6">
<y:SVGNode>
<y:Geometry height="66.76200103759766" width="56.554100036621094" x="57.22294998168945" y="-133.14892959594727"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.908496856689453" y="-27.701656341552734">Jane, ID=1<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.000484466552734" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="2"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n4">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.71484375" x="19.142578125" y="25.1494140625">updatePost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n5">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="61.36328125" x="20.818359375" y="25.1494140625">createPost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<edge id="e0" source="n4" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n1" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n1" target="n2">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e3" source="n0" target="n3">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e4" source="n5" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d0">
<y:Resources>
<y:Resource id="1">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="65px" viewBox="0 0 57 65" enable-background="new 0 0 57 65" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;path id="body_18_" fill="#ECECEC" stroke="#9B9B9B" stroke-miterlimit="10" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-11.244-6.146-11.244-6.146
c-1.771,1.655-5.61,3.802-10.063,3.802c-4.453,0-8.292-2.146-10.063-3.802c0,0-5.755,0.586-11.189,6.021
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;radialGradient id="SVGID_2_" cx="22.6621" cy="21.707" r="17.7954" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_2_)" stroke="#E55E03" d="M28.106,33.486c-8.112,0-12.688,4.313-12.688,10.438
c0,7.422,12.688,10.438,12.688,10.438s14.688-3.016,14.688-10.438C42.793,38.75,36.215,33.486,28.106,33.486z M26.288,53.051
c0,0-7.135-2.093-8.805-7.201c-0.222-0.682,0.147-1.156,0.795-1.521V37.8h20.188v6.663c0.235,0.352,1.109,0.737,1.229,1.387
C40.445,49.917,26.288,53.051,26.288,53.051z"/&gt;
&lt;radialGradient id="SVGID_3_" cx="15.2056" cy="831.1875" r="32.3071" gradientTransform="matrix(1 0 0 1 0.0801 -773.6914)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_3_)" stroke="#E55E03" d="M49.529,51.225c-2.239-2.24-5.041-3.724-7.396-4.67
c-2.854,5.51-14.021,7.807-14.021,7.807s-10.472-2.483-12.387-8.514c-2.439,0.771-5.787,2.287-8.749,5.25
c-5.592,5.592-6.47,11.67-6.47,11.67c0,1.938,1.575,3.492,3.523,3.492h48.51c1.946,0,3.521-1.558,3.521-3.492
C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="SVGID_4_" cx="17.0723" cy="18.4907" r="11.8931" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_4_)" stroke="#E55E03" d="M13.404,44.173c1.15-1.81,2.039-3.832,3.332-5.397
c-0.514,1.027-1.669,4.084-1.669,5.148c0,5.186,10.366,9.079,14.688,10.438c-3.472,1.627-9.134-1.498-11.334-2.359
c-3.601-1.419-4.071-3.063-5.89-4.854C12.523,47.135,12.878,45,13.404,44.173z"/&gt;
&lt;radialGradient id="SVGID_5_" cx="31.8184" cy="19.3525" r="14.63" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_5_)" stroke="#E55E03" d="M45.777,43.924c-1.317-1.568-5.11-9.424-6.604-6.617
c0.516,1.025,3.617,3.693,3.617,6.617c0,5.186-10.271,8.576-16.699,9.145c1.429,4.938,11.373,1.293,13.805-0.313
c3.563-2.354,4.563-5.133,7.854-3.705C47.754,49.045,48.006,46.574,45.777,43.924z"/&gt;
&lt;radialGradient id="SVGID_6_" cx="30.4893" cy="4.8721" r="5.2028" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_6_)" stroke="#E55E03" d="M30.777,54.167c0.357,0.836-0.153,1.983-0.352,2.813
c-0.256,1.084-0.072,2.104,0.102,3.186c0.164,1.02,0.156,2.107,0.25,3.167c0.082,0.916,0.482,1.849,0.357,2.75"/&gt;
&lt;radialGradient id="SVGID_7_" cx="23.2871" cy="5.3008" r="5.5143" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_7_)" stroke="#E55E03" d="M23.695,53.417c-0.508,0.584-0.476,2.209-0.398,3
c0.116,1.183,0.456,2.099,0.333,3.333c-0.192,1.943,0.154,4.479-0.436,6.333"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.2-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.501" y1="-12291.5195" x2="6492.1304" y2="-12384.9688" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3351.7349)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Young_Black_1_" fill="#5C5C5C" stroke="#353535" stroke-linecap="round" stroke-linejoin="round" d="M20.278,13.25
c3.417,4.333,9.333,6.917,9.333,6.917l-1.417-3.5c0,0,7.094,4.691,8.083,4.333c0.968-0.2-1.082-3.807-1.082-3.807
s3.138,1.795,4.854,3.969c1.803,2.28,4.285,3.504,4.285,3.504S47.027,2.719,27.289,2.744C8.278,2.709,12.058,27.678,12.058,27.678
L14.695,17c0,0,0.914,5.757,1.399,4.875C17.861,15.211,18.861,11.5,20.278,13.25z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
<y:Resource id="2">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="67px" viewBox="0 0 57 67" enable-background="new 0 0 57 67" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.199-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.5" y1="-12286.8594" x2="6492.1294" y2="-12380.3086" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3350.4617)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Female_1_Red_1_" fill="#FAE1AA" stroke="#E2B354" stroke-linecap="round" stroke-linejoin="round" d="M28.372,0.5
C17.537,0.5,8.269,7.748,9.153,26.125c0.563,6.563,5.862,12.042,9.366,13.531c-2.929-10.968-0.304-25.021-0.585-25.526
c-0.281-0.505,3.536,6.728,3.536,6.728l3.183-8.312c5.541,4.28,0.393,11.309,1.049,11.058c4.26-1.631,5.34-9.228,5.34-9.228
s2.729,3.657,2.701,5.504c-0.054,3.562,2.194-6.067,2.194-6.067l1.027,2.031c6.727,9.822,3.684,16.208,1.648,22.781
c15.666-0.703,12.291-10.48,9.66-18.407C43.59,6.092,39.206,0.5,28.372,0.5z"/&gt;
&lt;linearGradient id="body_1_" gradientUnits="userSpaceOnUse" x1="95.9063" y1="-3134.2153" x2="31.5133" y2="-3134.2153" gradientTransform="matrix(0.9852 0 0 -0.9852 -34.4844 -3031.9851)"&gt;
&lt;stop offset="0" style="stop-color:#49AD33"/&gt;
&lt;stop offset="1" style="stop-color:#C2DA92"/&gt;
&lt;/linearGradient&gt;
&lt;path id="body_8_" fill="url(#body_1_)" stroke="#008D33" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-8.244-5.146-8.244-5.146
c-1.444,6.983-8.555,8.786-13.007,8.786s-11.322-2.643-11.941-9.439c0,0-4.559,1.199-9.367,5.674
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
</y:Resources>
</data>
</graphml>

BIN
docs/guide-ru/images/rbac-hierarchy-1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

368
docs/guide-ru/images/rbac-hierarchy-2.graphml

@ -0,0 +1,368 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.12.2-->
<key for="graphml" id="d0" yfiles.type="resources"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key attr.name="Description" attr.type="string" for="graph" id="d7"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d7"/>
<node id="n0">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="36.68359375" x="33.158203125" y="25.1494140625">admin<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n1">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="-11.5"/>
<y:Fill color="#ADF4A6" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="38.025390625" x="32.4873046875" y="25.1494140625">author<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n2">
<data key="d6">
<y:SVGNode>
<y:Geometry height="64.53585815429688" width="56.560157775878906" x="216.21992111206055" y="-132.03585815429688"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.905467987060547" y="-27.814727783203125">John, ID=2<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.113555908203125" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="1"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n3">
<data key="d6">
<y:SVGNode>
<y:Geometry height="66.76200103759766" width="56.554100036621094" x="57.22294998168945" y="-133.14892959594727"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.908496856689453" y="-27.701656341552734">Jane, ID=1<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.000484466552734" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="2"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n4">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="34.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.71484375" x="19.142578125" y="25.1494140625">updatePost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n5">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="193.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="89.388671875" x="6.8056640625" y="25.1494140625">updateOwnPost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n6">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="69.0" width="103.0" x="352.0" y="197.5"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="61.36328125" x="20.818359375" y="25.1494140625">createPost<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n7">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="29.535858154296875" width="103.0" x="193.0" y="167.96414184570312"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.03515625" x="19.482421875" y="5.4173431396484375">AuthorRule<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="roundrectangle"/>
</y:ShapeNode>
</data>
</node>
<edge id="e0" source="n4" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n4" target="n5">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n1" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e3" source="n6" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="403.5" y="23.0"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e4" source="n1" target="n2">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e5" source="n0" target="n3">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e6" source="n7" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d0">
<y:Resources>
<y:Resource id="1">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="65px" viewBox="0 0 57 65" enable-background="new 0 0 57 65" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;path id="body_18_" fill="#ECECEC" stroke="#9B9B9B" stroke-miterlimit="10" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-11.244-6.146-11.244-6.146
c-1.771,1.655-5.61,3.802-10.063,3.802c-4.453,0-8.292-2.146-10.063-3.802c0,0-5.755,0.586-11.189,6.021
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;radialGradient id="SVGID_2_" cx="22.6621" cy="21.707" r="17.7954" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_2_)" stroke="#E55E03" d="M28.106,33.486c-8.112,0-12.688,4.313-12.688,10.438
c0,7.422,12.688,10.438,12.688,10.438s14.688-3.016,14.688-10.438C42.793,38.75,36.215,33.486,28.106,33.486z M26.288,53.051
c0,0-7.135-2.093-8.805-7.201c-0.222-0.682,0.147-1.156,0.795-1.521V37.8h20.188v6.663c0.235,0.352,1.109,0.737,1.229,1.387
C40.445,49.917,26.288,53.051,26.288,53.051z"/&gt;
&lt;radialGradient id="SVGID_3_" cx="15.2056" cy="831.1875" r="32.3071" gradientTransform="matrix(1 0 0 1 0.0801 -773.6914)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_3_)" stroke="#E55E03" d="M49.529,51.225c-2.239-2.24-5.041-3.724-7.396-4.67
c-2.854,5.51-14.021,7.807-14.021,7.807s-10.472-2.483-12.387-8.514c-2.439,0.771-5.787,2.287-8.749,5.25
c-5.592,5.592-6.47,11.67-6.47,11.67c0,1.938,1.575,3.492,3.523,3.492h48.51c1.946,0,3.521-1.558,3.521-3.492
C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="SVGID_4_" cx="17.0723" cy="18.4907" r="11.8931" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_4_)" stroke="#E55E03" d="M13.404,44.173c1.15-1.81,2.039-3.832,3.332-5.397
c-0.514,1.027-1.669,4.084-1.669,5.148c0,5.186,10.366,9.079,14.688,10.438c-3.472,1.627-9.134-1.498-11.334-2.359
c-3.601-1.419-4.071-3.063-5.89-4.854C12.523,47.135,12.878,45,13.404,44.173z"/&gt;
&lt;radialGradient id="SVGID_5_" cx="31.8184" cy="19.3525" r="14.63" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_5_)" stroke="#E55E03" d="M45.777,43.924c-1.317-1.568-5.11-9.424-6.604-6.617
c0.516,1.025,3.617,3.693,3.617,6.617c0,5.186-10.271,8.576-16.699,9.145c1.429,4.938,11.373,1.293,13.805-0.313
c3.563-2.354,4.563-5.133,7.854-3.705C47.754,49.045,48.006,46.574,45.777,43.924z"/&gt;
&lt;radialGradient id="SVGID_6_" cx="30.4893" cy="4.8721" r="5.2028" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_6_)" stroke="#E55E03" d="M30.777,54.167c0.357,0.836-0.153,1.983-0.352,2.813
c-0.256,1.084-0.072,2.104,0.102,3.186c0.164,1.02,0.156,2.107,0.25,3.167c0.082,0.916,0.482,1.849,0.357,2.75"/&gt;
&lt;radialGradient id="SVGID_7_" cx="23.2871" cy="5.3008" r="5.5143" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FCB57A"/&gt;
&lt;stop offset="1" style="stop-color:#FF8C36"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_7_)" stroke="#E55E03" d="M23.695,53.417c-0.508,0.584-0.476,2.209-0.398,3
c0.116,1.183,0.456,2.099,0.333,3.333c-0.192,1.943,0.154,4.479-0.436,6.333"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.2-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.501" y1="-12291.5195" x2="6492.1304" y2="-12384.9688" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3351.7349)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Young_Black_1_" fill="#5C5C5C" stroke="#353535" stroke-linecap="round" stroke-linejoin="round" d="M20.278,13.25
c3.417,4.333,9.333,6.917,9.333,6.917l-1.417-3.5c0,0,7.094,4.691,8.083,4.333c0.968-0.2-1.082-3.807-1.082-3.807
s3.138,1.795,4.854,3.969c1.803,2.28,4.285,3.504,4.285,3.504S47.027,2.719,27.289,2.744C8.278,2.709,12.058,27.678,12.058,27.678
L14.695,17c0,0,0.914,5.757,1.399,4.875C17.861,15.211,18.861,11.5,20.278,13.25z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
<y:Resource id="2">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="67px" viewBox="0 0 57 67" enable-background="new 0 0 57 67" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.199-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.5" y1="-12286.8594" x2="6492.1294" y2="-12380.3086" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3350.4617)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/&gt;
&lt;path id="Hair_Female_1_Red_1_" fill="#FAE1AA" stroke="#E2B354" stroke-linecap="round" stroke-linejoin="round" d="M28.372,0.5
C17.537,0.5,8.269,7.748,9.153,26.125c0.563,6.563,5.862,12.042,9.366,13.531c-2.929-10.968-0.304-25.021-0.585-25.526
c-0.281-0.505,3.536,6.728,3.536,6.728l3.183-8.312c5.541,4.28,0.393,11.309,1.049,11.058c4.26-1.631,5.34-9.228,5.34-9.228
s2.729,3.657,2.701,5.504c-0.054,3.562,2.194-6.067,2.194-6.067l1.027,2.031c6.727,9.822,3.684,16.208,1.648,22.781
c15.666-0.703,12.291-10.48,9.66-18.407C43.59,6.092,39.206,0.5,28.372,0.5z"/&gt;
&lt;linearGradient id="body_1_" gradientUnits="userSpaceOnUse" x1="95.9063" y1="-3134.2153" x2="31.5133" y2="-3134.2153" gradientTransform="matrix(0.9852 0 0 -0.9852 -34.4844 -3031.9851)"&gt;
&lt;stop offset="0" style="stop-color:#49AD33"/&gt;
&lt;stop offset="1" style="stop-color:#C2DA92"/&gt;
&lt;/linearGradient&gt;
&lt;path id="body_8_" fill="url(#body_1_)" stroke="#008D33" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-8.244-5.146-8.244-5.146
c-1.444,6.983-8.555,8.786-13.007,8.786s-11.322-2.643-11.941-9.439c0,0-4.559,1.199-9.367,5.674
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
</y:Resources>
</data>
</graphml>

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

Loading…
Cancel
Save