Browse Source

Merge branch 'master' of git://github.com/yiisoft/yii2

Conflicts:
	framework/CHANGELOG.md
tags/2.0.0
Qiang Xue 10 years ago
parent
commit
2e105d2a93
  1. 12
      docs/guide-es/README.md
  2. 44
      docs/guide-es/concept-components.md
  3. 43
      docs/guide-es/concept-configurations.md
  4. 71
      docs/guide-es/concept-service-locator.md
  5. 2
      docs/guide-es/images/application-lifecycle.graphml
  6. BIN
      docs/guide-es/images/application-lifecycle.png
  7. BIN
      docs/guide-es/images/application-structure.png
  8. 24
      docs/guide-es/runtime-bootstrapping.md
  9. 14
      docs/guide-es/runtime-overview.md
  10. 108
      docs/guide-es/runtime-requests.md
  11. 51
      docs/guide-es/runtime-routing.md
  12. 4
      docs/guide-es/structure-filters.md
  13. 12
      docs/guide-es/structure-models.md
  14. 31
      docs/guide-es/structure-modules.md
  15. 288
      docs/guide-es/structure-views.md
  16. 7
      docs/guide-es/structure-widgets.md
  17. 2
      docs/guide-fr/README.md
  18. 36
      docs/guide-fr/images/application-lifecycle.graphml
  19. BIN
      docs/guide-fr/images/application-lifecycle.png
  20. 15
      docs/guide-fr/images/application-structure.graphml
  21. BIN
      docs/guide-fr/images/application-structure.png
  22. 6
      docs/guide-fr/start-gii.md
  23. 39
      docs/guide-fr/start-looking-ahead.md
  24. 20
      docs/guide-fr/start-workflow.md
  25. 117
      docs/guide-fr/structure-entry-scripts.md
  26. 27
      docs/guide-fr/structure-overview.md
  27. 37
      docs/guide-uz/intro-yii.md
  28. 4
      docs/guide/README.md
  29. 3
      docs/guide/caching-data.md
  30. 16
      docs/guide/db-active-record.md
  31. 2
      docs/guide/db-dao.md
  32. 6
      docs/guide/db-migrations.md
  33. 2
      docs/guide/input-forms.md
  34. 2
      docs/guide/input-validation.md
  35. 4
      docs/guide/output-data-widgets.md
  36. 146
      docs/guide/output-formatter.md
  37. 2
      docs/guide/runtime-handling-errors.md
  38. 2
      docs/guide/runtime-logging.md
  39. 5
      docs/guide/runtime-sessions-cookies.md
  40. 6
      docs/guide/security-authorization.md
  41. 2
      docs/guide/start-databases.md
  42. 0
      docs/guide/structure-application-components.md
  43. 2
      docs/guide/structure-applications.md
  44. 2
      docs/guide/structure-views.md
  45. 10
      docs/guide/tutorial-console.md
  46. 9
      docs/guide/tutorial-i18n.md
  47. 2
      docs/guide/tutorial-performance-tuning.md
  48. 2
      docs/guide/tutorial-yii-integration.md
  49. 2
      docs/guide/widget-bootstrap.md
  50. 46
      docs/internals-es/translation-workflow.md
  51. 2
      docs/internals-pt-BR/translation-workflow.md
  52. 2
      docs/internals-ru/translation-workflow.md
  53. 2
      docs/internals-uz/translation-workflow.md
  54. 1
      docs/internals/translation-teams.md
  55. 2
      docs/internals/translation-workflow.md
  56. 47
      extensions/authclient/BaseClient.php
  57. 2
      extensions/authclient/CHANGELOG.md
  58. 1
      extensions/authclient/README.md
  59. 27
      extensions/bootstrap/BootstrapThemeAsset.php
  60. 2
      extensions/codeception/README.md
  61. 2
      extensions/elasticsearch/ActiveQuery.php
  62. 2
      extensions/elasticsearch/README.md
  63. 6
      extensions/gii/generators/model/Generator.php
  64. 4
      extensions/mongodb/ActiveQuery.php
  65. 2
      extensions/mongodb/CHANGELOG.md
  66. 2
      extensions/mongodb/Connection.php
  67. 6
      extensions/redis/ActiveQuery.php
  68. 4
      extensions/sphinx/ActiveQuery.php
  69. 2
      extensions/sphinx/CHANGELOG.md
  70. 475
      extensions/sphinx/Query.php
  71. 117
      extensions/sphinx/QueryBuilder.php
  72. 2
      framework/CHANGELOG.md
  73. 20
      framework/base/Controller.php
  74. 18
      framework/db/ActiveQuery.php
  75. 4
      framework/db/ActiveQueryInterface.php
  76. 8
      framework/db/ActiveRecordInterface.php
  77. 12
      framework/db/ActiveRelationTrait.php
  78. 8
      framework/db/BaseActiveRecord.php
  79. 4
      framework/db/Connection.php
  80. 6
      framework/filters/Cors.php
  81. 4
      framework/helpers/BaseHtml.php
  82. 6
      framework/i18n/Formatter.php
  83. 1
      framework/messages/config.php
  84. 86
      framework/messages/el/yii.php
  85. 2
      framework/views/errorHandler/callStackItem.php
  86. 4
      framework/web/DbSession.php
  87. 98
      tests/unit/extensions/authclient/BaseClientTest.php
  88. 38
      tests/unit/extensions/mongodb/ConnectionTest.php
  89. 16
      tests/unit/extensions/sphinx/QueryTest.php
  90. 137
      tests/unit/framework/web/UserTest.php

12
docs/guide-es/README.md

@ -1,4 +1,4 @@
Guía Definitiva de Yii 2.0
Guía Definitiva de Yii 2.0
==========================
Este tutorial se publica con arreglo a los [Términos de Documentación Yii](http://www.yiiframework.com/doc/terms/).
@ -40,7 +40,7 @@ Estructura de una aplicación
* [Filtros](structure-filters.md)
* [Widgets](structure-widgets.md)
* [Módulos](structure-modules.md)
* **TBD** [Recursos](structure-assets.md)
* **TBD** [Assets](structure-assets.md)
* **TBD** [Extensiones](structure-extensions.md)
@ -48,9 +48,9 @@ Gestión de las peticiones
-------------------------
* [Información general](runtime-overview.md)
* **TBD** [Bootstrapping](runtime-bootstrapping.md)
* **TBD** [Rutas](runtime-routing.md)
* **TBD** [Peticiones](runtime-requests.md)
* [Bootstrapping](runtime-bootstrapping.md)
* [Routing](runtime-routing.md)
* [Requests](runtime-requests.md)
* **TBD** [Respuestas](runtime-responses.md)
* **TBD** [Sesiones y Cookies](runtime-sessions-cookies.md)
* **TBD** [Procesamiento y generación de las URL](runtime-url-handling.md)
@ -68,7 +68,7 @@ Conceptos clave
* [Configuraciones](concept-configurations.md)
* [Alias](concept-aliases.md)
* [Autocarga de clases](concept-autoloading.md)
* **TBD** [Localizador de servicios (Service Locator)](concept-service-locator.md)
* [Localizador de servicios (Service Locator)](concept-service-locator.md)
* **TBD** [Contenedor de inyección de dependencia](concept-di-container.md)

44
docs/guide-es/concept-components.md

@ -1,17 +1,14 @@
Componentes
Componentes
===========
Los componentes son los principales bloques de construcción de las aplicaciones Yii. Los componentes son instancias de
[[yii\base\Component]] o de una clase extendida. Las tres características principales que los componentes proporcionan
Los componentes son los principales bloques de construcción de las aplicaciones Yii. Los componentes son instancias de [[yii\base\Component]] o de una clase extendida. Las tres características principales que los componentes proporcionan
a las otras clases son:
* [Propiedades](concept-properties.md)
* [Eventos](concept-events.md)
* [Comportamientos](concept-behaviors.md)
Por separado y combinadas, estas características hacen que las clases Yii sean mucho mas personalizables y sean mucho
más fáciles de usar. Por ejemplo, el incluido [[yii\jui\DatePicker|widget de selección de fecha]], un componente de la
interfaz de usuario, puede ser utilizado en una [vista](structure-view.md) para generar un selector de fechas interactivo:
Por separado y combinadas, estas características hacen que las clases Yii sean mucho mas personalizables y sean mucho más fáciles de usar. Por ejemplo, el incluido [[yii\jui\DatePicker|widget de selección de fecha]], un componente de la interfaz de usuario, puede ser utilizado en una [vista](structure-view.md) para generar un DatePicker interactivo:
```php
use yii\jui\DatePicker;
@ -25,22 +22,16 @@ echo DatePicker::widget([
]);
```
Las propiedades del widget son facilmente modificables porque la clase se extiende de [[yii\base\Component]].
Las propiedades del widget son fácilmente modificables porque la clase se extiende de [[yii\base\Component]].
Mientras que los componentes son muy potentes, son un poco más pesados que los objetos normales, debido al hecho de que
necesitan más memoria y tiempo de CPU para poder soportar [eventos](concept-events.md) y [comportamientos](concept-behaviors.md) en particular.
Si tus componentes no necesitan estas dos características, deberías considerar extender tu componente directamente de
[[yii\base\Object]] en vez de [[yii\base\Component]]. De esta manera harás que tus componentes sean mucho más eficientes que
que objetos PHP normales, pero con el añadido soporte para [propiedades](concept-properties.md).
Mientras que los componentes son muy potentes, son un poco más pesados que los objetos normales, debido al hecho de que necesitan más memoria y tiempo de CPU para poder soportar [eventos](concept-events.md) y [comportamientos](concept-behaviors.md) en particular.
Si tus componentes no necesitan estas dos características, deberías considerar extender tu componente directamente de [[yii\base\Object]] en vez de [[yii\base\Component]]. De esta manera harás que tus componentes sean mucho más eficientes que objetos PHP normales, pero con el añadido soporte para [propiedades](concept-properties.md).
Cuando extiendes tu clase de [[yii\base\Component]] o [[yii\base\Object]], se recomienda que sigas las siguientes
convenciones:
Cuando extiendes tu clase de [[yii\base\Component]] o [[yii\base\Object]], se recomienda que sigas las siguientes convenciones:
- Si sobrescribes el constructor, especifica un parámetro `$config` como el *último* parámetro del constructor, y después
pasa este parámetro al constructor de la clase "padre".
- Si sobrescribes el constructor, especifica un parámetro `$config` como el *último* parámetro del constructor, y después pasa este parámetro al constructor de la clase "padre".
- Siempre llama al constructor del "padre" al *final* de su propio constructor.
- Si sobrescribes el método [[yii\base\Object::init()]], asegúrate de que llamas a la implementación de la clase "padre"
*al principio* de tu método `init`.
- Si sobrescribes el método [[yii\base\Object::init()]], asegúrate de que llamas a la implementación de la clase "padre" *al principio* de tu método `init`.
Por ejemplo:
@ -65,7 +56,7 @@ class MyClass extends Object
{
parent::init();
// ... inicialización despues de la configuración esta siendo aplicada
// ... inicialización después de la configuración esta siendo aplicada
}
}
```
@ -82,19 +73,14 @@ $component = \Yii::createObject([
], [1, 2]);
```
> Información: Mientras que el enfoque de llamar [[Yii::createObject()]] parece mucho más complicado, es mucho más potente
debido al hecho de que se implementa en la parte superior de un [contenedor de inyección de dependencia](concept-di-container.md).
> Información: Mientras que el enfoque de llamar [[Yii::createObject()]] parece mucho más complicado, es mucho más potente debido al hecho de que se implementa en la parte superior de un [contenedor de inyección de dependencia](concept-di-container.md).
La clase [[yii\base\Object]] hace cumplir el siguiente ciclo de vida del objeto:
1. Pre-inicialización en el constructor. Puedes establecer los valores predeterminados de propiedades aquí.
2. Configuración del objeto a través de `$config`. La configuración puede sobrescribir los valores prdeterminados dentro
del constructor.
3. Post-inicialización dentro de [[yii\base\Object::init()|init()]]. Puedes sobrescribir este método para realizar
comprobaciones de validez y normalización de las propiedades.
4. LLamadas a métodos del objeto.
2. Configuración del objeto a través de `$config`. La configuración puede sobrescribir los valores prdeterminados dentro del constructor.
3. Post-inicialización dentro de [[yii\base\Object::init()|init()]]. Puedes sobrescribir este método para realizar comprobaciones de validez y normalización de las propiedades.
4. Llamadas a métodos del objeto.
Los tres primeros pasos ocurren dentro del constructor del objeto. Esto significa que una vez obtengas la instancia de
un objeto, ésta ha sido inicializada para que puedas utilizarla adecuadamente.
Los tres primeros pasos ocurren dentro del constructor del objeto. Esto significa que una vez obtengas la instancia de un objeto, ésta ha sido inicializada para que puedas utilizarla adecuadamente.

43
docs/guide-es/concept-configurations.md

@ -1,9 +1,9 @@
Configuración
Configuración
==============
Las configuraciones se utilizan ampliamente en Yii al crear nuevos objetos o inicializar los objetos existentes. Las configuraciones por lo general incluyen el nombre de la clase del objeto que se está creando, y una lista de los valores iniciales que debería ser asignada al del objeto [propiedades](concept-properties.md). Las configuraciones también pueden incluir una lista de manipuladores que deban imponerse a del objeto [eventos](concept-events.md) y/o una lista de [comportamiento](concept-behaviors.md) que también ha de atribuirse al objeto.
Las configuraciones se utilizan ampliamente en Yii al crear nuevos objetos o inicializar los objetos existentes. Las configuraciones por lo general incluyen el nombre de la clase del objeto que se está creando, y una lista de los valores iniciales que deberían ser asignadas a las del [propiedades](concept-properties.md) objeto. Las configuraciones también pueden incluir una lista de manipuladores que deban imponerse a del objeto [eventos](concept-events.md) y/o una lista de [comportamientos](concept-behaviors.md) que también ha de atribuirse al objeto.
A continuación, una configuración que se utiliza para crear e inicializar una conexión de base de datos:
A continuación, una configuración que se utiliza para crear e inicializar una conexión a base de datos:
```php
$config = [
@ -16,9 +16,7 @@ $config = [
$db = Yii::createObject($config);
```
El [[Yii::createObject()]] método toma una matriz de configuración como su argumento, y crea un objeto creando instanciando la clase llamada en la configuración. Cuando se crea una instancia del objeto, el resto de la configuración se utilizará para inicializar las propiedades del objeto, controladores de eventos y comportamientos.
El método [[Yii::createObject()]] toma una matriz de configuración como su argumento, y crea un objeto intanciando la clase llamada en la configuración. Cuando se crea una instancia del objeto, el resto de la configuración se utilizará para inicializar las propiedades del objeto, controladores de eventos y comportamientos.
Si usted ya tiene un objeto, puede usar [[Yii::configure()]] para inicializar las propiedades del objeto con una matriz de configuración:
@ -26,7 +24,7 @@ Si usted ya tiene un objeto, puede usar [[Yii::configure()]] para inicializar la
Yii::configure($object, $config);
```
Tenga en cuenta que, en este caso, la matriz de configuración no debe contener un elemento `class`.
Tenga en cuenta que en este caso, la matriz de configuración no debe contener un elemento `class`.
## Formato de Configuración <a name="configuration-format"></a>
@ -44,9 +42,9 @@ El formato de una configuración se puede describir formalmente como:
donde
* El elemento `class` especifica un nombre de clase completo para el objeto que se está creando.
* Los elementos `propertyName` especifica los valores iniciales de la propiedad con nombre. Las claves son los nombres de las propiedades y los valores son los valores iniciales correspondientes. Sólo las variables miembro públicas y [propiedades](concept-properties.md) definido por getters/setters se pueden configurar.
* Los elementos `on eventName` especifican qué manejadores deberán adjuntarse al del objeto [eventos](concept-events.md). Observe que las claves de matriz se forman prefijando nombres de eventos con `on`. Por favor, consulte el [Eventos] sección(concept-events.md) para los formatos de controlador de eventos compatibles.
* Los elementos `as behaviorName` especifican qué [comportamiento](concept-behaviors.md) deben adjuntarse al objeto. Observe que las claves de matriz se forman prefijando nombres de comportamiento con `as`; el valor, `$ behaviorConfig`, representa la configuración para la creación de un comportamiento, como una configuración normal se describe aquí.
* Los elementos `propertyName` especifica los valores iniciales de la propiedad con nombre. Las claves son los nombres de las propiedades y los valores son los valores iniciales correspondientes. Sólo los miembros de variables públicas y [propiedades](concept-properties.md) definidas por getters/setters se pueden configurar.
* Los elementos `on eventName` especifican qué manipuladores deberán adjuntarse al del objeto [eventos](concept-events.md). Observe que las claves de matriz se forman prefijando nombres de eventos con `on`. Por favor, consulte la sección [Eventos](concept-events.md) para los formatos de controlador de eventos compatibles.
* Los elementos `as behaviorName` especifican qué [comportamientos](concept-behaviors.md) deben adjuntarse al objeto. Observe que las claves de matriz se forman prefijando nombres de comportamiento con `as`; el valor, `$behaviorConfig`, representa la configuración para la creación de un comportamiento, como una configuración normal descrita aquí.
A continuación se muestra un ejemplo de una configuración con los valores de propiedad iniciales, controladores de eventos y comportamientos:
@ -72,7 +70,7 @@ Las configuraciones se utilizan en muchos lugares en Yii. Al comienzo de esta se
### Configuraciones de aplicación <a name="application-configurations"></a>
Configuración para una [aplicación](structure-applications.md) es probablemente una de las configuraciones más complejas. Esto se debe a la clase [[yii\web\Application|application]] tiene un montón de propiedades y eventos configurables. Más importante aún, su propiedad [[yii\web\Application::components|components]] que puede recibir una gran variedad de configuraciones para crear componentes que se registran a través de la aplicación. El siguiente es un resumen de la aplicación archivo de configuración de la [plantilla básica de la aplicación](start-basic.md).
Configuración para una [aplicación](structure-applications.md) es probablemente una de las configuraciones más complejas. Esto se debe a que la clase [[yii\web\Application|application]] tiene un montón de propiedades y eventos configurables. Más importante aún, su propiedad [[yii\web\Application::components|components]] que puede recibir una gran variedad de configuraciones para crear componentes que se registran a través de la aplicación. Lo siguiente es un resumen del archivo de configuración de la aplicación para la [plantilla básica de la aplicación](start-basic.md).
```php
$config = [
@ -112,12 +110,12 @@ La configuración no tiene una clave `class`. Esto es porque se utiliza como sig
(new yii\web\Application($config))->run();
```
Para más detalles sobre la configuración de la propiedad `components` de una aplicación se puede encontrar en la [Aplicación](structure-applications.md) sección y la sección [Localizador de Servicio](concept-service-locator.md).
Para más detalles sobre la configuración de la propiedad `components` de una aplicación se puede encontrar en la sección [Aplicación](structure-applications.md) y la sección [Localizador de Servicio](concept-service-locator.md).
### Configuración Widget <a name="widget-configurations"></a>
Cuando se utiliza [widgets](structure-widgets.md), a menudo es necesario utilizar las configuraciones para personalizar las propiedades de widgets. Tanto los metodos [[yii\base\Widget::widget()]] y [[yii\base\Widget::begin()]] puede usarse para crear un widget. Toman un arreglo de configuración, como la siguiente,
Cuando se utiliza [widgets](structure-widgets.md), a menudo es necesario utilizar las configuraciones para personalizar las propiedades de widgets. Tanto los metodos [[yii\base\Widget::widget()]] y [[yii\base\Widget::begin()]] pueden usarse para crear un widget. Toman un arreglo de configuración, como el siguiente,
```php
use yii\widgets\Menu;
@ -131,15 +129,15 @@ echo Menu::widget([
],
]);
```
El código anterior crea un widget `Menu` e inicializa su propiedad `activeItems` es falsa.
La propiedad `items` también se configura con elementos de menú que se muestran.
El código anterior crea un widget `Menu` e inicializa su propiedad `activeItems` en falsa. La propiedad `items` también se configura con elementos de menú que se muestran.
Tenga en cuenta que debido a que el nombre de la clase ya está dado, la matriz de configuración no deben tener la clave `class`.
## Archivos de Configuración <a name="configuration-files"></a>
Cuando una configuración es muy compleja, una práctica común es almacenar en uno o múltiples archivos PHP, conocidos como *Los archivos de configuración*. Un archivo de configuración devuelve un array de PHP que representa la configuración. Por ejemplo, es posible mantener una configuración de la aplicación en un archivo llamado `web.php`, como el siguiente,
Cuando una configuración es muy compleja, una práctica común es almacenarla en uno o múltiples archivos PHP, conocidos como *Los archivos de configuración*. Un archivo de configuración devuelve un array de PHP que representa la configuración. Por ejemplo, es posible mantener una configuración de la aplicación en un archivo llamado `web.php`, como el siguiente,
```php
return [
@ -150,8 +148,7 @@ return [
];
```
Debido a la configuración `componentes` es compleja también, se guarda en un archivo separado llamado `components.php`
y "requerir" este archivo en `web.php` como se muestra arriba. El contenido de `components.php` es el siguiente,
Debido a que la configuración `componentes` es compleja también, se guarda en un archivo separado llamado `components.php` y "requerir" este archivo en `web.php` como se muestra arriba. El contenido de `components.php` es el siguiente,
```php
return [
@ -190,9 +187,9 @@ $config = require('path/to/web.php');
## Configuraciones por Defecto <a name="default-configurations"></a>
El método [[Yii::createObject()]] es implementado en base a [contenedor de inyección de dependencia](concept-di-container.md). Le permite especificar un conjunto de los llamados *configuraciones predeterminadas* que se aplicarán a todos los casos de las clases especificadas cuando se crean utilizando [[Yii::createObject()]]. Las configuraciones por defecto se puede especificar llamando `Yii::$container->set()` en el codigo [bootstrapping](runtime-bootstrapping.md).
El método [[Yii::createObject()]] es implementado en base a [contenedor de inyección de dependencia](concept-di-container.md). Le permite especificar un conjunto de los llamados *configuraciones predeterminadas* que se aplicarán a todos los casos de las clases especificadas cuando se crean utilizando [[Yii::createObject()]]. Las configuraciones por defecto se puede especificar llamando `Yii::$container->set()` en el código [bootstrapping](runtime-bootstrapping.md).
Por ejemplo, si desea personalizar [[yii\widgets\LinkPager]] para que TODOS los buscas enlace mostrarán como máximo 5 botones de la página (el valor por defecto es 10), puede utilizar el siguiente código para lograr este objetivo,
Por ejemplo, si desea personalizar [[yii\widgets\LinkPager]] para que TODO enlace de búsqueda muestre como máximo 5 botones de página (el valor por defecto es 10), puede utilizar el siguiente código para lograr este objetivo,
```php
\Yii::$container->set('yii\widgets\LinkPager', [
@ -204,7 +201,7 @@ Sin utilizar las configuraciones predeterminadas, usted tendría que configurar
## Constantes de Entorno <a name="environment-constants"></a>
Las configuraciones a menudo varían de acuerdo al entorno en que se ejecuta una aplicación. Por ejemplo, en el entorno de desarrollo, es posible que desee utilizar una base de datos llamada `mydb_dev`, mientras que en servidor de producción es posible que desee utilizar la base de datos `mydb_prod`. Para facilitar la conmutación de entornos, Yii proporciona una constante llamado `YII_ENV`que se puede definir en el [entrada script](structure-entry-scripts.md) de su aplicación. Por ejemplo,
Las configuraciones a menudo varían de acuerdo al entorno en que se ejecuta una aplicación. Por ejemplo, en el entorno de desarrollo, es posible que desee utilizar una base de datos llamada `mydb_dev`, mientras que en servidor de producción es posible que desee utilizar la base de datos `mydb_prod`. Para facilitar la conmutación de entornos, Yii proporciona una constante llamado `YII_ENV` que se puede definir en el [script de entrada](structure-entry-scripts.md) de su aplicación. Por ejemplo,
```php
defined('YII_ENV') or define('YII_ENV', 'dev');
@ -216,9 +213,7 @@ Usted puede definir `YII_ENV` como uno de los valores siguientes:
- `dev`: entorno de desarrollo. La constante `YII_ENV_DEV` evaluará como verdadero.
- `test`: entorno de pruebas. La constante `YII_ENV_TEST` evaluará como verdadero.
Con estas constantes de entorno, puede especificar sus configuraciones condicional basado en
el entorno actual. Por ejemplo, la configuración de la aplicación puede contener el siguiente
código para permitir que el [depurador y barra de herramientas de depuración](tool-debugger.md) en el entorno de desarrollo.
Con estas constantes de entorno, puede especificar sus configuraciones condicionales basado en el entorno actual. Por ejemplo, la configuración de la aplicación puede contener el siguiente código para permitir que el [depurador y barra de herramientas de depuración](tool-debugger.md) en el entorno de desarrollo.
```php
$config = [...];

71
docs/guide-es/concept-service-locator.md

@ -0,0 +1,71 @@
Localizador de Servicios
========================
Un localizador de servicios es un objeto que sabe cómo proporcionar todo tipo de servicios (o componentes) que puede necesitar una aplicación. Dentro de un localizador de servicios, existe en cada componente como una única instancia, únicamente identificado por un ID. Se utiliza el ID para recuperar un componente desde el localizador de servicios.
En Yii, un localizador de servicio es simplemente una instancia de [[yii\di\ServiceLocator]], o de una clase hija.
El localizador de servicio más utilizado en Yii es el objeto *aplicación*, que se puede acceder a través de `\Yii::$app`. Los servicios que prestá son llamadas *componentes de la aplicación*, como los componentes `request`, `response`, and `urlManager`. Usted puede configurar estos componentes, o incluso cambiarlos por sus propias implementaciones fácilmente a través de la funcionalidad proporcionada por el localizador de servicios.
Además del objeto de aplicación, cada objeto módulo es también un localizador de servicios.
Para utilizar un localizador de servicios, el primer paso es registrar los componentes de la misma. Un componente se puede registrar a través de [[yii\di\ServiceLocator::set()]]. El código siguiente muestra diferentes maneras de registrarse componentes:
```php
use yii\di\ServiceLocator;
use yii\caching\FileCache;
$locator = new ServiceLocator;
// register "cache" using a class name that can be used to create a component
$locator->set('cache', 'yii\caching\ApcCache');
// register "db" using a configuration array that can be used to create a component
$locator->set('db', [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=demo',
'username' => 'root',
'password' => '',
]);
// register "search" using an anonymous function that builds a component
$locator->set('search', function () {
return new app\components\SolrService;
});
// register "pageCache" using a component
$locator->set('pageCache', new FileCache);
```
Una vez que el componente se ha registrado, usted puede acceder a él utilizando su ID, en una de las dos formas siguientes:
```php
$cache = $locator->get('cache');
// or alternatively
$cache = $locator->cache;
```
Como puede observarse, [[yii\di\ServiceLocator]] le permite acceder a un componente como una propiedad utilizando el ID de componente. Cuando acceda a un componente, por primera vez, [[yii\di\ServiceLocator]] utilizará la información de registro de componente para crear una nueva instancia del componente y devolverlo. Más tarde, si se accede de nuevo al componente, el localizador de servicio devolverá la misma instancia.
Usted puede utilizar [[yii\di\ServiceLocator::has()]] para comprobar si un ID de componente ya ha sido registrada.
Si llama [[yii\di\ServiceLocator::get()]] con una identificación válida, se produce una excepción.
Debido a que los localizadores de servicios a menudo se crean con [configuraciones](concept-configurations.md), se proporciona una propiedad que puede escribir el nombre [[yii\di\ServiceLocator::setComponents()|components]]. Esto le permite configurar y registrar varios componentes a la vez. El siguiente código muestra un arreglo de configuración que se puede utilizar para configurar una aplicación, al mismo tiempo que el registro de la "db", "cache" y "buscar" componentes:
```php
return [
// ...
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=demo',
'username' => 'root',
'password' => '',
],
'cache' => 'yii\caching\ApcCache',
'search' => function () {
return new app\components\SolrService;
},
],
];
```

2
docs/guide-es/images/application-lifecycle.graphml

@ -219,7 +219,7 @@
<y:Geometry height="30.0" width="150.55899810791016" x="637.2124862670898" y="721.1271178722382"/>
<y:Fill color="#FFFFFF" 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="17.96875" modelName="custom" textColor="#000000" visible="true" width="101.447265625" x="24.555866241455078" y="6.015625">interpretar vista<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="98.3359375" x="26.111530303955078" y="6.015625">renderizar vista<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>

BIN
docs/guide-es/images/application-lifecycle.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 39 KiB

BIN
docs/guide-es/images/application-structure.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 15 KiB

24
docs/guide-es/runtime-bootstrapping.md

@ -0,0 +1,24 @@
Bootstrapping
=============
El Bootstrapping hace referencia al proceso de preparar el entorno antes de que una aplicación se inicie para resolver y procesar una petición entrante. El se ejecuta en dos lugares: el [script de entrada](structure-entry-scripts.md) y la [aplicación](structure-applications.md).
En el [script de entrada](structure-entry-scripts.md), se registran los cargadores automáticos de clase para diferentes librerías. Esto incluye el cargador automático de Composer a través de su fichero ‘autoload.php’ y del cargador automático de Yii a través del fichero de clase ‘Yii’. El script de entrada después carga la [configuración](concept-configurations.md) de la aplicación y crea una instancia de la [aplicación](structure-applications.md).
El constructor de la aplicación, ejecuta el siguiente trabajo de bootstrapping:
Llama a [[yii\base\Application::preInit()|preInit()]], que configura algunas propiedades de alta prioridad de la aplicación, como [[yii\base\Application::basePath|basePath]].
Registra el [[yii\base\Application::errorHandler|error handler]].
Inicializa las propiedades de aplicación usando la configuración de la aplicación dada.
Llama a [[yii\base\Application::init()|init()]] que a su vez llama a [[yii\base\Application::bootstrap()|bootstrap()]] para ejecutar componentes de bootstrapping.
Incluye el archivo de manifiesto de extensiones ‘vendor/yiisoft/extensions.php’
Crea y ejecuta [compoentenes de bootstrap](structure-extensions.md#bootstrapping-classes) declarados por las extensiones.
Crea y ejecuta [componentes de aplicación](structure-application-components.md) y/o [módulos](structure-modules.md) que se declaran en la [propiedad bootstrap](structure-applications.md#bootstrap) de la aplicación.
Debido a que el trabajo de bootstrapping se tiene que ejecutar antes de gestionar *todas* las peticiones, es muy importante mantener este proceso ligero y optimizado lo máximo que sea posible.
Intenta no registrar demasiados componentes de bootstrapping. Un componente de bootstrapping sólo es necesario si tiene que interaccionar en todo el ciclo de vida de la gestión de la petición. Por ejemplo, si un modulo necesita registrar reglas de análisis de URL adicionales, se debe incluirse en la [propiedad bootstrap](structure-applications.md#bootstrap) para que la nueva regla de URL tenga efecto antes de que sea utilizada para resolver peticiones.
En modo de producción, hay que habilitar la cache bytecode, así como [APC](http://php.net/manual/es/book.apc.php), para minimizar el tiempo necesario para incluir y analizar archivos PHP.
Algunas grandes aplicaciones tienen [configuraciones](concept-configurations.md) de aplicación muy complejas que están dividida en muchos archivos de configuración más pequeños.

14
docs/guide-es/runtime-overview.md

@ -1,22 +1,22 @@
Información General
Información General
===============
Cada vez que una aplicación Yii gestiona una petición, se somete a una flujo de trabajo similar.
Cada vez que una aplicación Yii gestiona una petición, se somete a un flujo de trabajo similar.
1. Un usuario hace una petición al [script de entrada](structure-entry-scripts.md) ‘web/index.php’.
2. El script de entrada carga la [configuración](concept-configurations.md) y crea una instancia de la [aplicación](structure-applications.md) para gestionar la petición.
3. La aplicación resuelve la [ruta](runtime-routing.md) solicitada con la ayuda del componente [petición](runtime-requests.md) de la aplicación.
4. La aplicación crea una instancia del [controlador](structure-controllers.md) para gestionar la petición.
5. El controlador crea una instancia de la [acción](structure-controllers.md) y ejecuta los filtros para la acción.
6. Si algun filtro falla, se cancela la acción.
6. Si algún filtro falla, se cancela la acción.
7. Si pasa todos los filtros, se ejecuta la acción.
8. La acción carga un modelo de datos, posiblemente de la base de datos.
9. La acción interpreta una vista, proporcionandole el modelo de datos.
10. El resultado interpretado se devuelve al componente [respuesta](runtime-responses.md) de la aplicación.
11. El componente respuesta envía el resultado interpretado al navegador del usuario.
9. La acción renderiza una vista, proporcionándole el modelo de datos.
10. El resultado renderizado se devuelve al componente [respuesta](runtime-responses.md) de la aplicación.
11. El componente respuesta envía el resultado renderizado al navegador del usuario.
El siguiente diagrama muestra como una aplicación gestiona una petición.
![Request Lifecycle](images/application-lifecycle.png)
En esta sección, se describirá en detalle cómo funcionan algunos de estos pasos.
En esta sección, se describirá en detalle cómo funcionan algunos de estos pasos.

108
docs/guide-es/runtime-requests.md

@ -0,0 +1,108 @@
Peticiones
========
Las peticiones(requests) hechas a una aplicación son representadas como objetos [[yii\web\Request]] que proporcionan información como parámetros de la petición, cabeceras HTTP, cookies, etc. Dada una petición, se puede acceder al objeto request correspondiente a través del [componente de aplicación](structure-application-components.md) 'request' que, por defecto, es una instancia de [[yii\web\Request]]. En esta sección se describirá como hacer uso de este componente en las aplicaciones.
## Parámetros de Request <a name="request-parameters"></a>
Para obtener los parámetros de la petición, se puede llamar a los métodos [[yii\web\Request::get()|get()]] y [[yii\web\Request::post()|post()]] del componente 'request'. Estos devuelven los valores de '$_GET' y '$_POST', respectivamente. Por ejemplo:
```php
$request = Yii::$app->request;
$get = $request->get();
// equivalente a: $get = $_GET;
$id = $request->get('id');
// equivalente a: $id = isset($_GET['id']) ? $_GET['id'] : null;
$id = $request->get('id', 1);
// equivalente a: $id = isset($_GET['id']) ? $_GET['id'] : 1;
$post = $request->post();
// equivalente a: $post = $_POST;
$name = $request->post('name');
// equivalente a: $name = isset($_POST['name']) ? $_POST['name'] : null;
$name = $request->post('name', '');
// equivalente a: $name = isset($_POST['name']) ? $_POST['name'] : '';
```
>Info: En lugar de acceder directamente a '$_GET' y '$_POST' para obtener los parámetros de la petición, es recomendable que se obtengan mediante el componente 'request' como en el ejemplo anterior. Esto facilitará la creación de tests ya que se puede simular una componente de request con datos de peticiones personalizados.
Cuando se implementan [APIs RESTful](rest-quick-start.md), a menudo se necesita obtener parámetros enviados desde el formulario a través de PUT, PATCH u otros [métodos de request](runtime-requests.md#request-methods). Se pueden obtener estos parámetros llamando a los métodos [[yii\web\Request::getBodyParam()]]. Por ejemplo:
```php
$request = Yii::$app->request;
// devuelve todos los parámetros
$params = $request->bodyParams;
// devuelve el parámetro "id"
$param = $request->getBodyParam('id');
```
>Info: A diferencia de los parámetros 'GET', los parámetros enviados desde el formulario a través de 'POST', 'PUT', 'PATCH', etc. se envían en el cuerpo de la petición. El componente 'request' convierte los parámetros cuando se acceda a él a través de los métodos descritos anteriormente. Se puede personalizar la manera en como los parámetros se convierten configurando la propiedad [[yii\web\Request::parsers]].
## Métodos de Request <a name="request-methods"></a>
Se puede obtener el método HTTP usado por la petición actual a través de la expresión 'Yii::$app->request->method'. Se proporcionan un conjunto de propiedades booleanas para comprobar si el método actual es de un cierto tipo. Por ejemplo:
```php
$request = Yii::$app->request;
if ($request->isAjax) { // la request una request AJAX }
if ($request->isGet) { // el método de la request es GET }
if ($request->isPost) { // el método de la request es POST }
if ($request->isPut) { // el método de la request es PUT }
```
## URLs de Request <a name="request-urls"></a>
El componente 'request' proporciona muchas maneras de inspeccionar la URL solicitada actualmente.
Asumiendo que la URL que se está solicitando es 'http://example.com/admin/index.php/product?id=100', se pueden obtener varias partes de la URL explicadas en los siguientes puntos:
* [[yii\web\Request::url|url]]: devuelve `/admin/index.php/product?id=100`, que es la URL sin la parte de información del host.
* [[yii\web\Request::absoluteUrl|absoluteUrl]]: devuelve `http://example.com/admin/index.php/product?id=100`, que es la URL entera, incluyendo la parte de información del host.
* [[yii\web\Request::hostInfo|hostInfo]]: devuelve `http://example.com`, que es la parte de información del host dentro de la URL.
* [[yii\web\Request::pathInfo|pathInfo]]: devuelve `/product`, que es la parte posterior al script de entrada y anterior al interrogante (query string)
* [[yii\web\Request::queryString|queryString]]: devuelve `id=100`, que es la parte posterior al interrogante.
* [[yii\web\Request::baseUrl|baseUrl]]: devuelve `/admin`, que es la parte posterior a la información del host y anterior al nombre de script de entrada.
* [[yii\web\Request::scriptUrl|scriptUrl]]: devuelve `/admin/index.php`, que es la URL sin la información del la ruta ni la query string.
* [[yii\web\Request::serverName|serverName]]: devuelve `example.com`, que es el nombre del host dentro de la URL.
* [[yii\web\Request::serverPort|serverPort]]: devuelve 80, que es el puerto que usa el servidor web.
## Cabeceras HTTP <a name="http-headers"></a>
Se pueden obtener la información de las cabeceras HTTP a través de [[yii\web\HeaderCollection|header collection]] devueltas por la propiedad [[yii\web\Request::headers]]. Por ejemplo:
```php
// $headers es un objeto de yii\web\HeaderCollection
$headers = Yii::$app->request->headers;
// devuelve el valor Accept de la cabecera
$accept = $headers->get('Accept');
if ($headers->has('User-Agent')) { // la cabecera contiene un User-Agent }
```
El componente 'request' también proporciona soporte para acceder rápidamente a las cabeceras usadas más comúnmente, incluyendo:
* [[yii\web\Request::userAgent|userAgent]]: devuelve el valor de la cabecera 'User-Agen'.
* [[yii\web\Request::contentType|contentType]]: devuelve el valor de la cabecera `Content-Type` que indica el tipo MIME de los datos del cuerpo de la petición.
* [[yii\web\Request::acceptableContentTypes|acceptableContentTypes]]: devuelve los tipos de contenido MIME aceptado por los usuarios, ordenados por puntuación de calidad. Los que tienen mejor puntuación, se devolverán primero.
* [[yii\web\Request::acceptableLanguages|acceptableLanguages]]: devuelve los idiomas aceptados por el usuario. Los idiomas devueltos son ordenados según su orden de preferencia. El primer elemento representa el idioma preferido.
Si la aplicación soporta múltiples idiomas y se quiere mostrar las páginas en el idioma preferido por el usuario, se puede usar el método de negociación de idioma [[yii\web\Request::getPreferredLanguage()]]. Este método obtiene una lista de idiomas soportados por la aplicación, comparados con [[yii\web\Request::acceptableLanguages|acceptableLanguages]], y devuelve el idioma más apropiado.
>Consejo: También se puede usar el filtro [[yii\filters\ContentNegotiator|ContentNegotiator]] para determinar diatónicamente el content type y el idioma que debe usarse en la respuesta. El filtro implementa la negociación de contenido en la parte superior de las propiedades y métodos descritos anteriormente.
## Información del cliente <a name="client-information"></a>
Se puede obtener el nombre del host y la dirección IP de la máquina cliente a través de [[yii\web\Request::userHost|userHost]] y [[yii\web\Request::userIP|userIP]], respectivamente. Por ejemplo:
```php
$userHost = Yii::$app->request->userHost;
$userIP = Yii::$app->request->userIP;
```

51
docs/guide-es/runtime-routing.md

@ -0,0 +1,51 @@
Routing
=======
Cuando se llama al método [[yii\web\Application::run()|run()]] a través del [script de entrada](structure-entry-scripts.md), lo primero que hace es resolver la petición entrante e instanciar una [accion de controlador](structure-controllers.md) apropiada para gestionar la petición. A este proceso se le llama *routing*.
## Resolver una Ruta <a name="resolving-route"></a>
El primer paso el primer paso de routing es convertir la petición entrante una ruta que, tal y como se describe en la sección [Controladores](structure-controllers.md#routes), se usa para dirigirse a una acción de controlador. El método invoca al [gestor de URLs](runtime-url-handling.md) para hacer que la conversión de la petición actual funcione.
Por defecto, si la petición entrante contiene un parámetro 'GET' llamado 'r', su valor será considerado como la ruta. Sin embargo, si la [[yii\web\UrlManager::enablePrettyUrl|pretty URL feature]] esta habilitada, se tendrá que hacer más trabajo para determinar la ruta solicitada. Para conocer más detalles, por favor refiérase a la sección [generación y conversión de URLs](runtime-url-handling.md).
En el caso que una ruta no pueda ser determinada, el componente 'petición' lanzará una [[yii\web\NotFoundHttpException]].
### Ruta por defecto <a name="default-route"></a>
Si una petición entrante no especifica una ruta, cosa que sucede habitualmente en las paginas de inicio, se usará la ruta especificada por [[yii\web\Application::defaultRoute]]. El valor por defecto de esta propiedad es 'site/index', que hace referencia a la acción 'index' del controlador 'site'. Se puede personalizar esta propiedad en la configuración de aplicación como en el siguiente ejemplo:
```php
return [
// ...
'defaultRoute' => 'main/index',
];
```
### La ruta `catchAll` <a name="catchall-route"></a>
A veces, queremos poner una aplicación Web en modo de mantenimiento temporalmente y mostrar la misma pagina de información para todas las peticiones. Hay varias maneras de llevar esta operación a cabo. Pero una de las maneras más simples es configurando la propiedad [[yii\web\Application::catchAll]] como en la siguiente configuración de aplicación:
```php
return [
// ...
'catchAll' => ['site/offline'],
];
```
La propiedad 'catchAll' debe componerse de un array cuyo primer elemento especifique la ruta, y el resto de elementos(pares de nombre-valor) especifiquen los parámetros que van ligados a la acción.
Cuando se especifica la propiedad 'catchAll', esta reemplazará cualquier otra ruta resuelta a partir de la petición entrante. Con la anterior configuración, la misma acción 'site/offline' se usará para gestionar todas las peticiones entrantes.
## Crear una Acción <a name="creating-action"></a>
Una vez que se determina la ruta solicitada, el siguiente paso es crear el objecto de la acción correspondiente a la ruta.
La ruta se desglosa en múltiples partes mediante barras oblicuas '/'. Por ejemplo, 'site/index' será desglosado en 'site' y 'index'. Cada parte es un ID que puede hacer referencia a un modulo, un controlador o una acción.
Empezando por la primera parte de la ruta, la aplicación lleva a cabo los siguientes pasos para crear módulos(si los hay), el controlador y la acción.
1. Establece la aplicación como el modulo actual.
2. Comprueba si el [[yii\base\Module::controllerMap|controller map]] del modulo actual contiene un ID actual. Si lo tiene, se creará un objecto controlador de acuerdo con la configuración encontrada en el mapa, y ejecuta el Paso 5 con el resto de partes de la ruta.
3. Comprueba si el ID hace referencia a un modulo de la lista de la propiedad[[yii\base\Module::modules|modules]] del actual modulo. Si es así, se crea un modulo de acuerdo con la configuración encontrada en la lista del modulo, y se ejecuta el Paso 2 con la siguiente parte de la ruta dentro del contexto del modulo recién creado.
4. Trata el ID como un ID de controlador y crea un objeto controlador. Ejecuta el siguiente paso con el resto de la ruta.
5. El controlador busca el ID actual en su [[yii\base\Controller::actions()|action map]]. Si lo encuentra, crea una acción de acuerdo con la configuración encontrada en el mapa. De lo contrario, el controlador intentará crear una acción en linea que esta definida por el método de la acción correspondiente con el ID actual.

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

@ -31,8 +31,8 @@ Por defecto, los filtros declarados en una clase controlador, serán aplicados e
Además de en los controladores, se pueden declarar filtros en [modulos](structure-modules.md) o [aplicaciones](structure-applications.md).
Una vez hecho, los filtros serán aplicados a *todas* las acciones de controlador que pertenezcan a ese modulo o aplicación, a menos que las propiedades [[yii\base\ActionFilter::only|only]] y [[yii\base\ActionFilter::except|except]] sean configuradas como se ha descrito anteriormente.
>Nota: Cuando se declaran filtros en módulos o aplicaciones, deben usarse [rutas](structure-controllers.md#routes) en lugar de identificadores de acciones en las propiedades [[yii\base\ActionFilter::only|only]] y [[yii\base\ActionFilter::except|except]].
Esto es debido a que los identificadores de acciones no pueden especificar acciones dentro del ámbito de un modulo o una aplicación por si mismos.
>Nota: Cuando se declaran filtros en módulos o aplicaciones, deben usarse [rutas](structure-controllers.md#routes) en lugar de IDs de acciones en las propiedades [[yii\base\ActionFilter::only|only]] y [[yii\base\ActionFilter::except|except]].
Esto es debido a que los IDs de acciones no pueden especificar acciones dentro del ámbito de un modulo o una aplicación por si mismos.
Cuando se configuran múltiples filtros para una misma acción, se aplican de acuerdo a las siguientes reglas:

12
docs/guide-es/structure-models.md

@ -1,4 +1,4 @@
Modelos
Modelos
======
Los modelos forman parte de la arquitectura [MVC](http://es.wikipedia.org/wiki/Modelo%E2%80%93vista%E2%80%93controlador). Son objetos que representan datos de negocio, reglas y lógica.
@ -11,7 +11,7 @@ Se pueden crear clases modelo extendiendo a [[yii\base\Model]] o a sus clases hi
* [validación](#validation-rules): asegura la validez de los datos de entrada basándose en reglas declaradas;
* [Exportación de datos](#data-exporting): permite que los datos del modelo sean exportados en términos de arrays con formatos personalizables.
La clase 'modelo' también es una base base para modelos más avanzados, tales como [Registros Activos](db-active-record.md).
La clase 'modelo' también es una base para modelos más avanzados, tales como [Active Records](db-active-record.md).
>Info: No es obligatorio basar las clases modelo en [[yii\base\Model]]. Sin embargo, debido a que hay muchos componentes de Yii construidos para dar soporte a [[yii\base\Model]], por lo general es la clase base preferible para un modelo.
@ -156,7 +156,7 @@ class User extends ActiveRecord
}
```
> Info: En el anterior y en los siguientes ejemplos, las clases modelo extienden a [[yii\db\ActiveRecord]] porque el uso de múltiples escenarios normalmente sucede con clases de [Registros Activos](db-active-record.md).
> Info: En el anterior y en los siguientes ejemplos, las clases modelo extienden a [[yii\db\ActiveRecord]] porque el uso de múltiples escenarios normalmente sucede con clases de [Active Records](db-active-record.md).
El método 'scenarios()' devuelve un array cuyas claves son el nombre de escenario y los valores correspondientes a los *atributos activos*. Un atributo activo puede ser [asignado masivamente](#massive-assignment) y esta sujeto a [validación](#validation-rules). En el anterior ejemplo, los atributos 'username' y 'password' están activados en el escenario 'login'; mientras que en el escenario 'register', el atributo 'email' esta activado junto con 'username' y 'password'.
@ -370,13 +370,13 @@ En resumen, los modelos:
* pueden contener atributos para representar los datos de negocio;
* pueden contener reglas de validación para asegurar la validez e integridad de los datos;
* pueden contener métodos que para implementar la lógica de negocio;
* NO deben acceder directamente a peticiones, sesiones, o otro tipo de datos de entorno. Estos datos deben ser inyectados por los [controladores](structure-controllers.md) en los modelos.
* deben evitar embeber HTML o otro código de presentación – esto es mejor hacerlo en las [vistas](structure-views.md);
* NO deben acceder directamente a peticiones, sesiones, u otro tipo de datos de entorno. Estos datos deben ser inyectados por los [controladores](structure-controllers.md) en los modelos.
* deben evitar embeber HTML u otro código de presentación – esto es mejor hacerlo en las [vistas](structure-views.md);
* evitar tener demasiados [escenarios](#scenarios) en un mismo modelo.
Generalmente se puede considerar la última recomendación cuando se estén desarrollando grandes sistemas complejos. En estos sistemas, los modelos podrían ser muy grandes debido a que podrían ser usados en muchos lugares y por tanto contener muchos conjuntos de reglas y lógicas de negocio. A menudo esto desemboca en un código muy difícil de mantener ya que una simple modificación en el código puede afectar a muchos sitios diferentes. Para mantener el código más fácil de mantener, se puede seguir la siguiente estrategia:
* Definir un conjunto de clases modelo base que sean compartidas por diferentes [aplicaciones](structure-applications.md) o [módulos](structure-modules.md). Estas clases modelo deben contener el conjuntos mínimos de reglas y lógica que sean comunes para todos sus usos.
* Definir un conjunto de clases modelo base que sean compartidas por diferentes [aplicaciones](structure-applications.md) o [módulos](structure-modules.md). Estas clases modelo deben contener el conjunto mínimo de reglas y lógica que sean comunes para todos sus usos.
* En cada [aplicación](structure-applications.md) o [módulo](structure-modules.md) que use un modelo, definir una clase modelo concreta que extienda a la correspondiente clase modelo base. La clase modelo concreta debe contener reglas y lógica que sean específicas para esa aplicación o módulo.
Por ejemplo, en la [Plantilla de Aplicación Avanzada](tutorial-advanced-app.md), definiendo una clase modelo base 'common\models\Post'. Después en la aplicación front end, definiendo y usando una clase modelo concreta 'frontend\models\Post' que extienda a 'common\models\Post'. Y de forma similar en la aplicación back end, definiendo 'backend\models\Post'. Con esta estrategia, nos aseguramos que el código de 'frontend\models\Post' es específico para la aplicación front end, y si se efectúa algún cambio en el, no nos tenemos que preocupar de si el cambio afectará a la aplicación back end.

31
docs/guide-es/structure-modules.md

@ -1,4 +1,4 @@
Módulos
Módulos
=======
Los módulos son unidades de software independientes que consisten en [modelos](structure-models.md), [vistas](structure-views.md), [controladores](structure-controllers.md), y otros componentes de apoyo. Los usuarios finales pueden acceder a los controladores de un módulo cuando éste está instalado en la [aplicación](structure-applications.md). Por éstas razones, los módulos a menudo se considerados como mini-aplicaciones. Los módulos difieren de las [aplicaciones](structure-applications.md) en que los módulos no pueden ser desplegados solos y tienen que residir dentro de aplicaciones.
@ -50,7 +50,7 @@ public function init()
}
```
donde el archivo de configuracion ‘config.php’ puede contaner el siguiente contenido, similar al de [configuraciones de aplicacion](structure-applications.md#application-configurations).
donde el archivo de configuración ‘config.php’ puede contener el siguiente contenido, similar al de [configuraciones de aplicación](structure-applications.md#application-configurations).
```php
<?php
@ -66,7 +66,7 @@ return [
### Controladores en Módulos <a name="controllers-in-modules"></a>
Cuando se crean controladores en un modelo, una convención es poner las clases controlador debajo del sub espacio de nombres de ‘controllers’ del espacio de nombres de la clase módulo. Esto también significa que los archivos de la clase controlador deben ponerse en el directorio ‘controllers’ dentro del [[yii\base\Module::basePath|base path]] del módulo. Por ejemplo, para crear un controlador ‘post’ en el módulo ‘forum’ mostrado en la última subdivisión, se debe declarar la clase controlador de la siguiente manera:
Cuando se crean controladores en un modelo, una convención es poner las clases controlador debajo del sub-espacio de nombres de ‘controllers’ del espacio de nombres de la clase módulo. Esto también significa que los archivos de la clase controlador deben ponerse en el directorio ‘controllers’ dentro del [[yii\base\Module::basePath|base path]] del módulo. Por ejemplo, para crear un controlador ‘post’ en el módulo ‘forum’ mostrado en la última subdivisión, se debe declarar la clase controlador de la siguiente manera:
```php
namespace app\modules\forum\controllers;
@ -79,13 +79,13 @@ class PostController extends Controller
}
```
Se puede personalizar el espacio de nombres de las clases controlador configurando la propiedad [[yii\base\Module::controllerNamespace]]. En el caso que alguno de los controladores esté fuera del espacio de nombres, se puede hacer acesible configurando la propiedad [[yii\base\Module::controllerMap]], similar a [como se hace en una aplicación](structure-applications.md#controller-map).
Se puede personalizar el espacio de nombres de las clases controlador configurando la propiedad [[yii\base\Module::controllerNamespace]]. En el caso que alguno de los controladores esté fuera del espacio de nombres, se puede hacer accesible configurando la propiedad [[yii\base\Module::controllerMap]], similar a [como se hace en una aplicación](structure-applications.md#controller-map).
### Vistas en Módulos <a name="views-in-modules"></a>
Las vistas en un módulo deben deben alojarse en el directorio ‘views’ dentro del módulo del [[yii\base\Module::basePath|base path]]. Las vistas interpretadas por un controlador en el módulo, deben alojarse en el directorio ‘views/ControllerID’, donde el ‘ControllerID’ hace referencia al [identificador del controlador](structure-controllers.md#routes). Por ejemplo, si la clase controlador es ‘PostController’, el directorio sería ‘views/post’ dentro del [[yii\base\Module::basePath|base path]] del módulo.
Las vistas en un módulo deben alojarse en el directorio ‘views’ dentro del módulo del [[yii\base\Module::basePath|base path]]. Las vistas renderizadas por un controlador en el módulo, deben alojarse en el directorio ‘views/ControllerID’, donde el ‘ControllerID’ hace referencia al [ID del controlador](structure-controllers.md#routes). Por ejemplo, si la clase controlador es ‘PostController’, el directorio sería ‘views/post’ dentro del [[yii\base\Module::basePath|base path]] del módulo.
Un modulo puede especificar un [layout](structure-views.md#layouts) que se aplica a las vistas interpretadas por los controladores del módulo. El layout debe alojarse en el directorio ‘views/layouts’ por defecto, y se puede configurar la propiedad [[yii\base\Module::layout]] para apuntar al nombre del layout. Si no se configura la propiedad ‘layout’, se usar el layout de la aplicación.
Un modulo puede especificar un [layout](structure-views.md#layouts) que se aplica a las vistas renderizadas por los controladores del módulo. El layout debe alojarse en el directorio ‘views/layouts’ por defecto, y se puede configurar la propiedad [[yii\base\Module::layout]] para apuntar al nombre del layout. Si no se configura la propiedad ‘layout’, se usar el layout de la aplicación.
## Uso de los Módulos <a name="using-modules"></a>
@ -102,35 +102,35 @@ Para usar un módulo en una aplicación, simplemente se tiene que configurar la
]
```
La propiedad [[yii\base\Application::modules|modules]] contiene un array de configuraciones de módulo. Cada clave del array representa un *identificador de módulo* que identifica de forma única el módulo de entre todos los módulos de la aplicación, y el correspondiente valor del array es la [configuración](concept-configurations.md) para crear el módulo.
La propiedad [[yii\base\Application::modules|modules]] contiene un array de configuraciones de módulo. Cada clave del array representa un *ID de módulo* que identifica de forma única el módulo de entre todos los módulos de la aplicación, y el correspondiente valor del array es la [configuración](concept-configurations.md) para crear el módulo.
### Rutas <a name="routes"></a>
De Igual manera que el acceso a los controladores en una aplicacion, las [rutas](structure-controllers.md#routes) se utiliza para dirigirse a los controladores en un módulo. Una ruta para un controlador dentro de un módulo debe empezar con el identificador del módulo seguido por el identificador del controlador y el identificador de la acción. Por ejemplo, si una aplicación usa un módulo llamado ‘forum’, la ruta ‘forum/post/index’ representaría la acción ‘index’ del controlador ‘post’ en el módulo. Si la ruta sólo contiene el identificador del módulo, entonces la propiedad [[yii\base\Module::defaultRoute]] que por defecto es ‘default’, determinara que controlador/acción debe usarse. Esto significa que la ruta ‘forum’ representaría el controlador ‘default’ en el módulo ‘forum’.
De Igual manera que el acceso a los controladores en una aplicación, las [rutas](structure-controllers.md#routes) se utiliza para dirigirse a los controladores en un módulo. Una ruta para un controlador dentro de un módulo debe empezar con el ID del módulo seguido por el ID del controlador y el ID de la acción. Por ejemplo, si una aplicación usa un módulo llamado ‘forum’, la ruta ‘forum/post/index’ representaría la acción ‘index’ del controlador ‘post’ en el módulo. Si la ruta sólo contiene el ID del módulo, entonces la propiedad [[yii\base\Module::defaultRoute]] que por defecto es ‘default’, determinara que controlador/acción debe usarse. Esto significa que la ruta ‘forum’ representaría el controlador ‘default’ en el módulo ‘forum’.
### Acceder a los Módulos <a name="accessing-modules"></a>
Dentro de un módulo, se puede necesitar obtener la instancia de la [clase módulo](#module-classes) para poder acceder al identificador del módulo, componentes del módulo, etc. Se puede hacer usando la siguiente declaración:
Dentro de un módulo, se puede necesitar obtener la instancia de la [clase módulo](#module-classes) para poder acceder al ID del módulo, componentes del módulo, etc. Se puede hacer usando la siguiente declaración:
```php
$module = MyModuleClass::getInstance();
```
donde ‘MyModuleClass’ hace referencia al nombre de la clase módulo en la que estemos interesados. El método ‘getInstance()’ devolverá la instancia actualmente solicitada de la clase módulo. Si no se solicita el módulo, el método devolverá nulo. Hay que tener en cuenta que si se crea una nueva instancia del módulo, esta será diferente a la creada por Yii en respuesta a la solicitud.
nde ‘MyModuleClass’ hace referencia al nombre de la clase módulo en la que estemos interesados. El método ‘getInstance()’ devolverá la instancia actualmente solicitada de la clase módulo. Si no se solicita el módulo, el método devolverá nulo. Hay que tener en cuenta que si se crea una nueva instancia del módulo, esta será diferente a la creada por Yii en respuesta a la solicitud.
>Info: Cuando se desarrolla un módulo, no se debe dar por sentado que el módulo usará un identificador fijo. Esto se debe a que un módulo puede asociarse a un identificador arbitrario cuando se usa en una aplicación o dentro de otro módulo. Para obtener el identificador del módulo, primero se debe usar el código del anterior ejemplo para obtener la instancia y luego el identificador mediante ‘$modeule->id’.
>Info: Cuando se desarrolla un módulo, no se debe dar por sentado que el módulo usará un ID fijo. Esto se debe a que un módulo puede asociarse a un ID arbitrario cuando se usa en una aplicación o dentro de otro módulo. Para obtener el ID del módulo, primero se debe usar el código del anterior ejemplo para obtener la instancia y luego el ID mediante ‘$modeule->id’.
También se puede acceder a la instancia de un módulo usando las siguientes declaraciones:
```php
// obtiene el modulo hijo cuyo identificador es “forum”
// obtiene el modulo hijo cuyo ID es “forum”
$module = \Yii::$app->getModule('forum');
// obtiene el módulo al que pertenece la petición actual
$module = \Yii::$app->controller->module;
```
El primer ejemplo sólo es útil cuando conocemos el identificador del módulo, mientras que el segundo es mejor usarlo cuando conocemos los controladores que se están solicitando.
El primer ejemplo sólo es útil cuando conocemos el ID del módulo, mientras que el segundo es mejor usarlo cuando conocemos los controladores que se están solicitando.
Una vez obtenida la instancia del módulo, se puede acceder a parámetros o componentes registrados con el módulo. Por ejemplo:
@ -140,7 +140,7 @@ $maxPostCount = $module->params['maxPostCount'];
### Bootstrapping Módulos <a name="bootstrapping-modules"></a>
Puede darse el caso en que necesitemos que un módulo se ejecute en cada petición. El módulo [[yii\debug\Module|debug]] es un ejemplo. Para hacerlo, tenemos que listar los identificadores de los módulos en la propiedad [[yii\base\Application::bootstrap|bootstrap]] de la aplicación.
Puede darse el caso en que necesitemos que un módulo se ejecute en cada petición. El módulo [[yii\debug\Module|debug]] es un ejemplo. Para hacerlo, tenemos que listar los IDs de los módulos en la propiedad [[yii\base\Application::bootstrap|bootstrap]] de la aplicación.
Por ejemplo, la siguiente configuración de aplicación se asegura de que el módulo ‘debug’ siempre se cargue:
@ -179,7 +179,7 @@ class Module extends \yii\base\Module
}
```
En un controlador dentro de un módulo anidado, la ruta debe incluir el identificador de todos los módulos antecesores. Por ejemplo, la ruta ‘forum/admin/dashboard/index’ representa la acción ‘index’ del controlador ‘dashboard’ en el módulo ‘admin’ que es el módulo hijo del módulo ‘forum’.
En un controlador dentro de un módulo anidado, la ruta debe incluir el ID de todos los módulos antecesores. Por ejemplo, la ruta ‘forum/admin/dashboard/index’ representa la acción ‘index’ del controlador ‘dashboard’ en el módulo ‘admin’ que es el módulo hijo del módulo ‘forum’.
>Info: El método [[yii\base\Module::getModule()|getModule()]] sólo devuelve el módulo hijo que pertenece directamente a su padre. La propiedad [[yii\base\Application::loadedModules]] contiene una lista de los módulos cargados, incluyendo los hijos directos y los anidados, indexados por sus nombres de clase.
@ -188,4 +188,3 @@ En un controlador dentro de un módulo anidado, la ruta debe incluir el identifi
Es mejor usar los módulos en grandes aplicaciones en las que sus funcionalidades puedan ser divididas en diferentes grupos, cada uno compuesto por funcionalidades directamente relacionadas. Cada grupo de funcionalidades se puede desarrollar como un módulo que puede ser desarrollado y mantenido por un programador o equipo específico.
Los módulos también son una buena manera de reutilizar código a nivel de grupo de funcionalidades. Algunas funcionalidades de uso común, tales como la gestión de usuarios o la gestión de comentarios, pueden ser desarrollados como módulos para que puedan ser fácilmente reutilizados en futuros proyectos.

288
docs/guide-es/structure-views.md

@ -1,18 +1,14 @@
Vistas
Vistas
======
Las Vistas (views) son una parte de la arquitectura [MVC](http://es.wikipedia.org/wiki/Modelo%E2%80%93vista%E2%80%93controlador).
Estas son el código responsable de presentar los datos al usuario final. En una aplicación Web, las vistas son usualmente creadas
en términos de *templates* que son archivos PHP que contienen principalmente HTML y PHP.
Son manejadas por el componente de la aplicación [[yii\web\View|view]], el cual provee métodos comúnmente utilizados
para facilitar la composición y el renderizado de las mismas. Por simplicidad, a menudo las llamamos *templates* o *archivos de templates*.
Estas son el código responsable de presentar los datos al usuario final. En una aplicación Web, las vistas son usualmente creadas en términos de *templates* que son archivos PHP que contienen principalmente HTML y PHP.
Son manejadas por el componente de la aplicación [[yii\web\View|view]], el cual provee métodos comúnmente utilizados para facilitar la composición y el renderizado de las mismas. Por simplicidad, a menudo las llamamos *templates* o *archivos de templates*.
## Creando Vistas <a name="creating-views"></a>
Como fue mencionado, una vista es simplemente un archivo PHP que mezcla código PHP y HTML. La siguiente es una vista
que muestra un formulario de login. Como puedes ver, el código PHP utilizado es para generar contenido dinámico, como el
título de la página y el formulario mismo, mientras que el código HTML organiza estos elementos en una página HTML mostrable.
Como fue mencionado, una vista es simplemente un archivo PHP que mezcla código PHP y HTML. La siguiente es una vista que muestra un formulario de login. Como puedes ver, el código PHP utilizado es para generar contenido dinámico, como el título de la página y el formulario mismo, mientras que el código HTML organiza estos elementos en una página HTML mostrable.
```php
<?php
@ -36,25 +32,18 @@ $this->title = 'Login';
<?php ActiveForm::end(); ?>
```
Dentro de una vista, puedes acceder a la variable `$this` referida al [[yii\web\View|componente view]] que maneja
y renderiza la vista actual.
Dentro de una vista, puedes acceder a la variable `$this` referida al [[yii\web\View|componente view]] que maneja y renderiza la vista actual.
Además de `$this`, puede haber otras variables predefinidas en una vista, como `$form` y `$model` en el ejemplo
anterior. Estas variables representan los datos que son *inyectados* a la vista desde el [controlador](structure-controllers.md)
o algún otro objeto que dispara la [renderización de la vista](#rendering-views).
Además de `$this`, puede haber otras variables predefinidas en una vista, como `$form` y `$model` en el ejemplo anterior. Estas variables representan los datos que son *inyectados* a la vista desde el [controlador](structure-controllers.md) o algún otro objeto que dispara la [renderización de la vista](#rendering-views).
> Tip: La lista de variables predefinidas están listadas en un bloque de comentario al principio de la vista así pueden ser
reconocidas por las IDEs. Esto es también una buena manera de documentar tus propias vistas.
> Tip: La lista de variables predefinidas están listadas en un bloque de comentario al principio de la vista así pueden ser reconocidas por las IDEs. Esto es también una buena manera de documentar tus propias vistas.
### Seguridad <a name="security"></a>
Al crear vistas que generan páginas HTML, es importante que codifiques (encode) y/o filtres los datos provenientes
de los usuarios antes de mostrarlos. De otro modo, tu aplicación puede estar expuesta a
ataques tipo [cross-site scripting](http://es.wikipedia.org/wiki/Cross-site_scripting).
Al crear vistas que generan páginas HTML, es importante que codifiques (encode) y/o filtres los datos provenientes de los usuarios antes de mostrarlos. De otro modo, tu aplicación puede estar expuesta a ataques tipo [cross-site scripting](http://es.wikipedia.org/wiki/Cross-site_scripting).
Para mostrar un texto plano, codifícalos previamente utilizando [[yii\helpers\Html::encode()]]. Por ejemplo, el siguiente código
aplica una codificación del nombre de usuario antes de mostrarlo:
Para mostrar un texto plano, codifícalos previamente utilizando [[yii\helpers\Html::encode()]]. Por ejemplo, el siguiente código aplica una codificación del nombre de usuario antes de mostrarlo:
```php
<?php
@ -66,8 +55,7 @@ use yii\helpers\Html;
</div>
```
Para mostrar contenido HTML, utiliza [[yii\helpers\HtmlPurifier]] para filtrarlo antes. Por ejemplo, el siguiente
código filtra el contenido del post antes de mostrarlo en pantalla:
Para mostrar contenido HTML, utiliza [[yii\helpers\HtmlPurifier]] para filtrarlo antes. Por ejemplo, el siguiente código filtra el contenido del post antes de mostrarlo en pantalla:
```php
<?php
@ -79,31 +67,23 @@ use yii\helpers\HtmlPurifier;
</div>
```
> Tip: Aunque HTMLPurifier hace un excelente trabajo al hacer la salida más segura, no es rápido. Deberías considerar
utilizar [caching](caching-overview.md) al resultado de aplicar el filtro si tu aplicación requiere un gran desempeño (performance).
> Tip: Aunque HTMLPurifier hace un excelente trabajo al hacer la salida más segura, no es rápido. Deberías considerar utilizar [caching](caching-overview.md) al resultado de aplicar el filtro si tu aplicación requiere un gran desempeño (performance).
### Organizando Vistas <a name="organizing-views"></a>
Así como en [controladores](structure-controllers.md) y [modelos](structure-models.md), existen convenciones para organizar las vistas.
* Para vistas renderizadas por controladores, deberían colocarse en un directorio tipo `@app/views/ControllerID` por defecto,
donde `ControllerID` se refiere al [ID del controlador](structure-controllers.md#routes). Por ejemplo, si
la clase del controlador es `PostController`, el directorio sería `@app/views/post`; Si fuera `PostCommentController`,
el directorio sería `@app/views/post-comment`. En caso de que el controlador pertenezca a un módulo, el directorio
sería `views/ControllerID` bajo el [[yii\base\Module::basePath|directorio del módulo]].
* Para vistas renderizadas por un [widget](structure-widgets.md), deberían ser puestas en un directorio tipo `WidgetPath/views` por defecto,
donde `WidgetPath` se refiere al directorio que contiene a la clase del widget.
* Para vistas renderizadas por controladores, deberían colocarse en un directorio tipo `@app/views/ControllerID` por defecto, donde `ControllerID` se refiere al [ID del controlador](structure-controllers.md#routes). Por ejemplo, si la clase del controlador es `PostController`, el directorio sería `@app/views/post`; Si fuera `PostCommentController`, el directorio sería `@app/views/post-comment`. En caso de que el controlador pertenezca a un módulo, el directorio sería `views/ControllerID` bajo el [[yii\base\Module::basePath|directorio del módulo]].
* Para vistas renderizadas por un [widget](structure-widgets.md), deberían ser puestas en un directorio tipo `WidgetPath/views` por defecto, donde `WidgetPath` se refiere al directorio que contiene a la clase del widget.
* Para vistas renderizadas por otros objetos, se recomienda seguir una convención similar a la utilizada con los widgets.
Puedes personalizar estos directorios por defecto sobrescribiendo el método [[yii\base\ViewContextInterface::getViewPath()]]
en el controlador o widget necesario.
Puedes personalizar estos directorios por defecto sobrescribiendo el método [[yii\base\ViewContextInterface::getViewPath()]] en el controlador o widget necesario.
## Renderizando Vistas <a name="rendering-views"></a>
Puedes renderizar vistas desde [controllers](structure-controllers.md), [widgets](structure-widgets.md), o cualquier
otro lugar llamando a los métodos de renderización de vistas. Estos métodos comparten una firma similar, como se muestra a continuación:
Puedes renderizar vistas desde [controllers](structure-controllers.md), [widgets](structure-widgets.md), o cualquier otro lugar llamando a los métodos de renderización de vistas. Estos métodos comparten una firma similar, como se muestra a continuación:
```
/**
@ -119,13 +99,10 @@ methodName($view, $params = [])
Dentro de los [controladores](structure-controllers.md), puedes llamar al siguiente método del controlador para renderizar una vista:
* [[yii\base\Controller::render()|render()]]: renderiza la [vista nombrada](#named-views) y aplica un [layout](#layouts)
al resultado de la renderización.
* [[yii\base\Controller::render()|render()]]: renderiza la [vista nombrada](#named-views) y aplica un [layout](#layouts) al resultado de la renderización.
* [[yii\base\Controller::renderPartial()|renderPartial()]]: renderiza la [vista nombrada](#named-views) sin ningún layout aplicado.
* [[yii\web\Controller::renderAjax()|renderAjax()]]: renderiza la [vista nombrada](#named-views) sin layout,
e inyecta todos los scripts y archivos JS/CSS registrados. Esto sucede usualmente en respuestas a llamadas a AJAX `requests`.
* [[yii\base\Controller::renderFile()|renderFile()]]: renderiza la vista especificada en términos de la ruta al archivo o
[alias](concept-aliases.md).
* [[yii\web\Controller::renderAjax()|renderAjax()]]: renderiza la [vista nombrada](#named-views) sin layout, e inyecta todos los scripts y archivos JS/CSS registrados. Esto sucede usualmente en respuestas a llamadas a AJAX `requests`.
* [[yii\base\Controller::renderFile()|renderFile()]]: renderiza la vista especificada en términos de la ruta al archivo o [alias](concept-aliases.md).
Por ejemplo:
@ -160,8 +137,7 @@ class PostController extends Controller
Dentro de [widgets](structure-widgets.md), puedes llamar a cualquier de los siguientes métodos de widget para renderizar una vista.
* [[yii\base\Widget::render()|render()]]: renderiza la [vista nombrada](#named-views).
* [[yii\base\Widget::renderFile()|renderFile()]]: renderiza la vista especificada en términos de ruta al archivo o
[alias](concept-aliases.md).
* [[yii\base\Widget::renderFile()|renderFile()]]: renderiza la vista especificada en términos de ruta al archivo o [alias](concept-aliases.md).
Por ejemplo:
@ -191,13 +167,10 @@ class ListWidget extends Widget
Puedes renderizar una vista dentro de otra vista llamando a algunos de los siguientes métodos provistos por el [[yii\base\View|componente view]]:
* [[yii\base\View::render()|render()]]: renderiza la [vista nombrada](#named-views).
* [[yii\web\View::renderAjax()|renderAjax()]]: renderiza la [vista nombrada](#named-views) e inyecta todos los
archivos y scripts JS/CSS. Esto sucede usualmente en respuestas a llamadas a AJAX `requests`.
* [[yii\base\View::renderFile()|renderFile()]]: renderiza la vista especificada en términos de ruta al archivo o
[alias](concept-aliases.md).
* [[yii\web\View::renderAjax()|renderAjax()]]: renderiza la [vista nombrada](#named-views) e inyecta todos los archivos y scripts JS/CSS. Esto sucede usualmente en respuestas a llamadas a AJAX `requests`.
* [[yii\base\View::renderFile()|renderFile()]]: renderiza la vista especificada en términos de ruta al archivo o [alias](concept-aliases.md).
Por ejemplo, el siguiente código en una vista renderiza el template `_overview.php` encontrado en el mismo directorio
de la vista renderizada actualmente. Recuerda que la variable `$this` en una vista se refiere al componente [[yii\base\View|view]]:
Por ejemplo, el siguiente código en una vista renderiza el template `_overview.php` encontrado en el mismo directorio de la vista renderizada actualmente. Recuerda que la variable `$this` en una vista se refiere al componente [[yii\base\View|view]]:
```php
<?= $this->render('_overview') ?>
@ -217,43 +190,25 @@ echo \Yii::$app->view->renderFile('@app/views/site/license.php');
### Vistas Nombradas <a name="named-views"></a>
Cuando renderizas una vista, puedes especificar el template utilizando tanto el nombre de la vista o la ruta/alias al archivo. En la mayoría de los casos,
utilizarías la primera porque es más concisa y flexible. *Vistas nombradas* son vistas especificadas mediante un nombre en vez de una ruta al archivo o alias.
Cuando renderizas una vista, puedes especificar el template utilizando tanto el nombre de la vista o la ruta/alias al archivo. En la mayoría de los casos, utilizarías la primera porque es más concisa y flexible. *Vistas nombradas* son vistas especificadas mediante un nombre en vez de una ruta al archivo o alias.
Un nombre de vista es resuelto a su correspondiente ruta de archivo siguiendo las siguientes reglas:
* Un nombre de vista puede omitir la extensión del archivo. En estos casos se utilizará `.php` como extensión del archivo. Por ejemplo,
el nombre de vista `about` corresponde al archivo `about.php`.
* Un nombre de vista puede omitir la extensión del archivo. En estos casos se utilizará `.php` como extensión del archivo. Por ejemplo, el nombre de vista `about` corresponde al archivo `about.php`.
* Si el nombre de la vista comienza con doble barra (`//`), la ruta al archivo correspondiente será `@app/views/ViewName`.
Esto quiere decir que la vista es buscada bajo el [[yii\base\Application::viewPath|view path de la aplicación]].
Por ejemplo, `//site/about` será resuelto como `@app/views/site/about.php`.
* Si el nombre de la vista comienza con una barra simple `/`, la ruta al archivo de la vista utilizará como prefijo el nombre de la vista
con el [[yii\base\Module::viewPath|view path]] del [módulo](structure-modules.md) utilizado actualmente.
Si no hubiera módulo activo se utilizará `@app/views/ViewName`. Por ejemplo, `/user/create` será resuelto a
`@app/modules/user/views/user/create.php` si el módulo activo es `user`. Si no hubiera módulo activo,
la ruta al archivo será `@app/views/user/create.php`.
* Si la vista es renderizada con un [[yii\base\View::context|context]] y dicho contexto implementa [[yii\base\ViewContextInterface]],
la ruta al archivo se forma utilizando como prefijo el [[yii\base\ViewContextInterface::getViewPath()|view path]]
del contexto de la vista. Esto principalmente aplica a vistas renderizadas en controladores y widgets. Por ejemplo,
`site/about` será resuelto a `@app/views/site/about.php` si el contexto es el controlador `SiteController`.
* Si la vista es renderizada dentro de otra vista, el directorio que contiene la otra vista será prefijado
al nuevo nombre de la vista para formar la ruta a la vista. Por ejemplo, `item` sera resuelto a `@app/views/post/item`
si está siendo renderizado desde la vista `@app/views/post/index.php`.
De acuerdo a las reglas mencionadas, al llamar a `$this->render('view')` en el controlador `app\controllers\PostController`
se renderizará el template `@app/views/post/view.php`, mientras que llamando a `$this->render('_overview')` en la vista
renderizará el template `@app/views/post/_overview.php`.
Esto quiere decir que la vista es buscada bajo el [[yii\base\Application::viewPath|view path de la aplicación]].
Por ejemplo, `//site/about` será resuelto como `@app/views/site/about.php`.
* Si el nombre de la vista comienza con una barra simple `/`, la ruta al archivo de la vista utilizará como prefijo el nombre de la vista con el [[yii\base\Module::viewPath|view path]] del [módulo](structure-modules.md) utilizado actualmente. Si no hubiera módulo activo se utilizará `@app/views/ViewName`. Por ejemplo, `/user/create` será resuelto a `@app/modules/user/views/user/create.php` si el módulo activo es `user`. Si no hubiera módulo activo, la ruta al archivo será `@app/views/user/create.php`.
* Si la vista es renderizada con un [[yii\base\View::context|context]] y dicho contexto implementa [[yii\base\ViewContextInterface]], la ruta al archivo se forma utilizando como prefijo el [[yii\base\ViewContextInterface::getViewPath()|view path]] del contexto de la vista. Esto principalmente aplica a vistas renderizadas en controladores y widgets. Por ejemplo, `site/about` será resuelto a `@app/views/site/about.php` si el contexto es el controlador `SiteController`.
* Si la vista es renderizada dentro de otra vista, el directorio que contiene la otra vista será prefijado al nuevo nombre de la vista para formar la ruta a la vista. Por ejemplo, `item` sera resuelto a `@app/views/post/item` si está siendo renderizado desde la vista `@app/views/post/index.php`.
De acuerdo a las reglas mencionadas, al llamar a `$this->render('view')` en el controlador `app\controllers\PostController` se renderizará el template `@app/views/post/view.php`, mientras que llamando a `$this->render('_overview')` en la vista renderizará el template `@app/views/post/_overview.php`.
### Accediendo a Datos en la Vista <a name="accessing-data-in-views"></a>
Hay dos modos posibles de acceder a los datos en la vista: push (inyectar) y pull (traer).
Al pasar los datos como segundo parámetro en algún método de renderización, estás utilizando el modo push.
Los datos deberían ser representados como un array de pares clave-valor. Cuando la vista está siendo renderizada, la función PHP
`extract()` será llamada sobre este array así se extraen las variables que contiene a la vista actual .
Por ejemplo, el siguiente código de renderización en un controlador inyectará dos variables a la vista `report`:
`$foo = 1` and `$bar = 2`.
Al pasar los datos como segundo parámetro en algún método de renderización, estás utilizando el modo push. Los datos deberían ser representados como un array de pares clave-valor. Cuando la vista está siendo renderizada, la función PHP `extract()` será llamada sobre este array así se extraen las variables que contiene a la vista actual. Por ejemplo, el siguiente código de renderización en un controlador inyectará dos variables a la vista `report`: `$foo = 1` and `$bar = 2`.
```php
echo $this->render('report', [
@ -262,35 +217,26 @@ echo $this->render('report', [
]);
```
El modo pull obtiene los datos del [[yii\base\View|componente view]] u otros objetos accesibles
en las vistas (ej. `Yii::$app`). Utilizando el código anterior como ejemplo, dentro de una vista puedes acceder al objeto del controlador
a través de la expresión `$this->context`. Como resultado, te es posible acceder a cualquier propiedad o método
del controlador en la vista `report`, tal como el ID del controlador como se muestra a continuación:
El modo pull obtiene los datos del [[yii\base\View|componente view]] u otros objetos accesibles en las vistas (ej. `Yii::$app`). Utilizando el código anterior como ejemplo, dentro de una vista puedes acceder al objeto del controlador a través de la expresión `$this->context`. Como resultado, te es posible acceder a cualquier propiedad o método del controlador en la vista `report`, tal como el ID del controlador como se muestra a continuación:
```php
El ID del controlador es: <?= $this->context->id ?>
?>
```
Para acceder a datos en la vista, normalmente se prefiere el modo push, ya que hace a la vista menos dependiente
de los objetos del contexto. La contra es que tienes que construir el array manualmente cada vez, lo que podría
volverse tedioso y propenso al error si la misma vista es compartida y renderizada desde diferentes lugares.
Para acceder a datos en la vista, normalmente se prefiere el modo push, ya que hace a la vista menos dependiente de los objetos del contexto. La contra es que tienes que construir el array manualmente cada vez, lo que podría volverse tedioso y propenso al error si la misma vista es compartida y renderizada desde diferentes lugares.
### Compartiendo Datos Entre las Vistas <a name="sharing-data-among-views"></a>
El [[yii\base\View|componente view]] provee la propiedad [[yii\base\View::params|params]] para que puedas compartir
datos entre diferentes vistas.
El [[yii\base\View|componente view]] provee la propiedad [[yii\base\View::params|params]] para que puedas compartir datos entre diferentes vistas.
Por ejemplo, en una vista `about`, podrías tener el siguiente código que especifica el segmento actual
del breadcrumbs (migas de pan).
Por ejemplo, en una vista `about`, podrías tener el siguiente código que especifica el segmento actual del breadcrumbs (migas de pan).
```php
$this->params['breadcrumbs'][] = 'Acerca de Nosotros';
```
Entonces, en el archivo del [layout](#layouts), que es también una vista, puedes mostrar el breadcrumbs utilizando los datos
pasados a través de [[yii\base\View::params|params]]:
Entonces, en el archivo del [layout](#layouts), que es también una vista, puedes mostrar el breadcrumbs utilizando los datos pasados a través de [[yii\base\View::params|params]]:
```php
<?= yii\widgets\Breadcrumbs::widget([
@ -301,22 +247,14 @@ pasados a través de [[yii\base\View::params|params]]:
## Layouts <a name="layouts"></a>
Los layouts son un tipo especial de vista que representan partes comunes de otras múltiples vistas. Por ejemplo, las páginas
de la mayoría de las aplicaciones Web comparten el mismo encabezado y pie de página. Aunque puedes repetirlos en todas y cada una
de las vistas, una mejor forma es hacerlo sólo en el layout e incrustar el resultado de la renderización de la vista en
un lugar apropiado del mismo.
Los layouts son un tipo especial de vista que representan partes comunes de otras múltiples vistas. Por ejemplo, las páginas de la mayoría de las aplicaciones Web comparten el mismo encabezado y pie de página. Aunque puedes repetirlos en todas y cada una de las vistas, una mejor forma es hacerlo sólo en el layout e incrustar el resultado de la renderización de la vista en un lugar apropiado del mismo.
### Creando Layouts <a name="creating-layouts"></a>
Dado que los layouts son también vistas, pueden ser creados de manera similar a las vistas comunes. Por defecto, los layouts
son guardados en el directorio `@app/views/layouts`. Para layouts utilizados dentro de un [módulo](structure-modules.md),
deberían ser guardados en el directorio `views/layouts` bajo el [[yii\base\Module::basePath|directorio del módulo]].
Puedes personalizar el directorio de layouts por defecto configurando la propiedad [[yii\base\Module::layoutPath]] de
la aplicación o módulos.
Dado que los layouts son también vistas, pueden ser creados de manera similar a las vistas comunes. Por defecto, los layouts son guardados en el directorio `@app/views/layouts`. Para layouts utilizados dentro de un [módulo](structure-modules.md), deberían ser guardados en el directorio `views/layouts` bajo el [[yii\base\Module::basePath|directorio del módulo]]. Puedes personalizar el directorio de layouts por defecto configurando la propiedad [[yii\base\Module::layoutPath]] de la aplicación o módulos.
El siguiente ejemplo muestra cómo debe verse un layout. Ten en cuenta que por motivos ilustrativos, hemos simplificado bastante
el código del layout. En la práctica, probablemente le agregues más contenido, como tags en el `head`, un menú principal, etc.
El siguiente ejemplo muestra cómo debe verse un layout. Ten en cuenta que por motivos ilustrativos, hemos simplificado bastante el código del layout. En la práctica, probablemente le agregues más contenido, como tags en el `head`, un menú principal, etc.
```php
<?php
@ -345,51 +283,29 @@ use yii\helpers\Html;
<?php $this->endPage() ?>
```
Como puedes ver, el layout genera los tags HTML comunes a todas las páginas. Dentro de la sección `<body>`,
el layout imprime la variable `$content`, que representa el resultado de la renderización del contenido de cada vista y es incrustado
dentro del layout cuando se llama al método [[yii\base\Controller::render()]].
La mayoría de layouts deberían llamar a los siguientes métodos (como fue mostrado recién). Estos métodos principalmente disparan eventos
acerca del proceso de renderizado así los scripts y tags registrados en otros lugares pueden ser propiamente inyectados en
los lugares donde los métodos son llamados.
- [[yii\base\View::beginPage()|beginPage()]]: Este método debería ser llamado bien al principio del layout.
Esto dispara el evento [[yii\base\View::EVENT_BEGIN_PAGE|EVENT_BEGIN_PAGE]], el cual indica el comienzo de la página.
- [[yii\base\View::endPage()|endPage()]]: Este método debería ser llamado al final del layout.
Esto dispara el evento [[yii\base\View::EVENT_END_PAGE|EVENT_END_PAGE]], indicando el final de la página.
- [[yii\web\View::head()|head()]]: Este método debería llamarse dentro de la sección `<head>` de una página HTML.
Esto genera un espacio vacío que será reemplazado con el código del head HTML registrado (ej. link tags, meta tags)
cuando una página finaliza el renderizado.
- [[yii\base\View::beginBody()|beginBody()]]: Este método debería llamarse al principio de la sección `<body>`.
Esto dispara el evento [[yii\web\View::EVENT_BEGIN_BODY|EVENT_BEGIN_BODY]] y genera un espacio vacío que será
reemplazado con el código HTML registrado (ej. JavaScript) que apunta al principio del body.
- [[yii\base\View::endBody()|endBody()]]: Este método debería llamarse al final de la sección `<body>`.
Esto dispara el evento [[yii\web\View::EVENT_END_BODY|EVENT_END_BODY]], que genera un espacio vacío a ser reemplazado
por el código HTML registrado (ej. JavaScript) que apunta al final del body.
Como puedes ver, el layout genera los tags HTML comunes a todas las páginas. Dentro de la sección `<body>`,el layout imprime la variable `$content`, que representa el resultado de la renderización del contenido de cada vista y es incrustado dentro del layout cuando se llama al método [[yii\base\Controller::render()]].
La mayoría de layouts deberían llamar a los siguientes métodos (como fue mostrado recién). Estos métodos principalmente disparan eventos acerca del proceso de renderizado así los scripts y tags registrados en otros lugares pueden ser propiamente inyectados en los lugares donde los métodos son llamados.
- [[yii\base\View::beginPage()|beginPage()]]: Este método debería ser llamado bien al principio del layout. Esto dispara el evento [[yii\base\View::EVENT_BEGIN_PAGE|EVENT_BEGIN_PAGE]], el cual indica el comienzo de la página.
- [[yii\base\View::endPage()|endPage()]]: Este método debería ser llamado al final del layout. Esto dispara el evento [[yii\base\View::EVENT_END_PAGE|EVENT_END_PAGE]], indicando el final de la página.
- [[yii\web\View::head()|head()]]: Este método debería llamarse dentro de la sección `<head>` de una página HTML. Esto genera un espacio vacío que será reemplazado con el código del head HTML registrado (ej. link tags, meta tags) cuando una página finaliza el renderizado.
- [[yii\base\View::beginBody()|beginBody()]]: Este método debería llamarse al principio de la sección `<body>`. Esto dispara el evento [[yii\web\View::EVENT_BEGIN_BODY|EVENT_BEGIN_BODY]] y genera un espacio vacío que será reemplazado con el código HTML registrado (ej. JavaScript) que apunta al principio del body.
- [[yii\base\View::endBody()|endBody()]]: Este método debería llamarse al final de la sección `<body>`. Esto dispara el evento [[yii\web\View::EVENT_END_BODY|EVENT_END_BODY]], que genera un espacio vacío a ser reemplazado por el código HTML registrado (ej. JavaScript) que apunta al final del body.
### Accediendo a Datos en Layouts <a name="accessing-data-in-layouts"></a>
Dentro de un layout, tienes acceso a dos variables predefinidas: `$this` y `$content`. La primera se refiere
al componente [[yii\base\View|view]], como en cualquier vista, mientras que la última contiene el resultado de la renderización del contenido
de la vista que está siendo renderizada all llamar al método [[yii\base\Controller::render()|render()]] en los controladores.
Dentro de un layout, tienes acceso a dos variables predefinidas: `$this` y `$content`. La primera se refiere al componente [[yii\base\View|view]], como en cualquier vista, mientras que la última contiene el resultado de la renderización del contenido de la vista que está siendo renderizada all llamar al método [[yii\base\Controller::render()|render()]] en los controladores.
Si quieres acceder a otros datos en los layouts, debes utilizar el modo pull que fue descrito en la sub-sección
[Accediendo a Datos en la Vista](#accessing-data-in-views). Si quieres pasar datos desde al contenido de la vista
a un layout, puedes utilizar el método descrito en la sub-sección [Compartiendo Datos Entre las Vistas](#sharing-data-among-views).
Si quieres acceder a otros datos en los layouts, debes utilizar el modo pull que fue descrito en la sub-sección [Accediendo a Datos en la Vista](#accessing-data-in-views). Si quieres pasar datos desde al contenido de la vista a un layout, puedes utilizar el método descrito en la sub-sección [Compartiendo Datos Entre las Vistas](#sharing-data-among-views).
### Utilizando Layouts <a name="using-layouts"></a>
Como se describe en la sub-sección [Renderizando en Controllers](#rendering-in-controllers), cuando renderizas una vista
llamando al método [[yii\base\Controller::render()|render()]] en un controlador, al resultado de dicha renderización
le será aplicado un layout. Por defecto, el layout `@app/views/layouts/main.php` será el utilizado.
Como se describe en la sub-sección [Renderizando en Controllers](#rendering-in-controllers), cuando renderizas una vista llamando al método [[yii\base\Controller::render()|render()]] en un controlador, al resultado de dicha renderización le será aplicado un layout. Por defecto, el layout `@app/views/layouts/main.php` será el utilizado.
Puedes utilizar un layout diferente configurando la propiedad [[yii\base\Application::layout]] o [[yii\base\Controller::layout]].
El primero se refiere al layout utilizado por todos los controladores, mientras que el último sobrescribe el layout en controladores individuales.
Por ejemplo, el siguiente código hace que el controlador `post` utilice `@app/views/layouts/post.php` como layout
al renderizar sus vistas. Otros controladores, asumiendo que su propiedad `layout` no fue modificada, utilizarán
`@app/views/layouts/main.php` como layout.
Puedes utilizar un layout diferente configurando la propiedad [[yii\base\Application::layout]] o [[yii\base\Controller::layout]]. El primero se refiere al layout utilizado por todos los controladores, mientras que el último sobrescribe el layout en controladores individuales. Por ejemplo, el siguiente código hace que el controlador `post` utilice `@app/views/layouts/post.php` como layout al renderizar sus vistas. Otros controladores, asumiendo que su propiedad `layout` no fue modificada, utilizarán `@app/views/layouts/main.php` como layout.
```php
namespace app\controllers;
@ -404,31 +320,20 @@ class PostController extends Controller
}
```
Para controladores que pertencen a un módulo, puedes también configurar la propiedad [[yii\base\Module::layout|layout]] y así
utilizar un layout en particular para esos controladores.
Para controladores que pertencen a un módulo, puedes también configurar la propiedad [[yii\base\Module::layout|layout]] y así utilizar un layout en particular para esos controladores.
Dado que la propiedad `layout` puede ser configurada en diferentes niveles (controladores, módulos, aplicación),
detrás de escena Yii realiza dos pasos para determinar cuál es el archivo de layout siendo utilizado para un controlador en particular.
Dado que la propiedad `layout` puede ser configurada en diferentes niveles (controladores, módulos, aplicación), detrás de escena Yii realiza dos pasos para determinar cuál es el archivo de layout siendo utilizado para un controlador en particular.
En el primer paso, determina el valor del layout y el módulo de contexto:
- Si la propiedad [[yii\base\Controller::layout]] no es `null`, la utiliza como valor del layout y
el [[yii\base\Controller::module|módulo]] del controlador como el módulo de contexto.
- Si [[yii\base\Controller::layout|layout]] es `null`, busca a través de todos los módulos ancestros del controlador y
encuentra el primer módulo cuya propiedad [[yii\base\Module::layout|layout]] no es `null`. Utiliza ese módulo y
su valor de [[yii\base\Module::layout|layout]] como módulo de contexto y como layout seleccionado.
Si tal módulo no puede ser encontrado, significa que no se aplicará ningún layout.
- Si la propiedad [[yii\base\Controller::layout]] no es `null`, la utiliza como valor del layout y el [[yii\base\Controller::module|módulo]] del controlador como el módulo de contexto.
- Si [[yii\base\Controller::layout|layout]] es `null`, busca a través de todos los módulos ancestros del controlador y encuentra el primer módulo cuya propiedad [[yii\base\Module::layout|layout]] no es `null`. Utiliza ese módulo y su valor de [[yii\base\Module::layout|layout]] como módulo de contexto y como layout seleccionado. Si tal módulo no puede ser encontrado, significa que no se aplicará ningún layout.
En el segundo paso, se determina el archivo de layout actual de acuerdo al valor de layout y el módulo de contexto
determinado en el primer paso. El valor de layout puede ser:
En el segundo paso, se determina el archivo de layout actual de acuerdo al valor de layout y el módulo de contexto determinado en el primer paso. El valor de layout puede ser:
- un alias de ruta (ej. `@app/views/layouts/main`).
- una ruta absoluta (ej. `/main`): el valor del layout comienza con una barra. El archivo de layout actual será
buscado bajo el [[yii\base\Application::layoutPath|layout path]] de la aplicación, que es por defecto
`@app/views/layouts`.
- una ruta relativa (ej. `main`): El archivo de layout actual será buscado bajo el
[[yii\base\Module::layoutPath|layout path]] del módulo de contexto, que es por defecto el directorio `views/layouts`
bajo el [[yii\base\Module::basePath|directorio del módulo]].
- una ruta absoluta (ej. `/main`): el valor del layout comienza con una barra. El archivo de layout actual será buscado bajo el [[yii\base\Application::layoutPath|layout path]] de la aplicación, que es por defecto `@app/views/layouts`.
- una ruta relativa (ej. `main`): El archivo de layout actual será buscado bajo el [[yii\base\Module::layoutPath|layout path]] del módulo de contexto, que es por defecto el directorio `views/layouts` bajo el [[yii\base\Module::basePath|directorio del módulo]].
- el valor booleano `false`: no se aplicará ningún layout.
Si el valor de layout no contiene una extensión de tipo de archivo, utilizará por defecto `.php`.
@ -436,10 +341,7 @@ Si el valor de layout no contiene una extensión de tipo de archivo, utilizará
### Layouts Anidados <a name="nested-layouts"></a>
A veces podrías querer anidar un layout dentro de otro. Por ejemplo, en diferentes secciones de un sitio Web, podrías
querer utilizar layouts diferentes, mientras que todos esos layouts comparten el mismo layout básico que genera la
estructura general de la página en HTML5. Esto es posible llamando a los métodos [[yii\base\View::beginContent()|beginContent()]] y
[[yii\base\View::endContent()|endContent()]] en los layouts hijos como se muestra a continuación:
A veces podrías querer anidar un layout dentro de otro. Por ejemplo, en diferentes secciones de un sitio Web, podrías querer utilizar layouts diferentes, mientras que todos esos layouts comparten el mismo layout básico que genera la estructura general de la página en HTML5. Esto es posible llamando a los métodos [[yii\base\View::beginContent()|beginContent()]] y [[yii\base\View::endContent()|endContent()]] en los layouts hijos como se muestra a continuación:
```php
<?php $this->beginContent('@app/views/layouts/base.php'); ?>
@ -449,19 +351,14 @@ estructura general de la página en HTML5. Esto es posible llamando a los métod
<?php $this->endContent(); ?>
```
Como se acaba de mostrar, el contenido del layout hijo debe ser encerrado dentro de [[yii\base\View::beginContent()|beginContent()]] y
[[yii\base\View::endContent()|endContent()]]. El parámetro pasado a [[yii\base\View::beginContent()|beginContent()]]
especifica cuál es el módulo padre. Este puede ser tanto un archivo layout como un alias.
Como se acaba de mostrar, el contenido del layout hijo debe ser encerrado dentro de [[yii\base\View::beginContent()|beginContent()]] y [[yii\base\View::endContent()|endContent()]]. El parámetro pasado a [[yii\base\View::beginContent()|beginContent()]] especifica cuál es el módulo padre. Este puede ser tanto un archivo layout como un alias.
Utilizando la forma recién mencionada, puedes anidar layouts en más de un nivel.
## Utilizando Componentes de Vista <a name="using-view-components"></a>
Los [[yii\base\View|componentes de vista]] proveen características relacionadas a las vistas. Aunque puedes obtener componentes de vista
creando instancias individuales de [[yii\base\View]] o sus clases hijas, en la mayoría de los casos utilizarías el
componente `view` del a aplicación. Puedes configurar este componente en la [configuración de la aplicación](structure-applications.md#application-configurations)
como a continuación:
Los [[yii\base\View|componentes de vista]] proveen características relacionadas a las vistas. Aunque puedes obtener componentes de vista creando instancias individuales de [[yii\base\View]] o sus clases hijas, en la mayoría de los casos utilizarías el componente `view` del a aplicación. Puedes configurar este componente en la [configuración de la aplicación](structure-applications.md#application-configurations) como a continuación:
```php
[
@ -489,9 +386,7 @@ Puedes también utilizar frecuentemente el siguiente menor pero útil grupo de c
### Definiendo Títulos de Página <a name="setting-page-titles"></a>
Toda página Web debería tener un título. Normalmente el tag de título es generado en [layout](#layouts). De todos modos, en la práctica
el título es determinado en el contenido de las vistas más que en layouts. Para resolver este problema, [[yii\web\View]] provee
la propiedad [[yii\web\View::title|title]] para que puedas pasar información del título desde el contenido de la vista a los layouts.
Toda página Web debería tener un título. Normalmente el tag de título es generado en [layout](#layouts). De todos modos, en la práctica el título es determinado en el contenido de las vistas más que en layouts. Para resolver este problema, [[yii\web\View]] provee la propiedad [[yii\web\View::title|title]] para que puedas pasar información del título desde el contenido de la vista a los layouts.
Para utilizar esta característica, en cada contenido de la vista, puedes definir el título de la siguiente manera:
@ -510,11 +405,9 @@ Entonces en el layout, asegúrate de tener el siguiente código en la sección `
### Registrando Meta Tags <a name="registering-meta-tags"></a>
Las páginas Web usualmente necesitan generar varios meta tags necesarios por diferentes grupos (ej. Facebook, motores de búsqueda, etc).
Cómo los títulos de página, los meta tags aparecen en la sección `<head>` y son usualmente generado en los layouts.
Las páginas Web usualmente necesitan generar varios meta tags necesarios por diferentes grupos (ej. Facebook, motores de búsqueda, etc). Cómo los títulos de página, los meta tags aparecen en la sección `<head>` y son usualmente generado en los layouts.
Si quieres especificar cuáles meta tags generar en las vistas, puedes llamar a [[yii\web\View::registerMetaTag()]]
dentro de una de ellas, como se muestra a continuación:
Si quieres especificar cuáles meta tags generar en las vistas, puedes llamar a [[yii\web\View::registerMetaTag()]] dentro de una de ellas, como se muestra a continuación:
```php
<?php
@ -522,19 +415,15 @@ $this->registerMetaTag(['name' => 'keywords', 'content' => 'yii, framework, php'
?>
```
El código anterior registrará el meta tag "keywords" a través del componente view. El meta tag registrado no
se renderiza hasta que finaliza el renderizado del layout. Para entonces, el siguiente código HTML será insertado
en el lugar donde llamas a [[yii\web\View::head()]] en el layout, generando el siguiente HTML:
El código anterior registrará el meta tag "keywords" a través del componente view. El meta tag registrado no se renderiza hasta que finaliza el renderizado del layout. Para entonces, el siguiente código HTML será insertado en el lugar donde llamas a [[yii\web\View::head()]] en el layout, generando el siguiente HTML:
```php
<meta name="keywords" content="yii, framework, php">
```
Ten en cuenta que si llamas a [[yii\web\View::registerMetaTag()]] varias veces, esto registrará varios meta tags,
sin tener en cuenta si los meta tags son los mismo o no.
Ten en cuenta que si llamas a [[yii\web\View::registerMetaTag()]] varias veces, esto registrará varios meta tags, sin tener en cuenta si los meta tags son los mismo o no.
Para asegurarte de que sólo haya una instancia de cierto tipo de meta tag, puedes especificar una clave al llamar al método.
Por ejemplo, el siguiente código registra dos meta tags "description", aunque sólo el segundo será renderizado.
Para asegurarte de que sólo haya una instancia de cierto tipo de meta tag, puedes especificar una clave al llamar al método. Por ejemplo, el siguiente código registra dos meta tags "description", aunque sólo el segundo será renderizado.
```html
$this->registerMetaTag(['name' => 'description', 'content' => 'Este es mi sitio Web cool hecho con Yii!'], 'description');
@ -544,9 +433,7 @@ $this->registerMetaTag(['name' => 'description', 'content' => 'Este sitio Web es
### Registrando Link Tags <a name="registering-link-tags"></a>
Tal como los [meta tags](#adding-meta-tags), los link tags son útiles en muchos casos, como personalizar el ícono (favicon) del sitio, apuntar a
una fuente de RSS o delegar OpenID a otro servidor. Puedes trabajar con link tags, al igual que con meta tags,
utilizando [[yii\web\View::registerLinkTag()]]. Por ejemplo, en el contenido de una vista, puedes registrar un link tag como se muestra a continuación:
Tal como los [meta tags](#adding-meta-tags), los link tags son útiles en muchos casos, como personalizar el ícono (favicon) del sitio, apuntar a una fuente de RSS o delegar OpenID a otro servidor. Puedes trabajar con link tags, al igual que con meta tags, utilizando [[yii\web\View::registerLinkTag()]]. Por ejemplo, en el contenido de una vista, puedes registrar un link tag como se muestra a continuación:
```php
$this->registerLinkTag([
@ -563,20 +450,16 @@ El resultado del código es el siguiente:
<link title="Noticias en Vivo de Yii" rel="alternate" type="application/rss+xml" href="http://www.yiiframework.com/rss.xml/">
```
Al igual que con [[yii\web\View::registerMetaTag()|registerMetaTags()]], puedes especificar una clave al llamar a
[[yii\web\View::registerLinkTag()|registerLinkTag()]] para evitar registrar link tags repetidos.
Al igual que con [[yii\web\View::registerMetaTag()|registerMetaTags()]], puedes especificar una clave al llamar a [[yii\web\View::registerLinkTag()|registerLinkTag()]] para evitar registrar link tags repetidos.
## Eventos de Vistas <a name="view-events"></a>
Los [[yii\base\View|componentes de vistas]] disparan varios eventos durante el proceso de renderizado de la vista. Puedes responder
a estos eventos para inyectar contenido a la vista o procesar el resultado de la renderización antes de que sea enviada al usuario final.
Los [[yii\base\View|componentes de vistas]] disparan varios eventos durante el proceso de renderizado de la vista. Puedes responder a estos eventos para inyectar contenido a la vista o procesar el resultado de la renderización antes de que sea enviada al usuario final.
- [[yii\base\View::EVENT_BEFORE_RENDER|EVENT_BEFORE_RENDER]]: disparado al principio del renderizado de un archivo
en un controlador. Los manejadores de este evento pueden definir [[yii\base\ViewEvent::isValid]] como `false` para cancelar el proceso de renderizado.
- [[yii\base\View::EVENT_BEFORE_RENDER|EVENT_BEFORE_RENDER]]: disparado al principio del renderizado de un archivo en un controlador. Los manejadores de este evento pueden definir [[yii\base\ViewEvent::isValid]] como `false` para cancelar el proceso de renderizado.
- [[yii\base\View::EVENT_AFTER_RENDER|EVENT_AFTER_RENDER]]: disparado por la llamada a [[yii\base\View::beginPage()]] en layouts.
Los manejadores de este evento pueden obtener el resultado de la renderización a través de [[yii\base\ViewEvent::output]] y entonces modificar
esta propiedad para así cambiar el mismo.
Los manejadores de este evento pueden obtener el resultado de la renderización a través de [[yii\base\ViewEvent::output]] y entonces modificar esta propiedad para así cambiar el mismo.
- [[yii\base\View::EVENT_BEGIN_PAGE|EVENT_BEGIN_PAGE]]: disparado por la llamada a [[yii\base\View::beginPage()]] en layouts.
- [[yii\base\View::EVENT_END_PAGE|EVENT_END_PAGE]]: disparado por la llamada a [[yii\base\View::endPage()]] en layouts.
- [[yii\web\View::EVENT_BEGIN_BODY|EVENT_BEGIN_BODY]]: disparado por la llamada a [[yii\web\View::beginBody()]] en layouts.
@ -591,10 +474,9 @@ Por ejemplo, el siguiente código inyecta la fecha actual al final del body de l
```
## Renderizando Página Estáticas <a name="rendering-static-pages"></a>
## Renderizando Páginas Estáticas <a name="rendering-static-pages"></a>
Con páginas estáticas nos referimos a esas páginas cuyo contenido es mayormente estático y sin necesidad de acceso
a datos dinámicos enviados desde los controladores.
Con páginas estáticas nos referimos a esas páginas cuyo contenido es mayormente estático y sin necesidad de acceso a datos dinámicos enviados desde los controladores.
Puedes generar páginas estáticas utilizando un código como el que sigue dentro de un controlador:
@ -605,9 +487,7 @@ public function actionAbout()
}
```
Si un sitio Web contiene muchas páginas estáticas, resultaría tedioso repetir el mismo código en muchos lados.
Para resolver este problema, puedes introducir una [acción independiente](structure-controllers.md#standalone-actions)
llamada [[yii\web\ViewAction]] en el controlador. Por ejemplo,
Si un sitio Web contiene muchas páginas estáticas, resultaría tedioso repetir el mismo código en muchos lados. Para resolver este problema, puedes introducir una [acción independiente](structure-controllers.md#standalone-actions) llamada [[yii\web\ViewAction]] en el controlador. Por ejemplo,
```php
namespace app\controllers;
@ -627,16 +507,13 @@ class SiteController extends Controller
}
```
Ahora, si creamos una vista llamada `about` bajo el directorio `@app/views/site/pages`, serás capáz
de mostrarla en la siguiente URL:
Ahora, si creamos una vista llamada `about` bajo el directorio `@app/views/site/pages`, serás capáz de mostrarla en la siguiente URL:
```
http://localhost/index.php?r=site/page&view=about
```
El parámetro `GET` `view` le comunica a [[yii\web\ViewAction]] cuál es la vista solicitada. La acción entonces buscará
esta vista dentro de `@app/views/site/pages`. Puedes configurar la propiedad [[yii\web\ViewAction::viewPrefix]]
para cambiar el directorio en el que se buscarán dichas páginas.
El parámetro `GET` `view` le comunica a [[yii\web\ViewAction]] cuál es la vista solicitada. La acción entonces buscará esta vista dentro de `@app/views/site/pages`. Puedes configurar la propiedad [[yii\web\ViewAction::viewPrefix]] para cambiar el directorio en el que se buscarán dichas páginas.
## Buenas Prácticas <a name="best-practices"></a>
@ -646,15 +523,12 @@ Las vistas son responsables de la presentación de modelos en el formato que el
* deberían contener principalmente sólo código de presentación, como HTML, y PHP simple para recorrer, dar formato y renderizar datos.
* no deberían contener código que realiza consultas a la base de datos. Ese tipo de código debe ir en los modelos.
* deberían evitar el acceso directo a datos del `request`, como `$_GET` y/o `$_POST`. Esto es una responsabilidad de los controladores.
Si se necesitan datos del `request`, deben ser inyectados a la vista desde el controlador.
Si se necesitan datos del `request`, deben ser inyectados a la vista desde el controlador.
* pueden leer propiedades del modelo, pero no debería modificarlas.
Para hacer las vistas más manejables, evita crear vistas que son demasiado complejas o que contengan código redundante.
Puedes utilizar estas técnicas para alcanzar dicha meta:
Para hacer las vistas más manejables, evita crear vistas que son demasiado complejas o que contengan código redundante. Puedes utilizar estas técnicas para alcanzar dicha meta:
* utiliza [layouts](#layouts) para representar secciones comunes (ej. encabezado y footer de la página).
* divide una vista compleja en varias más simples. Las vistas pequeñas pueden ser renderizadas y unidas una mayor
utilizando los métodos de renderización antes descritos.
* divide una vista compleja en varias más simples. Las vistas pequeñas pueden ser renderizadas y unidas una mayor utilizando los métodos de renderización antes descritos.
* crea y utiliza [widgets](structure-widgets.md) como bloques de construcción de la vista.
* crea y utilizar helpers para transformar y dar formato a los datos en la vista.

7
docs/guide-es/structure-widgets.md

@ -1,7 +1,7 @@
Widgets
=======
Los Widgets son bloques de código reutilizables utilizados en las [vistas](structure-views.md) para crear elementos de interfaz de usuario complejos y configurables de forma orientada a objetos. Por ejemplo, widget selector de fechas puede generar un selector de fechas de lujo que permita a los usuarios seleccionar una fecha. Todo lo que se tiene que hacer es insertar el siguiente código en una vista.
Los Widgets son bloques de código reutilizables utilizados en las [vistas](structure-views.md) para crear elementos de interfaz de usuario complejos y configurables de forma orientada a objetos. Por ejemplo, widget DatePicker puede generar un DatePicker de lujo que permita a los usuarios seleccionar una fecha. Todo lo que se tiene que hacer es insertar el siguiente código en una vista.
```php
<?php
@ -14,7 +14,7 @@ Hay un buen número de widgets incluidos en Yii, tales como [[yii\widgets\Active
## Uso de los Widgets <a name="using-widgets"></a>
Los Widgets son usados principalmente en las [vistas](structure-views.md). Se puede llamar al método [[yii\base\Widget::widget()]] para usar un widget en una vista. El método obtiene un array de [configuración](concept-configurations.md) para inicializar el widget y retorna la representación resultante del widget. Por ejemplo, el siguiente código inserta un widget selector de fechas que esta configurado para usar el idioma Ruso y mantener la entrada en atributo 'form_date' del '$model'.
Los Widgets son usados principalmente en las [vistas](structure-views.md). Se puede llamar al método [[yii\base\Widget::widget()]] para usar un widget en una vista. El método obtiene un array de [configuración](concept-configurations.md) para inicializar el widget y retorna la representación resultante del widget. Por ejemplo, el siguiente código inserta un widget DatePicker que esta configurado para usar el idioma Ruso y mantener la entrada en atributo 'form_date' del '$model'.
```php
<?php
@ -151,7 +151,6 @@ Los widgets son una manera orientada a objetos de reutilizar código de las vist
Cuando se crean widgets, se debería continuar manteniendo el patrón MVC. En general, se debería mantener la lógica en las clases del widget y mantener la presentación en las [vistas](structure-views.md).
Los widgets deberían ser diseñados para ser autónomos. Es decir, cuando se usa un widget, se debería poder poner en una vista sin hacer nada más. Esto puede resultar complicado si un widget requiere recursos externos, tales como CSS, JavaScript, imágenes, etc. Afortunadamente Yii proporciona soporte para [paquetes asset](structure-asset-bundles.md) que pueden ser utilizados para resolver el problema.
Los widgets deberían ser diseñados para ser autónomos. Es decir, cuando se usa un widget, se debería poder poner en una vista sin hacer nada más. Esto puede resultar complicado si un widget requiere recursos externos, tales como CSS, JavaScript, imágenes, etc. Afortunadamente Yii proporciona soporte para [paquetes de recursos](structure-asset-bundles.md) que pueden ser utilizados para resolver el problema.
Cuando un widget sólo contiene código de vista, este es muy similar a una [vista](structure-views.md). De hecho, en este caso, su única diferencia es que un widget es una clase redistribuible, mientras que una vista es sólo un script PHP llano que prefiere mantenerse dentro de su aplicación.

2
docs/guide-fr/README.md

@ -31,7 +31,7 @@ Structure Application
---------------------
* [Vue d'ensemble](structure-overview.md)
* [Script d'entrée](structure-entry-scripts.md)
* [Scripts d'entrée](structure-entry-scripts.md)
* [Applications](structure-applications.md)
* [Composants application](structure-application-components.md)
* [Contrôleurs](structure-controllers.md)

36
docs/guide-fr/images/application-lifecycle.graphml

@ -28,7 +28,7 @@
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="-0.5" nodeRatioX="0.0" nodeRatioY="0.5" offsetX="0.0" offsetY="4.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="29.16015625" x="-33.16015625" y="26.002094268798828">user<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="29.16015625" x="-33.16015625" y="26.002094268798828">utilisateur<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@ -48,7 +48,7 @@
<y:Geometry height="45.0" width="119.0" x="789.0653619766235" y="637.1271178722382"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="40.28125" x="39.359375" y="13.43359375">model<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="40.28125" x="39.359375" y="13.43359375">modèle<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@ -65,7 +65,7 @@
<y:Geometry height="46.887996673583984" width="39.527000427246094" x="828.8018617630005" y="544.9831195354463"/>
<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.1328125" modelName="custom" textColor="#000000" visible="true" width="56.27734375" x="-8.375171661376953" y="-30.154888153076172">database<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="56.27734375" x="-8.375171661376953" y="-30.154888153076172">base de donnée<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@ -93,7 +93,7 @@
<y:Geometry height="45.0" width="119.0" x="789.0653619766235" y="713.6271178722382"/>
<y:Fill color="#99CC00" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="29.611328125" x="44.6943359375" y="13.43359375">view<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="29.611328125" x="44.6943359375" y="13.43359375">vue<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@ -113,7 +113,7 @@
<y:Geometry height="376.3268349409104" width="219.27949905395508" x="527.4919853210449" y="408.6371007919311"/>
<y:Fill color="#FFEFD6" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="node_width" backgroundColor="#FF9900" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.666015625" modelName="internal" modelPosition="t" textColor="#000000" visible="true" width="219.27949905395508" x="0.0" y="0.0">controller</y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="node_width" backgroundColor="#FF9900" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.666015625" modelName="internal" modelPosition="t" textColor="#000000" visible="true" width="219.27949905395508" x="0.0" y="0.0">contrôleur</y:NodeLabel>
<y:Shape type="rectangle"/>
<y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/>
@ -139,7 +139,7 @@
<y:Geometry height="30.0" width="150.55899810791016" x="563.2124862670898" y="445.3031164169311"/>
<y:Fill color="#FFFFFF" 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.1328125" modelName="custom" textColor="#000000" visible="true" width="78.888671875" x="35.83516311645508" y="5.93359375">create action<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="78.888671875" x="35.83516311645508" y="5.93359375">créer l'action<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@ -156,7 +156,8 @@
<y:Geometry height="45.0" width="159.91864204406738" x="558.5326642990112" y="521.8166599273682"/>
<y:Fill color="#FFFFFF" 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.1328125" modelName="custom" textColor="#000000" visible="true" width="88.392578125" x="35.76303195953369" y="13.43359375">perform filters<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="88.392578125" x="35.76303195953369" y="13.43359375">effectue
les filtres<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@ -202,7 +203,7 @@
<y:Geometry height="30.0" width="150.55899810791016" x="563.2124862670898" y="644.6271178722382"/>
<y:Fill color="#FFFFFF" 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.1328125" modelName="custom" textColor="#000000" visible="true" width="69.09765625" x="40.73067092895508" y="5.93359375">load model<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="69.09765625" x="40.73067092895508" y="5.93359375">charge un modèle<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@ -219,7 +220,7 @@
<y:Geometry height="30.0" width="150.55899810791016" x="563.2124862670898" y="721.1271178722382"/>
<y:Fill color="#FFFFFF" 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.1328125" modelName="custom" textColor="#000000" visible="true" width="71.599609375" x="39.47969436645508" y="5.93359375">render view<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="71.599609375" x="39.47969436645508" y="5.93359375">génère une vue<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@ -240,7 +241,7 @@
<y:Geometry height="45.0" width="96.0" x="189.47636032104495" y="713.6271178722382"/>
<y:Fill color="#FFCC99" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="56.88671875" x="19.556640625" y="13.43359375">response<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="56.88671875" x="19.556640625" y="13.43359375">réponse<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@ -257,7 +258,7 @@
<y:Geometry height="45.0" width="119.0" x="789.0653619766235" y="254.50096702575684"/>
<y:Fill color="#FFCC99" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="47.88671875" x="35.556640625" y="13.43359375">request<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="47.88671875" x="35.556640625" y="13.43359375">requête<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@ -303,7 +304,7 @@
<y:Geometry height="30.0" width="150.55899810791016" x="563.2124862670898" y="262.00096702575684"/>
<y:Fill color="#FFFFFF" 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.1328125" modelName="custom" textColor="#000000" visible="true" width="80.1484375" x="35.20528030395508" y="5.93359375">resolve route<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="80.1484375" x="35.20528030395508" y="5.93359375">résout la route<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@ -320,7 +321,8 @@
<y:Geometry height="30.0" width="150.55899810791016" x="563.2124862670898" y="322.00096702575684"/>
<y:Fill color="#FFFFFF" 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.1328125" modelName="custom" textColor="#000000" visible="true" width="99.607421875" x="25.475788116455078" y="5.93359375">create controller<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="99.607421875" x="25.475788116455078" y="5.93359375">crée une instance
de contrôleur<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@ -342,7 +344,7 @@
<y:Geometry height="141.666015625" width="159.91864204406738" x="313.2978515625" y="225.33495140075684"/>
<y:Fill color="#FFCC0024" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="node_width" backgroundColor="#FFCC00" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.666015625" modelName="internal" modelPosition="t" textColor="#000000" visible="true" width="159.91864204406738" x="0.0" y="0.0">entry script</y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="node_width" backgroundColor="#FFCC00" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.666015625" modelName="internal" modelPosition="t" textColor="#000000" visible="true" width="159.91864204406738" x="0.0" y="0.0">script de démarrage</y:NodeLabel>
<y:Shape type="rectangle"/>
<y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/>
@ -368,7 +370,8 @@
<y:Geometry height="30.0" width="129.0" x="329.2164936065674" y="262.00096702575684"/>
<y:Fill color="#FFFFFF" 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.1328125" modelName="custom" textColor="#000000" visible="true" width="94.673828125" x="17.1630859375" y="5.93359375">load app config<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="94.673828125" x="17.1630859375" y="5.93359375">charge la configuration
de l'application<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@ -385,7 +388,8 @@
<y:Geometry height="30.0" width="129.0" x="329.2164936065674" y="322.00096702575684"/>
<y:Fill color="#FFFFFF" 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.1328125" modelName="custom" textColor="#000000" visible="true" width="91.8203125" x="18.58984375" y="5.93359375">run application<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="91.8203125" x="18.58984375" y="5.93359375">créé une instance
d'application<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>

BIN
docs/guide-fr/images/application-lifecycle.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 42 KiB

15
docs/guide-fr/images/application-structure.graphml

@ -20,8 +20,8 @@
<y:Geometry height="35.0" width="100.0" x="872.1807999999999" y="-14.764159999999947"/>
<y:Fill color="#FFCC99" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.265625" modelName="custom" textColor="#000000" visible="true" width="69.712890625" x="15.1435546875" y="1.3671875">application
component<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.265625" modelName="custom" textColor="#000000" visible="true" width="69.712890625" x="15.1435546875" y="1.3671875">composant
d'application<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@ -38,7 +38,8 @@ component<y:LabelModel>
<y:Geometry height="35.0" width="100.0" x="702.4223999999999" y="-91.97375999999994"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="70.28125" x="14.859375" y="8.43359375">entry script<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="70.28125" x="14.859375" y="8.43359375">script de
démarrage<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@ -72,7 +73,7 @@ component<y:LabelModel>
<y:Geometry height="35.0" width="100.0" x="702.4223999999999" y="62.44544000000004"/>
<y:Fill color="#FF9900" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="60.267578125" x="19.8662109375" y="8.433593750000007">controller<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="60.267578125" x="19.8662109375" y="8.433593750000007">contrôleur<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@ -89,7 +90,7 @@ component<y:LabelModel>
<y:Geometry height="35.0" width="100.0" x="872.1807999999999" y="62.44544000000005"/>
<y:Fill color="#FFCC99" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="31.43359375" x="34.283203125" y="8.43359375">filter<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="31.43359375" x="34.283203125" y="8.43359375">filtre<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@ -123,7 +124,7 @@ component<y:LabelModel>
<y:Geometry height="35.0" width="100.0" x="618.4047999999991" y="139.65504000000004"/>
<y:Fill color="#99CC00" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="29.611328125" x="35.1943359375" y="8.43359375">view<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="29.611328125" x="35.1943359375" y="8.43359375">vue<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
@ -140,7 +141,7 @@ component<y:LabelModel>
<y:Geometry height="35.0" width="100.0" x="786.161599999999" y="139.65504000000004"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="40.28125" x="29.859375" y="8.43359375">model<y:LabelModel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="40.28125" x="29.859375" y="8.43359375">modèle<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>

BIN
docs/guide-fr/images/application-structure.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 26 KiB

6
docs/guide-fr/start-gii.md

@ -2,7 +2,7 @@ Générer du code avec Gii
========================
Cette section décrit comment utiliser [Gii](tool-gii.md) pour générer du code qui implémente des fonctionnalités
courrantes de sites Web automatiquement. Utiliser Gii pour auto-générer du code consiste simplement à saisir les
courantes de sites Web automatiquement. Utiliser Gii pour auto-générer du code consiste simplement à saisir les
bonnes informations en suivant les instructions affichées sur les pages Web Gii.
Au long de ce tutoriel, vous apprendrez comment :
@ -47,7 +47,7 @@ ci-dessus. Vous pouvez maintenant accéder à Gii via l’URL suivante :
http://hostname/index.php?r=gii
```
> Note : Si vous accede à Gii depuis une machine autre que localhost, l’accès sera refuse par défaut pour des raisons
> Note : Si vous accède à Gii depuis une machine autre que localhost, l’accès sera refuse par défaut pour des raisons
> de sécurité. Vous pouvez configurer Gii pour ajouter les adresses IP autorisées comme suit,
>
```php
@ -81,7 +81,7 @@ Quand vous utilisez Gii, si vous aviez déjà créé le même fichier et que vou
Quand vous écrasez un fichier existant, cochez la case située à côté de "overwrite" et ensuite, cliquez sur le bouton
"Generate". Si vous créez un nouveau fichier, il suffit de cliquer sur "Generate".
Ensuite, vous verrez une page de confirmation indiquand que le code a été généré avec succès. Si vous aviez un fichier
Ensuite, vous verrez une page de confirmation indiquant que le code a été généré avec succès. Si vous aviez un fichier
existant, vous verrez également un message indiquant qu’il a été écrasé par le code nouvellement généré.

39
docs/guide-fr/start-looking-ahead.md

@ -0,0 +1,39 @@
En savoir plus
=============
Si vous avez entièrement lu la section "Mise en Route", vous avec maintenant créé une application Yii complète. Ce
faisant, vous avez appris comment implémenter des fonctionnalités couramment utilisées, telles que recueillir des
données d'un utilisateur via un formulaire HTML, chercher des données dans une base de données, et afficher des données
de manière paginée. Vous avez également appris à utiliser [Gii](tool-gii.md) pour générer du code automatiquement.
Utiliser Gii pour générer du code rend le gros de votre processus de développement Web aussi simple que de remplir de
simples formulaires.
Cette section va résumer les ressources Yii disponibles pour vous aider à être plus productif dans l'utilisation du
framework.
* Documentation
- Le Guide définitif :
Comme son nom l'indique, le guide définit précisément comment Yii fonctionne et fournit des instructions générales
sur l'utilisation de Yii. C'est le tutoriel pour Yii le plus important, un que vous devriez lire avant d'écrire le
moindre code Yii.
- La Référence de Classes :
Elle spécifie l'usage de toutes les classes fournies par Yii. Elle doit être principalement utilisée lorsque
vous utilisez du code et souhaitez comprendre l'usage d'une classe, méthode ou propriété particulière.
L'utilisation de la référence de classe est plus appropriée quand vous avez une compréhension contextuelle du
framework entier.
- Les Articles Wiki:
Les articles wiki sont écrits par des utilisateurs de Yii en fonction de leurs propres expériences. Ils sont en
général écrits comme des recettes de cuisine, et montrent comment résoudre des problèmes pratiques en utilisant
Yii. Bien que la qualité de ces articles peut être inférieure à celle du Guide Définitif, ils sont utiles du fait
qu'ils couvrent des sujets plus vastes et peuvent fournir des solutions clef-en-main.
- Livres
* [Extensions](http://www.yiiframework.com/extensions/):
Yii est fort d'une librairie de milliers d'extensions créées par les utilisateurs, qui peuvent être facilement
ajoutées à votre application, rendant son développement encore plus facile et plus rapide.
* Communauté
- Forum : <http://www.yiiframework.com/forum/>
- Chat IRC : Les canal #yii sur le réseau freenode (<irc://irc.freenode.net/yii>)
- GitHub : <https://github.com/yiisoft/yii2>
- Facebook : <https://www.facebook.com/groups/yiitalk/>
- Twitter : <https://twitter.com/yiiframework>
- LinkedIn : <https://www.linkedin.com/groups/yii-framework-1483367>

20
docs/guide-fr/start-workflow.md

@ -2,7 +2,7 @@ Fonctionnement des applications
===============================
Après avoir installé Yii, vous obtenez une application Yii fonctionnelle accessible via l'URL `http://hostname/basic/web/index.php` ou `http://hostname/index.php`, en fonction
de votre configuration. Cette section vous initiera aux fonctionalités intégrées à l'application,
de votre configuration. Cette section vous initiera aux fonctionnalités intégrées à l'application,
à la manière dont le code est organisé, et à la gestion des requêtes par l'application.
> Info: Par simplicité, au long de ce tutoriel de démarrage, nous supposerons que `basic/web` est la racine de votre
@ -11,22 +11,22 @@ de votre configuration. Cette section vous initiera aux fonctionalités intégr
Pour vos besoins, merci d'ajuster les URLs dans notre description comme il convient.
Fonctionalité <a name="Functionality"></a>
-------------
Fonctionnalité <a name="Functionality"></a>
--------------
L'application basique installée contient quatre pages :
* La page d'accueil, affichée quand vous accédez à l'URL `http://hostname/index.php`,
* la page "About" (A Propos),
* la page "Contact", qui présente un formulaire de contact permettant aux utilisateurs finaux de vous contacter par email,
* et la page "Login" (Connexion), qui presente un formulaire de connexion qui peut être utilisé pour authentifier des utilisateurs finaux. Essayez de vous connecter
* et la page "Login" (Connexion), qui présente un formulaire de connexion qui peut être utilisé pour authentifier des utilisateurs finaux. Essayez de vous connecter
avec "admin/admin", et vous verrez l'élément "Login" du menu principal être remplacé par "Logout" (Déconnexion).
Ces pages ont en commun une entête et un pied de page. L'entête contient une barre de menu principal qui permet la navigation
entre les différentes pages.
Vous devriez également voir une barre d'outils en bas de votre fenêtre de navigation.
C'est un [outil de déboggage](tool-debugger.md) utile fourni par Yii pour enregistrer et afficher de nombreuses informations de déboggage, telles que des messages de logs, statuts de réponses, les requêtes lancées vers la base de données, et ainsi de suite.
C'est un [outil de débogage](tool-debugger.md) utile fourni par Yii pour enregistrer et afficher de nombreuses informations de débogage, telles que des messages de logs, statuts de réponses, les requêtes lancées vers la base de données, et ainsi de suite.
Structure de l'Application <a name="application-structure"></a>
@ -41,7 +41,7 @@ basic/ chemin de base de l'application
console.php configuration de l'application console
web.php configuration de l'application Web
commands/ contient les classes de commandes console
controllers/ contient les classes de controlleurs
controllers/ contient les classes de contrôleurs
models/ contient les classes de modèles
runtime/ contient les fichiers générés par Yii au cours de l'exécution, tels que les fichiers de logs ou de cache and cache
vendor/ contient les paquets Composer installés, y compris le framework Yii
@ -64,7 +64,7 @@ Le schéma suivant présente la structure statique d'une application.
Chaque application a un script de démarrage `web/index.php` qui est le seul script PHP de l'application accessible depuis le Web.
Le script de démarrage reçoit une requête et créé une instance d'[application](structure-applications.md) pour la traiter.
L'[application](structure-applications.md) résoud la requête avec l'aide de ses [composants](concept-components.md),
L'[application](structure-applications.md) résout la requête avec l'aide de ses [composants](concept-components.md),
et distribue la requête aux éléments MVC. Les [Widgets](structure-widgets.md) sont utilisés dans les [vues](structure-views.md)
pour aider à créer des éléments d'interface complexes et dynamiques.
@ -78,12 +78,12 @@ Le diagramme suivant présente la manière dont une application traite une requ
1. Un utilisateur fait une requête au [script de démarrage](structure-entry-scripts.md) `web/index.php`.
2. Le script de démarrage charge la [configuration](concept-configurations.md) de l'application et créé une instance d'[application](structure-applications.md) pour traiter la requête.
3. L'application resoud la [route](runtime-routing.md) requise avec l'aide du composant d'application [requête](runtime-requests.md).
3. L'application résout la [route](runtime-routing.md) requise avec l'aide du composant d'application [requête](runtime-requests.md).
4. L'application créé une instance de [contrôleur](structure-controllers.md) pour traiter la requête.
5. Le contrôleur créé une instance d'[action](structure-controllers.md) et effectue les filtres pour l'action.
6. Si un filtre échoue, l'action est annuléee.
6. Si un filtre échoue, l'action est annulée.
7. Si tous les filtres sont validés, l'action est exécutée.
8. L'action charge un modèle de donées, potentiellement depuis une base de données.
8. L'action charge un modèle de données, potentiellement depuis une base de données.
9. L'action génère une vue, lui fournissant le modèle de données.
10. Le résultat généré est renvoyé au composant d'application [réponse](runtime-responses.md).
11. Le composant réponse envoie le résultat généré au navigateur de l'utilisateur.

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

@ -0,0 +1,117 @@
Scripts d'entrée
=============
Les scripts d'entrée sont la première chaîne dans le processus de d'amorçage de l'application. Une application (qu'elle
soit une application Web ou une application console) a un unique script de démarrage. Les utilisateurs font des
requêtes au scripts de démarrage qui instancient des instances d'application et leur transmettent les requêtes.
Les scripts d'entrée pour application Web doivent être placés dans des dossiers accessibles par le Web pour que les
utilisateurs puissent y accéder. Ils sont souvent nommés `index.php`, mais peuvent également avoir tout autre nom,
du moment que les serveurs Web peuvent les trouver.
Les scripts d'entrée pour les applications console sont généralement placés dans le [répertoire de base](structure-applications.md)
des applications et sont nommés `yii` (avec le suffixe `.php`). Ils doivent être rendus exécutables afin que les
utilisateurs puissent lancer des applications console grâce à la commande `./yii <route> [arguments] [options]`.
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);
* Inclure le fichier de classe de [[Yii]];
* Charger la configuration de l'application;
* Créer et configurer une instance d'[application](structure-applications.md);
* Appeler [[yii\base\Application::run()]] pour traiter la requête entrante.
## Applications Web <a name="web-applications"></a>
Ce qui suit est le code du script de démarrage du [Modèle Basique d'Application Web](start-installation.md).
```php
<?php
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
// register Composer autoloader
require(__DIR__ . '/../vendor/autoload.php');
// include Yii class file
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
// load application configuration
$config = require(__DIR__ . '/../config/web.php');
// create, configure and run application
(new yii\web\Application($config))->run();
```
## Applications Console <a name="console-applications"></a>
De même, le code qui suit est le code du script de démarrage d'une application console :
```php
#!/usr/bin/env php
<?php
/**
* Yii console bootstrap file.
*
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
defined('YII_DEBUG') or define('YII_DEBUG', true);
// fcgi doesn't have STDIN and STDOUT defined by default
defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));
defined('STDOUT') or define('STDOUT', fopen('php://stdout', 'w'));
// register Composer autoloader
require(__DIR__ . '/vendor/autoload.php');
// include Yii class file
require(__DIR__ . '/vendor/yiisoft/yii2/Yii.php');
// load application configuration
$config = require(__DIR__ . '/config/console.php');
$application = new yii\console\Application($config);
$exitCode = $application->run();
exit($exitCode);
```
## Définir des Constantes <a name="defining-constants"></a>
Les scripts de démarrage sont l'endroit idéal pour définir des constantes globales. Yii supporte les trois constantes suivantes :
* `YII_DEBUG` : spécifie si une application tourne en mode de débogage. Si elle est en mode de débogage, une
application loguera plus d'informations, et révélera des piles d'appels d'erreurs détaillées si des exceptions
sont lancées. C'est pour cette raison que le mode de débogage doit être utilisé principalement pendant la phase
de développement. La valeur par défaut de `YII_DEBUG` est faux.
* `YII_ENV` : spécifie sur quel environnement l'application est en train de tourner. Cela a été décrit plus en détails
dans la section [Configurations](concept-configurations.md#environment-constants). La valeur par défaut de `YII_ENV`
est `'prod'`, ce qui signifie que l'application tourne en environnement de production.
* `YII_ENABLE_ERROR_HANDLER` : spécifie si le gestionnaire d'erreurs fourni par Yii doit être activé. La valeur par
défaut de cette constantes est vrai.
Quand on définit une constant, on utilise souvent le code suivant :
```php
defined('YII_DEBUG') or define('YII_DEBUG', true);
```
qui est l'équivalent du code suivant :
```php
if (!defined('YII_DEBUG')) {
define('YII_DEBUG', true);
}
```
Clairement, le premier est plus succinct et plus aisé à comprendre.
Les définitions de constantes doit être faite au tout début d'un script de démarrage pour qu'elles puissent prendre
effet quand d'autres fichiers PHP sont inclus.

27
docs/guide-fr/structure-overview.md

@ -0,0 +1,27 @@
Vue d'ensemble
========
Les applications Yii sont organisées suivant le patron de conception
[model-view-controller (MVC)](http://wikipedia.org/wiki/Model-view-controller). Les [Modèles](structure-models.md)
représentent les données, la logique métier et les règles; les [vues](structure-views.md) sont les représentations
visuelles des modèles, et les [contrôleurs](structure-controllers.md) prennent une entrée et la convertissent en
commandes pour les [modèles](structure-models.md) et les [vues](structure-views.md).
En plus du MVC, les applications Yii ont les entités suivantes :
* [scripts de démarrage](structure-entry-scripts.md): ce sont des scripts PHP qui sont directement accessibles aux
utilisateurs. Ils sont responsables du démarrage d'un cycle de gestion de requête.
* [applications](structure-applications.md): ce sont des objets globalement accessibles qui gèrent les composants
d'application et les coordonnent pour satisfaire des requêtes.
* [composants d'application](structure-application-components.md): ce sont des objets enregistrés avec des applications et
qui fournissent différents services pour satisfaire des requêtes.
* [modules](structure-modules.md): ce sont des paquets auto-contenus qui contiennent du MVC complet. Une application peut
être organisée en termes de multiples modules.
* [filtres](structure-filters.md): ils représentent du code qui doit être invoqué avant et après la gestion effective
de chaque requête par des contrôleurs.
* [widgets](structure-widgets.md): ce sont des objets qui peuvent être intégrés dans des [vues](structure-views.md). Ils
peuvent contenir de la logique contrôleur et peuvent être réutilisés dans différentes vues.
Le diagramme suivant montre la structure statique d'une application :
![Static Structure of Application](images/application-structure.png)

37
docs/guide-uz/intro-yii.md

@ -0,0 +1,37 @@
Yii nima o`zi?
==============
Yii – bu tez ishlovchi komponentli PHP freymvork bo'lib, zamonaviy web ilovalarni tez yaratish uchun mo'ljallangan. Yii (`Yi` `[ji:]` kabi talaffuz qilinadi) so'zi xitoy tilida "oddiy va evolyutsiyalovchi" degan ma'noni anglatadi. Shuningdek Yii akronim sifatida qaralganda uning yoyilma matni **Yes It Is** tarzida qaralishi ham mumkin!
Yii ko'proq qanday masalalar uchun mos keladi?
----------------------------------------------
Yii – bu universal freymvork va uni barcha turdagi web ilovalar uchun qo'llash mumkin. Uning komponentli strukturasi va keshlashni juda zo'r qo'llab-quvvatlashi evaziga freymvork asosan portallar, forumlar, CMS, magazinlar yoki RESTful ilovalar kabi katta proyektlar uchun qo'l keladi.
Yii ni boshqa freymvorklar bilan solishtirish
---------------------------------------------
- Boshqa ko'pgina PHP freymvorklar singari Yii ham kodni tashkillashtirish uchun MVC (Model-View-Controller) modelidan foydalanadi.
- Yii faqat loyihalashtirishning ma'lum bir qolipiga ergashib dizaynni murakkablashtirmasdan sodda va elegantli kod yozish falsafasiga tayanadi.
- Yii full-stack freymvork hisoblanadi. Shuningdek o'z ichiga tekshirilgan va o'zini yaxshi ko'rsatgan relatsion va NoSQL ma'lumotlar ombori uchun yaratilgan ActiveRecord, REST API ni qo'llab quvvatlash, ko'p qatlamli keshlash kabi imkoniyatlarni oladi.
- Yii juda yaxhsi kengayishi mumkin. Siz asosiy kodni ixtiyoriy qismini almashtirishingiz yoki sozlashingiz mumkin. Kengaytirish arxitekturasiga bo'ysunib kodni boshqalar bilan ulashish yoki jamoatning kodidan foydalanish mumkin.
- Yii ning asosiy maqsadlaridan biri - ishlash tezligi.
Yii — bir odamning loyihasi emas. U unga yordam berayotgan ishlab chiquvchilar [katta jamoa][]si tomonidan qo'llab quvvatlanadi va rivojlantiriladi. Freymvork ishlab chiquvchilari web ishlab chiqish va boshqa ilovalarni maromini kuzatishadi. Ko'proq mos keluvchi imkoniyatlar va eng yaxshi sinalgan amaliyotlar freymvork sodda va elegantli interfeysi tarzida qo'llaniladi.
[katta jamoa]: http://www.yiiframework.com/about/
Yii talqinlari
--------------
Ayni vaqtda Yii ning ikkita yo'nalishi mavjud: 1.1 va 2.0. 1.1 yo'nalishi avvalgi avlod hisoblanadi va qo'llab quvvatlash holatida. 2.0 talqini - bu Composer, PSR, nomlar sohasi, treytlar(traits) va boshqa shular kabi ko'pgina oxirgi texnologiyalarni va *qaydnoma*larni qo'llovchi Yii ning to'liq boshqatdan yozilgan talqini. Mana shu talqinda navbatdagi yillarda uni yanada kuchaytirish nazarda tutilgan. Ushbu qo'llanma aynan 2.0 talqin haqida.
DT va bilimlarga talablar
-------------------------
Yii 2.0 PHP 5.4.0 va undan yuqorisini talab qiladi. Boshqa imkoniyatlar uchun talablarni bilish uchun har bir alohida yo'lga qo'yilgan freymvork bilan birga mos o'rnatilgan talablar tekshiruv skriptini ishga tushirishingiz mumkin.
Freymvork to'liq obektga mo'ljallangan dasturlashga (OMD) asoslanganligi bois Yii da ishlash uchun OMD ni umumiy tushunish talab etiladi. Shuningdek, PHP ning zamonaviy imkoniyatlari bo'lmish [nomlar soxasi](http://www.php.net/manual/ru/language.namespaces.php) va [treytlar](http://www.php.net/manual/ru/language.oop5.traits.php) ni o'rganish talab etiladi.

4
docs/guide/README.md

@ -90,14 +90,14 @@ Getting Data from Users
* [Creating Forms](input-forms.md)
* [Validating Input](input-validation.md)
* **TBD** [Uploading Files](input-file-upload.md)
* [Uploading Files](input-file-upload.md)
* **TBD** [Getting Data for Multiple Models](input-multiple-models.md)
Displaying Data
---------------
* **TBD** [Data Formatting](output-formatter.md)
* [Data Formatting](output-formatter.md)
* **TBD** [Pagination](output-pagination.md)
* **TBD** [Sorting](output-sorting.md)
* [Data Providers](output-data-providers.md)

3
docs/guide/caching-data.md

@ -29,7 +29,8 @@ if ($data === false) {
Data caching relies on the so-called *cache components* which represent various cache storage,
such as memory, files, databases.
Cache components are usually registered as application components so that they can be globally configurable
Cache components are usually registered as [application components](structure-application-components.md) so
that they can be globally configurable
and accessible. The following code shows how to configure the `cache` application component to use
[memcached](http://memcached.org/) with two cache servers:

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

@ -97,7 +97,7 @@ Connecting to Database
----------------------
Active Record uses a [[yii\db\Connection|DB connection]] to exchange data with database. By default,
it uses the `db` application component as the connection. As explained in [Database basics](db-dao.md),
it uses the `db` [application component](structure-application-components.md) as the connection. As explained in [Database basics](db-dao.md),
you may configure the `db` component in the application configuration file like follows,
```php
@ -465,14 +465,14 @@ an `ActiveQuery` instance, while `$customer->orders` returns an array of `Order`
the query results in nothing).
Relations with Pivot Table
--------------------------
Relations with Junction Table
-----------------------------
Sometimes, two tables are related together via an intermediary table called [pivot table][]. To declare such relations,
Sometimes, two tables are related together via an intermediary table called [junction table][]. To declare such relations,
we can customize the [[yii\db\ActiveQuery]] object by calling its [[yii\db\ActiveQuery::via()|via()]] or
[[yii\db\ActiveQuery::viaTable()|viaTable()]] method.
For example, if table `order` and table `item` are related via pivot table `order_item`,
For example, if table `order` and table `item` are related via junction table `order_item`,
we can declare the `items` relation in the `Order` class like the following:
```php
@ -488,7 +488,7 @@ class Order extends \yii\db\ActiveRecord
The [[yii\db\ActiveQuery::via()|via()]] method is similar to [[yii\db\ActiveQuery::viaTable()|viaTable()]] except that
the first parameter of [[yii\db\ActiveQuery::via()|via()]] takes a relation name declared in the ActiveRecord class
instead of the pivot table name. For example, the above `items` relation can be equivalently declared as follows:
instead of the junction table name. For example, the above `items` relation can be equivalently declared as follows:
```php
class Order extends \yii\db\ActiveRecord
@ -506,7 +506,7 @@ class Order extends \yii\db\ActiveRecord
}
```
[pivot table]: http://en.wikipedia.org/wiki/Pivot_table "Pivot table on Wikipedia"
[junction table]: https://en.wikipedia.org/wiki/Junction_table "Junction table on Wikipedia"
Lazy and Eager Loading
@ -561,7 +561,7 @@ As you can see, only two SQL queries are needed for the same task!
> Info: In general, if you are eager loading `N` relations among which `M` relations are defined with `via()` or `viaTable()`,
> a total number of `1+M+N` SQL queries will be performed: one query to bring back the rows for the primary table, one for
> each of the `M` pivot tables corresponding to the `via()` or `viaTable()` calls, and one for each of the `N` related tables.
> each of the `M` junction tables corresponding to the `via()` or `viaTable()` calls, and one for each of the `N` related tables.
> Note: When you are customizing `select()` with eager loading, make sure you include the columns that link
> the related models. Otherwise, the related models will not be loaded. For example,

2
docs/guide/db-dao.md

@ -76,7 +76,7 @@ $primaryConnection = \Yii::$app->db;
$secondaryConnection = \Yii::$app->secondDb;
```
If you don't want to define the connection as an application component you can instantiate it directly:
If you don't want to define the connection as an [application component](structure-application-components.md) you can instantiate it directly:
```php
$connection = new \yii\db\Connection([

6
docs/guide/db-migrations.md

@ -178,7 +178,7 @@ After applying a migration, the migration tool will keep a record in a database
table named `migration`. This allows the tool to identify which migrations
have been applied and which are not. If the `migration` table does not exist,
the tool will automatically create it in the database specified by the `db`
application component.
[application component](structure-application-components.md).
Sometimes, we may only want to apply one or a few new migrations. We can use the
following command:
@ -293,7 +293,7 @@ line:
migration history information. It defaults to `migration`. The table
structure is `version varchar(255) primary key, apply_time integer`.
* `db`: string, specifies the ID of the database application component.
* `db`: string, specifies the ID of the database [application component](structure-application-components.md).
Defaults to 'db'.
* `templateFile`: string, specifies the path of the file to be served as the code
@ -341,7 +341,7 @@ can be also configured this way.
### Migrating with Multiple Databases
By default, migrations will be applied to the database specified by the `db` application component.
By default, migrations will be applied to the database specified by the `db` [application component](structure-application-components.md).
You may change it by specifying the `--db` option, for example,
```

2
docs/guide/input-forms.md

@ -168,7 +168,7 @@ class SettingsController extends Controller
```
In the code above we're using `indexBy` when retrieving models from database to make array indexed by model ids. These
will be later used to identify form fields. `loadMultiple` fills multiple modelds with the form data coming from POST
will be later used to identify form fields. `loadMultiple` fills multiple models with the form data coming from POST
and `validateMultiple` validates all models at once. In order to skip validation when saving we're passing `false` as
a parameter to `save`.

2
docs/guide/input-validation.md

@ -391,7 +391,7 @@ class CountryValidator extends Validator
public function validateAttribute($model, $attribute)
{
if (!in_array($model->$attribute, ['USA', 'Web'])) {
$this->addError($attribute, 'The country must be either "USA" or "Web".');
$this->addError($model, $attribute, 'The country must be either "USA" or "Web".');
}
}
}

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

@ -135,13 +135,13 @@ You may specify various container HTML options passing arrays to:
- `footerOptions`
- `filterOptions`
#### Data column
#### Data column <a name="data-column"></a>
Data column is for displaying and sorting data. It is default column type so specifying class could be omitted when
using it.
The main setting of the data column is its format. It could be specified via `format` attribute. Its values are
corresponding to methods in `format` application component that is [[\yii\i18n\Formatter|Formatter]] by default:
corresponding to methods in `formatter` [application component](structure-application-components.md) that is [[\yii\i18n\Formatter|Formatter]] by default:
```php
<?= GridView::widget([

146
docs/guide/output-formatter.md

@ -2,7 +2,7 @@ Data Formatter
==============
For formatting of outputs Yii provides a formatter class to make data more readable for users.
[[yii\i18n\Formatter]] is a helper class that is registered as an [application component](concept-components.md) named `formatter` by default.
[[yii\i18n\Formatter]] is a helper class that is registered as an [application component](structure-application-components.md) named `formatter` by default.
It provides a set of methods for data formatting purpose such as date/time values, numbers and other commonly used formats in a localized way.
The formatter can be used in two different ways.
@ -31,7 +31,7 @@ The formatter can be used in two different ways.
All output of the formatter is localized when the [PHP intl extension](http://php.net/manual/en/book.intl.php) is installed.
You can configure the [[yii\i18n\Formatter::locale|locale]] property of the formatter for this. If not configured, the
application [[yii\base\Application::language|language]] is used as the locale. See the [Section on internationaization](tutorial-i18n.md) for more details.
application [[yii\base\Application::language|language]] is used as the locale. See the [section on internationalization](tutorial-i18n.md) for more details.
The Formatter will then choose the correct format for dates and numbers according to the locale including names of month and
week days translated to the current language. Date formats are also affected by the [[yii\i18n\Formatter::timeZone|timeZone]]
which will also be taken [[yii\base\Application::timeZone|from the application]] if not configured explicitly.
@ -53,13 +53,13 @@ echo Yii::$app->formatter->asDate('2014-01-01'); // output: 1 января 2014
> is the same. See also: [Setting up your PHP environment for internationalization](tutorial-i18n.md#setup-environment).
Configuring the format
----------------------
Configuring the formatter <a name="configuring-format"></a>
-------------------------
The default format of the Formatter class can be adjusted using the properties of the formatter class.
The default formats used by the formatter methods can be adjusted using the properties of the [[yii\i18n\Formatter|formatter class]].
You can adjust these values application wide by configuring the `formatter` component in your [application config](concept-configurations.md#application-configurations).
An example configuration is shown in the following.
For more details about the available properties check out the [[yii\i18n\Formatter|API documentation of the Formatter class]].
For more details about the available properties check out the [[yii\i18n\Formatter|API documentation of the Formatter class]] and the following subsections.
```php
'components' => [
@ -72,63 +72,119 @@ For more details about the available properties check out the [[yii\i18n\Formatt
],
```
Formatting Dates
----------------
Formatting Date and Time values <a name="date-and-time"></a>
-------------------------------
> Note: This section is under development.
The formatter class provides different methods for formatting date and time values. These are:
TDB
- [[yii\i18n\Formatter::asDate()|date]] - the value is formatted as a date e.g. `January, 01 2014`.
- [[yii\i18n\Formatter::asTime()|time]] - the value is formatted as a time e.g. `14:23`.
- [[yii\i18n\Formatter::asDatetime()|datetime]] - the value is formatted as date and time e.g. `January, 01 2014 14:23`.
- [[yii\i18n\Formatter::asTimestamp()|timestamp]] - the value is formatted as a [unix timestamp](http://en.wikipedia.org/wiki/Unix_time) e.g. `1412609982`.
- [[yii\i18n\Formatter::asRelativeTime()|relativeTime]] - the value is formatted as the time interval between a date
and now in human readable form e.g. `1 hour ago`.
See http://site.icu-project.org/ for the format.
The date and time format for the [[yii\i18n\Formatter::asDate()|date]], [[yii\i18n\Formatter::asTime()|time]], and
[[yii\i18n\Formatter::asDatetime()|datetime]] method can be specified globally by configuring the formatters
properties [[yii\i18n\Formatter::$dateFormat|$dateFormat]], [[yii\i18n\Formatter::$timeFormat|$timeFormat]], and
[[yii\i18n\Formatter::$datetimeFormat|$datetimeFormat]].
- [[\yii\i18n\Formatter::asDate()|date]] - the value is formatted as date.
- [[\yii\i18n\Formatter::asTime()|time]] - the value is formatted as time.
- [[\yii\i18n\Formatter::asDatetime()|datetime]] - the value is formatted as datetime.
- [[\yii\i18n\Formatter::asTimestamp()|timestamp]] - the value is formatted as a unix timestamp.
- [[\yii\i18n\Formatter::asRelativeTime()|relativeTime]] - the value is formatted as the time interval between a date
and now in human readable form.
By default the formatter uses a shortcut format that is interpreted differently according to the currently active locale
so that dates and times are formatted in a way that is common for the users country and language.
There are four different shortcut formats available:
- `short` in `en_GB` locale will print for example `06/10/2014` for date and `15:58` for time, while
- `medium` will print `6 Oct 2014` and `15:58:42`,
- `long` will print `6 October 2014` and `15:58:42 GMT`,
- and `full` will print `Monday, 6 October 2014` and `15:58:42 GMT`.
The input value for date and time formatting is assumed to be in UTC unless a timezone is explicitly given.
Additionally you can specify custom formats using the syntax defined by the
[ICU Project](http://site.icu-project.org/) which is described in the ICU manual under the following URL:
<http://userguide.icu-project.org/formatparse/datetime>. Alternatively you can use the syntax that can be recognized by the
PHP [date()](http://php.net/manual/de/function.date.php)-function using a string that is prefixed with `php:`.
Formatting Numbers
------------------
```php
// ICU format
echo Yii::$app->formatter->asDate('now', 'yyyy-MM-dd'); // 2014-10-06
// PHP date()-format
echo Yii::$app->formatter->asDate('now', 'php:Y-m-d'); // 2014-10-06
```
> Note: This section is under development.
### Time zones <a name="time-zones"></a>
TDB
When formatting date and time values, Yii will convert them to the [[yii\i18n\Formatter::timeZone|configured time zone]].
Therefor the input value is assumed to be in UTC unless a time zone is explicitly given. For this reason
it is recommended to store all date and time values in UTC preferably as a UNIX timestamp, which is always UTC by definition.
If the input value is in a time zone different from UTC, the time zone has to be stated explicitly like in the following example:
See http://site.icu-project.org/ for the format.
```php
// assuming Yii::$app->timeZone = 'Europe/Berlin';
echo Yii::$app->formatter->asTime(1412599260); // 14:41:00
echo Yii::$app->formatter->asTime('2014-10-06 12:41:00'); // 14:41:00
echo Yii::$app->formatter->asTime('2014-10-06 14:41:00 CEST'); // 14:41:00
```
- [[\yii\i18n\Formatter::asInteger()|integer]] - the value is formatted as an integer.
- [[\yii\i18n\Formatter::asDecimal()|decimal]] - the value is formatted as a number with decimal and thousand separators.
- [[\yii\i18n\Formatter::asPercent()|percent]] - the value is formatted as a percent number.
- [[\yii\i18n\Formatter::asScientific()|scientific]] - the value is formatted as a number in scientific format.
- [[\yii\i18n\Formatter::asCurrency()|currency]] - the value is formatted as a currency value.
- [[\yii\i18n\Formatter::asSize()|size]] - the value that is a number of bytes is formatted as a human readable size.
- [[\yii\i18n\Formatter::asShortSize()|shortSize]] - the value that is a number of bytes is formatted as a human readable size.
> Note: As time zones are subject to rules made by the governments around the world and may change frequently, it is
> likely that you do not have the latest information in the time zone database installed on your system.
> You may refer to the [ICU manual](http://userguide.icu-project.org/datetime/timezone#TOC-Updating-the-Time-Zone-Data)
> for details on updating the time zone database.
> See also: [Setting up your PHP environment for internationalization](tutorial-i18n.md#setup-environment).
Other formatters
----------------
Formatting Numbers <a name="numbers"></a>
------------------
> Note: This section is under development.
For formatting numeric values the formatter class provides the following methods:
TDB
- [[yii\i18n\Formatter::asInteger()|integer]] - the value is formatted as an integer e.g. `42`.
- [[yii\i18n\Formatter::asDecimal()|decimal]] - the value is formatted as a decimal number considering decimal and thousand separators e.g. `42.123`.
- [[yii\i18n\Formatter::asPercent()|percent]] - the value is formatted as a percent number e.g. `42%`.
- [[yii\i18n\Formatter::asScientific()|scientific]] - the value is formatted as a number in scientific format e.g. `4.2E4`.
- [[yii\i18n\Formatter::asCurrency()|currency]] - the value is formatted as a currency value e.g. `£420.00`.
- [[yii\i18n\Formatter::asSize()|size]] - the value that is a number of bytes is formatted as a human readable size e.g. `410 kibibytes`.
- [[yii\i18n\Formatter::asShortSize()|shortSize]] - is the short version of [[yii\i18n\Formatter::asSize()|size]], e.g. `410 KiB`.
The format for number formatting can be adjusted using the [[yii\i18n\Formatter::decimalSeparator|decimalSeparator]] and
[[yii\i18n\Formatter::thousandSeparator|thousandSeparator]] which are set by default according to the locale.
For more advanced configuration, [[yii\i18n\Formatter::numberFormatterOptions]] and [[yii\i18n\Formatter::numberFormatterTextOptions]]
can be used to configure the interally used [Numberformatter class](http://php.net/manual/en/class.numberformatter.php)
For example to adjust the maximum and minimum value of fraction digits you can configure this property like the following:
```php
[
NumberFormatter::MIN_FRACTION_DIGITS => 0,
NumberFormatter::MAX_FRACTION_DIGITS => 2,
]
```
Other formatters <a name="other"></a>
----------------
Here's the bundled formatters list:
Additional to date, time and number formatting, Yii provides a set of other useful formatters for different purposes:
- [[\yii\i18n\Formatter::asRaw()|raw]] - the value is outputted as is.
- [[\yii\i18n\Formatter::asText()|text]] - the value is HTML-encoded. This format is used by default.
- [[\yii\i18n\Formatter::asNtext()|ntext]] - the value is formatted as an HTML-encoded plain text with newlines converted
- [[yii\i18n\Formatter::asRaw()|raw]] - the value is outputted as is, this is a pseudo-formatter that has no effect except that
`null` values will be formatted using [[nullDisplay]].
- [[yii\i18n\Formatter::asText()|text]] - the value is HTML-encoded.
This is the default format used by the [GridView DataColumn](output-data-widgets.md#data-column).
- [[yii\i18n\Formatter::asNtext()|ntext]] - the value is formatted as an HTML-encoded plain text with newlines converted
into line breaks.
- [[\yii\i18n\Formatter::asParagraphs()|paragraphs]] - the value is formatted as HTML-encoded text paragraphs wrapped
- [[yii\i18n\Formatter::asParagraphs()|paragraphs]] - the value is formatted as HTML-encoded text paragraphs wrapped
into `<p>` tags.
- [[\yii\i18n\Formatter::asHtml()|html]] - the value is purified using [[HtmlPurifier]] to avoid XSS attacks. You can
- [[yii\i18n\Formatter::asHtml()|html]] - the value is purified using [[HtmlPurifier]] to avoid XSS attacks. You can
pass additional options such as `['html', ['Attr.AllowedFrameTargets' => ['_blank']]]`.
- [[\yii\i18n\Formatter::asEmail()|email]] - the value is formatted as a mailto link.
- [[\yii\i18n\Formatter::asImage()|image]] - the value is formatted as an image tag.
- [[\yii\i18n\Formatter::asUrl()|url]] - the value is formatted as a hyperlink.
- [[\yii\i18n\Formatter::asBoolean()|boolean]] - the value is formatted as a boolean. You can set what's rendered for
true and false values by calling `Yii::$app->formatter->booleanFormat = ['No', 'Yes'];` before outputting GridView.
- [[yii\i18n\Formatter::asEmail()|email]] - the value is formatted as a `mailto`-link.
- [[yii\i18n\Formatter::asImage()|image]] - the value is formatted as an image tag.
- [[yii\i18n\Formatter::asUrl()|url]] - the value is formatted as a hyperlink.
- [[yii\i18n\Formatter::asBoolean()|boolean]] - the value is formatted as a boolean. By default `true` is rendered
as `Yes` and `false` as `No`, translated to the application language. You adjust this by configuring
the [[yii\i18n\Formatter::booleanFormat]]-property.
`null`-values <a name="null-values"></a>
-------------
For values that are `null` in PHP, the formatter class will print a placeholder instead of and empty string which
defaults to `(not set)` translated to the current application language. You can configure the
[[yii\i18n\Formatter::nullDisplay|nullDisplay]]-property to set a custom placeholder.
If you want no special handling for `null` values, you can set [[yii\i18n\Formatter::nullDisplay|nullDisplay]] to `null`.

2
docs/guide/runtime-handling-errors.md

@ -16,7 +16,7 @@ The [[yii\web\ErrorHandler|error handler]] is enabled by default. You may disabl
## Using Error Handler <a name="using-error-handler"></a>
The [[yii\web\ErrorHandler|error handler]] is registered as an application component named `errorHandler`.
The [[yii\web\ErrorHandler|error handler]] is registered as an [application component](structure-application-components.md) named `errorHandler`.
You may configure it in the application configuration like the following:
```php

2
docs/guide/runtime-logging.md

@ -63,7 +63,7 @@ severity levels and categories and then exports them to some medium. For example
exports the filtered log messages to a database table, while a [[yii\log\EmailTarget|email target]] exports
the log messages to specified email addresses.
You can register multiple log targets in an application by configuring them through the `log` application component
You can register multiple log targets in an application by configuring them through the `log` [application component](structure-application-components.md)
in the application configuration, like the following:
```php

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

@ -174,7 +174,10 @@ where 'BLOB' refers to the BLOB-type of your preferred DBMS. Below are the BLOB
- PostgreSQL: BYTEA
- MSSQL: BLOB
> Note: According to the php.ini setting of `session.hash_function`, you may need to adjust
the length of the `id` column. For example, if `session.hash_function=sha256`, you should use
length 64 instead of 40.
### Flash Data <a name="flash-data"></a>

6
docs/guide/security-authorization.md

@ -154,7 +154,7 @@ the [Wiki article](http://en.wikipedia.org/wiki/Role-based_access_control) for d
with other more traditional access control schemes.
Yii implements a General Hierarchical RBAC, following the [NIST RBAC model](http://csrc.nist.gov/rbac/sandhu-ferraiolo-kuhn-00.pdf).
It provides the RBAC functionality through the [[yii\rbac\ManagerInterface|authManager]] application component.
It provides the RBAC functionality through the [[yii\rbac\ManagerInterface|authManager]] [application component](structure-application-components.md).
Using RBAC involves two parts of work. The first part is to build up the RBAC authorization data, and the second
part is to use the authorization data to perform access check in places where it is needed.
@ -219,8 +219,8 @@ Building authorization data is all about the following tasks:
Depending on authorization flexibility requirements the tasks above could be done in different ways.
If your permissions hierarchy doesn't change at all and you have a fixed number of users you can create a console
command that will initialize authorization data once via APIs offered by `authManager`:
If your permissions hierarchy doesn't change at all and you have a fixed number of users you can create a
[console command](tutorial-console.md#create-command) command that will initialize authorization data once via APIs offered by `authManager`:
```php
<?php

2
docs/guide/start-databases.md

@ -18,7 +18,7 @@ In particular, you should know how to create a database, and how to execute SQL
Preparing the Database <a name="preparing-database"></a>
--------------------
----------------------
To begin, create a database named `yii2basic`, from which you will fetch data in your application.
You may create an SQLite, MySQL, PostgreSQL, MSSQL or Oracle database, as Yii has built-in support for many database applications. For simplicity, MySQL will be assumed in the following description.

0
docs/guide/structure-application-components.md

2
docs/guide/structure-applications.md

@ -195,7 +195,7 @@ The rest of the array elements (key-value pairs) specify the parameters to be bo
#### [[yii\base\Application::components|components]] <a name="components"></a>
This is the single most important property. It allows you to register a list of named components
called [application components](#structure-application-components.md) that you can use in other places. For example,
called [application components](structure-application-components.md) that you can use in other places. For example,
```php
[

2
docs/guide/structure-views.md

@ -4,7 +4,7 @@ Views
Views are part of the [MVC](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) architecture.
They are code responsible for presenting data to end users. In a Web application, views are usually created
in terms of *view templates* which are PHP script files containing mainly HTML code and presentational PHP code.
They are managed by the [[yii\web\View|view]] application component which provides commonly used methods
They are managed by the [[yii\web\View|view]] [application component](structure-application-components.md) which provides commonly used methods
to facilitate view composition and rendering. For simplicity, we often call view templates or view template files
as views.

10
docs/guide/tutorial-console.md

@ -6,7 +6,7 @@ Console applications
Yii has full featured support for console applications, whose structure is very similar to a Yii web application. A console application
consists of one or more [[yii\console\Controller]] classes, which are often referred to as "commands" in the console environment. Each controller can also have one or more actions, just like web controllers.
Usage
Usage <a name="usage"></a>
-----
You execute a console controller action using the following syntax:
@ -25,7 +25,7 @@ yii migrate/create --migrationTable=my_migration
In the above `yii` is the console application entry script described below.
Entry script
Entry script <a name="entry-script"></a>
------------
The console application entry script is equivalent to the `index.php` bootstrap file used for the web application. The console entry script is typically called `yii`, and located in your application's root directory. The contents of the console application entry script contains
@ -59,11 +59,11 @@ This script will be created as part of your application; you're free to edit it
not want to see a stack trace on error, and/or if you want to improve the overall performance. In both basic and advanced application
templates, the console application entry script has debugging enabled to provide a more developer-friendly environment.
Configuration
Configuration <a name="configuration"></a>
-------------
As can be seen in the code above, the console application uses its own configuration file, named `console.php`. In this file
you should configure various application components and properties for the console application in particular.
you should configure various [application components](structure-application-components.md) and properties for the console application in particular.
If your web application and the console application share a lot of configuration parameters and values, you may consider moving the common
parts into a separate file, and including this file in both of the application configurations (web and console). You can see an example of this in the "advanced" application template.
@ -81,7 +81,7 @@ yii <route> --appconfig=path/to/config.php ...
> command.
Creating your own console commands
Creating your own console commands <a name="create-command"></a>
----------------------------------
### Console Controller and Action

9
docs/guide/tutorial-i18n.md

@ -71,7 +71,7 @@ echo \Yii::t('app', 'This is a string to translate!');
```
Yii tries to load an appropriate translation according to the current [[yii\base\Application::$language|application language]]
from one of the message sources defined in the `i18n` [application component](concept-components.md).
from one of the message sources defined in the `i18n` [application component](structure-application-components.md).
A message source is a set of files or a database that provides translation messages.
The following configuration example defines a messages source that takes the messages from PHP files:
@ -408,7 +408,7 @@ Instead of using `fileMap` you can simply use convention of category mapping to
Yii comes with default translation messages for validation errors and some other strings. These messages are all
in the category `yii`. Sometimes you want to correct default framework message translation for your application.
In order to do so configure the `i18n` [application component](concept-components.md) like the following:
In order to do so configure the `i18n` [application component](structure-application-components.md) like the following:
```php
'i18n' => [
@ -523,3 +523,8 @@ We recommend an ICU version greater or equal to version ICU 49 to be able to use
One major feature that is missing in Versions below 49 is the `#` placeholder in plural rules.
See <http://site.icu-project.org/download> for a list of available ICU versions. Note that the version numbering has changed after the
4.8 release so that the first digits are now merged: the sequence is ICU 4.8, ICU 49, ICU 50.
Additionally the information in the time zone database shipped with the ICU library may be outdated. Please refer
to the [ICU manual](http://userguide.icu-project.org/datetime/timezone#TOC-Updating-the-Time-Zone-Data) for details
on updating the time zone database. While for output formatting the ICU timezone database is used, the time zone database
used by PHP may be relevant too. You can update it by installing the latest version of the [pecl package `timezonedb`](http://pecl.php.net/package/timezonedb).

2
docs/guide/tutorial-performance-tuning.md

@ -78,7 +78,7 @@ return [
];
```
Note that `cache` application component should be configured.
Note that the `cache` [application component](structure-application-components.md) should be configured.
### Combining and Minimizing Assets

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

@ -106,7 +106,7 @@ which is not needed in this case and already handled by the existing application
Like in a Yii application, you should configure the application instance based on the environment running
the third-party system. For example, to use the [Active Record](db-active-record.md) feature, you need to configure
the `db` application component with the DB connection setting used by the third-party system.
the `db` [application component](structure-application-components.md) with the DB connection setting used by the third-party system.
Now you can use most features provided by Yii. For example, you can create Active Record classes and use them
to work with databases.

2
docs/guide/widget-bootstrap.md

@ -57,7 +57,7 @@ Using the .less files of Bootstrap directly
If you want to include the [Bootstrap css directly in your less files](http://getbootstrap.com/getting-started/#customizing)
you may need to disable the original bootstrap css files to be loaded.
You can do this by setting the css property of the [[yii\bootstrap\BootstrapAsset|BootstrapAsset]] to be empty.
For this you need to configure the `assetManager` application component as follows:
For this you need to configure the `assetManager` [application component](structure-application-components.md) as follows:
```php
'assetManager' => [

46
docs/internals-es/translation-workflow.md

@ -0,0 +1,46 @@
Flujo de Trabajo de Traducción
==============================
Yii se traduce en muchos idiomas con el fin de ser útil para desarrolladores de aplicaciones e internacionales.
Dos áreas principales donde la contribución es muy bienvenida son la documentación y los mensajes del framework.
Mensajes del Framework
----------------------
El framework tiene dos tipos de mensajes: excepciones que están destinadas al desarrollador y nunca se traducen, y mensajes
que en realidad son visibles para el usuario final, tales como errores de validación.
El orden para comenzar con la traducción de mensajes:
1. Comprobar que en `framework/messages/config.php` su idioma aparece en `languages`. Si no, añade tu idioma allí (recuerda que debes mantener la lista en orden alfabético).
El formato de código de idioma debe seguir el [Código de Idiomas IETF](http://es.wikipedia.org/wiki/C%C3%B3digo_de_idioma_IETF), por ejemplo, `es`.
2. Ir al directorio `framework` y ejecutar el comando `yii message/extract messages/config.php`.
3. Traducir los mensajes en `framework/messages/tu-idioma/yii.php`. Asegúrate de guardar el archivo con codificación UTF-8.
4. [Crear un pull request](https://github.com/yiisoft/yii2/blob/master/docs/internals-es/git-workflow.md).
Con el fin de mantener la traducción al día puedes ejecutar `yii message/extract messages/config.php` nuevamente.
Se volverán a extraer automáticamente los mensajes de mantenimiento intactos sin los cambios.
En el archivo de traducción de cada elemento del `array` representa un mensaje (clave) y su la traducción (valor). Si el valor está vacío, el mensaje se considera como no traducido.
Los mensajes que ya no necesiten traducción tendrán sus traducciones encerrado entre un par de marcas '@@'. El texto de los mensajes se puede utilizar con el formato de formas plurales.
Chequea la [sección i18n de la guía](../guide-es/tutorial-i18n.md) para más detalles.
Documentación
-------------
Coloca las traducciones de la documentación bajo `docs/<original>-<language>` donde `<original>` es el nombre de la documentación original como `guide` o `internals`
y `<language>` es el código del idioma al que se está traduciendo. Para la traducción al español de la guía, es `docs/guide-es`.
Después de que el trabajo inicial está hecho, puedes obtener los cambios desde la última traducción del archivo usando un comando especial del directorio `build`:
```
php build translation "../docs/guide" "../docs/guide-es" "Reporte de traducción guia en Español" > report_guide_es.html
```
Si recibes un error de composer, ejecuta `composer install` en el directorio raíz.
Convenios para la traducción
----------------------------
Las palabras en inglés que son propias del framework o de PHP, o traducibles pero que están muy ligadas a conceptos extendidos o nombres de clases, se pueden dejar en idioma original.
Ejemplos: `namespace`, `assets`, `helper`, `widget`, etc.

2
docs/internals-pt-BR/translations.md → docs/internals-pt-BR/translation-workflow.md

@ -16,7 +16,7 @@ Os passos para iniciar a tradução de mensagens são:
Para manter as traduções sempre atualizadas, certifique-se que seu fork do Yii esteja com a última versão. Em seguida, basta executar o comando `yii message/extract messages/config.php` novamente e o mesmo irá adicionar automaticamente as novas mensagens a serem traduzidas.
No arquivo de tradução cada elemento do array representa a tradução de uma mensagem. Sendo que a "chave" representa o texto a ser traduzido e o "valor" a sua tradução. Se o "valor" estiver vazio, a mensagem é considerada como não traduzida. As mensagens que não precisam de tradução terão seus valores cercadas por um par de '@@'. Atentar para algumas mensagens que estão no formato de plural, para isso verifique a [seção i18n do guia](../guide/i18n.md) para mais detalhes.
No arquivo de tradução cada elemento do array representa a tradução de uma mensagem. Sendo que a "chave" representa o texto a ser traduzido e o "valor" a sua tradução. Se o "valor" estiver vazio, a mensagem é considerada como não traduzida. As mensagens que não precisam de tradução terão seus valores cercadas por um par de '@@'. Atentar para algumas mensagens que estão no formato de plural, para isso verifique a [seção i18n do guia](../guide-pt-BR/tutorial-i18n.md) para mais detalhes.
Documentação

2
docs/internals-ru/translation-workflow.md

@ -18,7 +18,7 @@ Yii переводится на множество языков, в том чи
В файле перевода находится массив. Его ключи — исходные строки, значения — перевод. Если значение пусто, сообщение
считается не переведённым. Переводы сообщений, которые больше не встречаются в коде, обрамлены `@@`. Для некоторых сообщений
необходимо использовать [специальный формат для поддержки употребления с числительными](../guide/i18n.md).
необходимо использовать [специальный формат для поддержки употребления с числительными](../guide-ru/tutorial-i18n.md).
Документация
------------

2
docs/internals-uz/translations.md → docs/internals-uz/translation-workflow.md

@ -14,7 +14,7 @@ Tarjimani yangilash uchun:
3. Habarlarni `framework/messages/uz/yii.php` ga ko`chiramiz. Muhimi fayllar UTF-8 kodlashda bo'lishi kerak.
4. `uz` dagi tarjimalar bilan [pull request qilamiz](https://github.com/yiisoft/yii2/blob/master/docs/internals/git-workflow.md), qolgan tillarga tegmaymiz.
Tarjima fayllarda massiv joylashgan. Uning kalitlari - boshlang'ich kodlar, qiymatlari - tarjima. Agar qiymat bo'sh bo'lsa habar tarjima qilinmagan hisoblanadi. Kodda boshqa uchramaydigan habarlar tarjimasi '@@' ga o'ralgan. Ayrim habarlar uchun [sonlar bilan qo'llanilishini qo'llab-quvvatlash uchun maxsus format](../guide/i18n.md) ni ishlatish zarur.
Tarjima fayllarda massiv joylashgan. Uning kalitlari - boshlang'ich kodlar, qiymatlari - tarjima. Agar qiymat bo'sh bo'lsa habar tarjima qilinmagan hisoblanadi. Kodda boshqa uchramaydigan habarlar tarjimasi '@@' ga o'ralgan. Ayrim habarlar uchun [sonlar bilan qo'llanilishini qo'llab-quvvatlash uchun maxsus format](../guide-uz/tutorial-i18n.md) ni ishlatish zarur.
Qo'llanma
---------

1
docs/internals/translation-teams.md

@ -40,6 +40,7 @@ Spanish
-------
- Luciano Baraglia, [@lucianobaraglia](https://github.com/lucianobaraglia)
- Marco Da Silva, [@markmarco16](https://github.com/markmarco16), markmarco16@gmail.com
Ukrainian
---------

2
docs/internals/translation-workflow.md

@ -26,7 +26,7 @@ automatically re-extract messages keeping unchanged ones intact.
In the translation file each array element represents the translation (value) of a message (key). If the value is empty,
the message is considered as not translated. Messages that no longer need translation will have their translations
enclosed between a pair of '@@' marks. Message string can be used with plural forms format. Check [i18n section
of the guide](../guide/i18n.md) for details.
of the guide](../guide/tutorial-i18n.md) for details.
Documentation
-------------

47
extensions/authclient/BaseClient.php

@ -9,6 +9,7 @@ namespace yii\authclient;
use Yii;
use yii\base\Component;
use yii\base\InvalidConfigException;
use yii\base\NotSupportedException;
use yii\helpers\Inflector;
use yii\helpers\StringHelper;
@ -50,7 +51,23 @@ abstract class BaseClient extends Component implements ClientInterface
private $_userAttributes;
/**
* @var array map used to normalize user attributes fetched from external auth service
* in format: rawAttributeName => normalizedAttributeName
* in format: normalizedAttributeName => sourceSpecification
* 'sourceSpecification' can be:
* - string, raw attribute name
* - array, pass to raw attribute value
* - callable, PHP callback, which should accept array of raw attributes and return normalized value.
*
* For example:
*
* ```php
* 'normalizeUserAttributeMap' => [
* 'about' => 'bio',
* 'language' => ['languages', 0, 'name'],
* 'fullName' => function ($attributes) {
* return $attributes['firstName'] . ' ' . $attributes['lastName'];
* },
* ],
* ```
*/
private $_normalizeUserAttributeMap;
/**
@ -229,13 +246,37 @@ abstract class BaseClient extends Component implements ClientInterface
/**
* Normalize given user attributes according to [[normalizeUserAttributeMap]].
* @param array $attributes raw attributes.
* @throws InvalidConfigException on incorrect normalize attribute map.
* @return array normalized attributes.
*/
protected function normalizeUserAttributes($attributes)
{
foreach ($this->getNormalizeUserAttributeMap() as $normalizedName => $actualName) {
if (array_key_exists($actualName, $attributes)) {
$attributes[$normalizedName] = $attributes[$actualName];
if (is_scalar($actualName)) {
if (array_key_exists($actualName, $attributes)) {
$attributes[$normalizedName] = $attributes[$actualName];
}
} else {
if (is_callable($actualName)) {
$attributes[$normalizedName] = call_user_func($actualName, $attributes);
} elseif (is_array($actualName)) {
$haystack = $attributes;
$searchKeys = $actualName;
$isFound = true;
while (($key = array_shift($searchKeys)) !== null) {
if (is_array($haystack) && array_key_exists($key, $haystack)) {
$haystack = $haystack[$key];
} else {
$isFound = false;
break;
}
}
if ($isFound) {
$attributes[$normalizedName] = $haystack;
}
} else {
throw new InvalidConfigException('Invalid actual name "' . gettype($actualName) . '" specified at "' . get_class($this) . '::normalizeUserAttributeMap"');
}
}
}

2
extensions/authclient/CHANGELOG.md

@ -4,7 +4,7 @@ Yii Framework 2 authclient extension Change Log
2.0.0 under development
-----------------------
- no changes in this release.
- Enh #5135: Added ability to operate nested and complex attributes via `yii\authclient\BaseClient::normalizeUserAttributeMap` (zinzinday, klimov-paul)
2.0.0-rc September 27, 2014

1
extensions/authclient/README.md

@ -155,7 +155,6 @@ Following predefined auth clients are available:
- [[yii\authclient\clients\GoogleOAuth]] - [Google](https://www.google.com/) OAuth2 client
- [[yii\authclient\clients\GoogleOpenId]] - [Google](https://www.google.com/) OpenID client
- [[yii\authclient\clients\LinkedIn]] - [LinkedIn](http://www.linkedin.com/) OAuth2 client
- [[yii\authclient\clients\LinkedIn]] - [LinkedIn](http://www.linkedin.com/) OAuth2 client
- [[yii\authclient\clients\Live]] - [Microsoft Live](http://live.com/) OAuth2 client
- [[yii\authclient\clients\Twitter]] - [Twitter](https://twitter.com/) OAuth1 client
- [[yii\authclient\clients\VKontakte]] - [VKontakte](http://vk.com/) OAuth2 client

27
extensions/bootstrap/BootstrapThemeAsset.php

@ -0,0 +1,27 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\bootstrap;
use yii\web\AssetBundle;
/**
* Asset bundle for the Twitter bootstrap default theme.
*
* @author Alexander Makarov <sam@rmcreative.ru>
* @since 2.0
*/
class BootstrapThemeAsset extends AssetBundle
{
public $sourcePath = '@bower/bootstrap/dist';
public $css = [
'css/bootstrap-theme.css',
];
public $depends = [
'yii\bootstrap\BootstrapAsset',
];
}

2
extensions/codeception/README.md

@ -281,4 +281,4 @@ Then run command `php codecept.phar run --debug unit/SomeDebugTest` and you will
```
For further instructions refer to the testing section in the [Yii Definitive Guide](https://github.com/yiisoft/yii2/blob/master/docs/guide/testing.md).
For further instructions refer to the testing section in the [Yii Definitive Guide](https://github.com/yiisoft/yii2/blob/master/docs/guide/test-overview.md).

2
extensions/elasticsearch/ActiveQuery.php

@ -60,7 +60,7 @@ use yii\db\ActiveRelationTrait;
* A relation is specified by [[link]] which represents the association between columns
* of different tables; and the multiplicity of the relation is indicated by [[multiple]].
*
* If a relation involves a pivot table, it may be specified by [[via()]].
* If a relation involves a junction table, it may be specified by [[via()]].
* This methods may only be called in a relational context. Same is true for [[inverseOf()]], which
* marks a relation as inverse of another relation.
*

2
extensions/elasticsearch/README.md

@ -59,7 +59,7 @@ TBD
Using the ActiveRecord
----------------------
For general information on how to use yii's ActiveRecord please refer to the [guide](https://github.com/yiisoft/yii2/blob/master/docs/guide/active-record.md).
For general information on how to use yii's ActiveRecord please refer to the [guide](https://github.com/yiisoft/yii2/blob/master/docs/guide/db-active-record.md).
For defining an elasticsearch ActiveRecord class your record class needs to extend from [[yii\elasticsearch\ActiveRecord]] and
implement at least the [[yii\elasticsearch\ActiveRecord::attributes()|attributes()]] method to define the attributes of the record.

6
extensions/gii/generators/model/Generator.php

@ -388,12 +388,12 @@ class Generator extends \yii\gii\Generator
}
/**
* Checks if the given table is a pivot table.
* Checks if the given table is a junction table.
* For simplicity, this method only deals with the case where the pivot contains two PK columns,
* each referencing a column in a different table.
* @param \yii\db\TableSchema the table being checked
* @return array|boolean the relevant foreign key constraint information if the table is a pivot table,
* or false if the table is not a pivot table.
* @return array|boolean the relevant foreign key constraint information if the table is a junction table,
* or false if the table is not a junction table.
*/
protected function checkPivotTable($table)
{

4
extensions/mongodb/ActiveQuery.php

@ -50,7 +50,7 @@ use yii\db\ActiveRelationTrait;
* A relation is specified by [[link]] which represents the association between columns
* of different tables; and the multiplicity of the relation is indicated by [[multiple]].
*
* If a relation involves a pivot table, it may be specified by [[via()]].
* If a relation involves a junction table, it may be specified by [[via()]].
* This methods may only be called in a relational context. Same is true for [[inverseOf()]], which
* marks a relation as inverse of another relation.
*
@ -102,7 +102,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface
// lazy loading
if ($this->via instanceof self) {
// via pivot collection
$viaModels = $this->via->findPivotRows([$this->primaryModel]);
$viaModels = $this->via->findJunctionRows([$this->primaryModel]);
$this->filterByModels($viaModels);
} elseif (is_array($this->via)) {
// via relation

2
extensions/mongodb/CHANGELOG.md

@ -4,7 +4,7 @@ Yii Framework 2 mongodb extension Change Log
2.0.0 under development
-----------------------
- no changes in this release.
- Bug #5303: Fixed `yii\mongodb\Collection` unable to fetch default database name from DSN with parameters (klimov-paul)
2.0.0-rc September 27, 2014

2
extensions/mongodb/Connection.php

@ -148,7 +148,7 @@ class Connection extends Component
if ($this->defaultDatabaseName === null) {
if (isset($this->options['db'])) {
$this->defaultDatabaseName = $this->options['db'];
} elseif (preg_match('/^mongodb:\\/\\/.+\\/(.+)$/s', $this->dsn, $matches)) {
} elseif (preg_match('/^mongodb:\\/\\/.+\\/([^?&]+)/s', $this->dsn, $matches)) {
$this->defaultDatabaseName = $matches[1];
} else {
throw new InvalidConfigException("Unable to determine default database name from dsn.");

6
extensions/redis/ActiveQuery.php

@ -64,7 +64,7 @@ use yii\db\QueryTrait;
* A relation is specified by [[link]] which represents the association between columns
* of different tables; and the multiplicity of the relation is indicated by [[multiple]].
*
* If a relation involves a pivot table, it may be specified by [[via()]].
* If a relation involves a junction table, it may be specified by [[via()]].
* This methods may only be called in a relational context. Same is true for [[inverseOf()]], which
* marks a relation as inverse of another relation.
*
@ -312,8 +312,8 @@ class ActiveQuery extends Component implements ActiveQueryInterface
if ($this->primaryModel !== null) {
// lazy loading
if ($this->via instanceof self) {
// via pivot table
$viaModels = $this->via->findPivotRows([$this->primaryModel]);
// via junction table
$viaModels = $this->via->findJunctionRows([$this->primaryModel]);
$this->filterByModels($viaModels);
} elseif (is_array($this->via)) {
// via relation

4
extensions/sphinx/ActiveQuery.php

@ -73,7 +73,7 @@ use yii\db\ActiveRelationTrait;
* A relation is specified by [[link]] which represents the association between columns
* of different tables; and the multiplicity of the relation is indicated by [[multiple]].
*
* If a relation involves a pivot table, it may be specified by [[via()]].
* If a relation involves a junction table, it may be specified by [[via()]].
* This methods may only be called in a relational context. Same is true for [[inverseOf()]], which
* marks a relation as inverse of another relation.
*
@ -225,7 +225,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface
// lazy loading a relational query
if ($this->via instanceof self) {
// via pivot index
$viaModels = $this->via->findPivotRows([$this->primaryModel]);
$viaModels = $this->via->findJunctionRows([$this->primaryModel]);
$this->filterByModels($viaModels);
} elseif (is_array($this->via)) {
// via relation

2
extensions/sphinx/CHANGELOG.md

@ -4,7 +4,7 @@ Yii Framework 2 sphinx extension Change Log
2.0.0 under development
-----------------------
- no changes in this release.
- Enh #5211: `yii\sphinx\Query` now supports 'HAVING' (klimov-paul)
2.0.0-rc September 27, 2014

475
extensions/sphinx/Query.php

@ -8,10 +8,9 @@
namespace yii\sphinx;
use Yii;
use yii\base\Component;
use yii\base\InvalidCallException;
use yii\base\NotSupportedException;
use yii\db\Expression;
use yii\db\QueryInterface;
use yii\db\QueryTrait;
/**
@ -46,31 +45,8 @@ use yii\db\QueryTrait;
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
*/
class Query extends Component implements QueryInterface
class Query extends \yii\db\Query
{
use QueryTrait;
/**
* @var array the columns being selected. For example, `['id', 'group_id']`.
* This is used to construct the SELECT clause in a SQL statement. If not set, if means selecting all columns.
* @see select()
*/
public $select;
/**
* @var string additional option that should be appended to the 'SELECT' keyword.
*/
public $selectOption;
/**
* @var boolean whether to select distinct rows of data only. If this is set true,
* the SELECT clause would be changed to SELECT DISTINCT.
*/
public $distinct;
/**
* @var array the index(es) to be selected from. For example, `['idx_user', 'idx_user_delta']`.
* This is used to construct the FROM clause in a SQL statement.
* @see from()
*/
public $from;
/**
* @var string|Expression text, which should be searched in fulltext mode.
* This value will be composed into MATCH operator inside the WHERE clause.
@ -80,11 +56,6 @@ class Query extends Component implements QueryInterface
*/
public $match;
/**
* @var array how to group the query results. For example, `['company', 'department']`.
* This is used to construct the GROUP BY clause in a SQL statement.
*/
public $groupBy;
/**
* @var string WITHIN GROUP ORDER BY clause. This is a Sphinx specific extension
* that lets you control how the best row within a group will to be selected.
* The possible value matches the [[orderBy]] one.
@ -97,11 +68,6 @@ class Query extends Component implements QueryInterface
*/
public $options;
/**
* @var array list of query parameter values indexed by parameter placeholders.
* For example, `[':name' => 'Dan', ':age' => 31]`.
*/
public $params = [];
/**
* @var callable PHP callback, which should be used to fetch source data for the snippets.
* Such callback will receive array of query result rows as an argument and must return the
* array of snippet source strings in the order, which match one of incoming rows.
@ -165,55 +131,33 @@ class Query extends Component implements QueryInterface
/**
* Creates a Sphinx command that can be used to execute this query.
* @param Connection $connection the Sphinx connection used to generate the SQL statement.
* @param Connection $db the Sphinx connection used to generate the SQL statement.
* If this parameter is not given, the `sphinx` application component will be used.
* @return Command the created Sphinx command instance.
*/
public function createCommand($connection = null)
public function createCommand($db = null)
{
$this->setConnection($connection);
$connection = $this->getConnection();
list ($sql, $params) = $connection->getQueryBuilder()->build($this);
$this->setConnection($db);
$db = $this->getConnection();
list ($sql, $params) = $db->getQueryBuilder()->build($this);
return $connection->createCommand($sql, $params);
return $db->createCommand($sql, $params);
}
/**
* Executes the query and returns all results as an array.
* @param Connection $db the Sphinx connection used to generate the SQL statement.
* If this parameter is not given, the `sphinx` application component will be used.
* @return array the query results. If the query results in nothing, an empty array will be returned.
* @inheritdoc
*/
public function all($db = null)
public function populate($rows)
{
$rows = $this->createCommand($db)->queryAll();
$rows = $this->fillUpSnippets($rows);
if ($this->indexBy === null) {
return $rows;
}
$result = [];
foreach ($rows as $row) {
if (is_string($this->indexBy)) {
$key = $row[$this->indexBy];
} else {
$key = call_user_func($this->indexBy, $row);
}
$result[$key] = $row;
}
return $result;
return parent::populate($this->fillUpSnippets($rows));
}
/**
* Executes the query and returns a single row of result.
* @param Connection $db the Sphinx connection used to generate the SQL statement.
* If this parameter is not given, the `sphinx` application component will be used.
* @return array|boolean the first row (in terms of an array) of the query result. False is returned if the query
* results in nothing.
* @inheritdoc
*/
public function one($db = null)
{
$row = $this->createCommand($db)->queryOne();
$row = parent::one($db);
if ($row !== false) {
list ($row) = $this->fillUpSnippets([$row]);
}
@ -222,168 +166,6 @@ class Query extends Component implements QueryInterface
}
/**
* Returns the query result as a scalar value.
* The value returned will be the first column in the first row of the query results.
* @param Connection $db the Sphinx connection used to generate the SQL statement.
* If this parameter is not given, the `sphinx` application component will be used.
* @return string|boolean the value of the first column in the first row of the query result.
* False is returned if the query result is empty.
*/
public function scalar($db = null)
{
return $this->createCommand($db)->queryScalar();
}
/**
* Executes the query and returns the first column of the result.
* @param Connection $db the Sphinx connection used to generate the SQL statement.
* If this parameter is not given, the `sphinx` application component will be used.
* @return array the first column of the query result. An empty array is returned if the query results in nothing.
*/
public function column($db = null)
{
return $this->createCommand($db)->queryColumn();
}
/**
* Returns the number of records.
* @param string $q the COUNT expression. Defaults to '*'.
* Make sure you properly quote column names in the expression.
* @param Connection $db the Sphinx connection used to generate the SQL statement.
* If this parameter is not given, the `sphinx` application component will be used.
* @return integer number of records
*/
public function count($q = '*', $db = null)
{
$this->select = ["COUNT($q)"];
return $this->createCommand($db)->queryScalar();
}
/**
* Returns the sum of the specified column values.
* @param string $q the column name or expression.
* Make sure you properly quote column names in the expression.
* @param Connection $db the Sphinx connection used to generate the SQL statement.
* If this parameter is not given, the `sphinx` application component will be used.
* @return integer the sum of the specified column values
*/
public function sum($q, $db = null)
{
$this->select = ["SUM($q)"];
return $this->createCommand($db)->queryScalar();
}
/**
* Returns the average of the specified column values.
* @param string $q the column name or expression.
* Make sure you properly quote column names in the expression.
* @param Connection $db the Sphinx connection used to generate the SQL statement.
* If this parameter is not given, the `sphinx` application component will be used.
* @return integer the average of the specified column values.
*/
public function average($q, $db = null)
{
$this->select = ["AVG($q)"];
return $this->createCommand($db)->queryScalar();
}
/**
* Returns the minimum of the specified column values.
* @param string $q the column name or expression.
* Make sure you properly quote column names in the expression.
* @param Connection $db the Sphinx connection used to generate the SQL statement.
* If this parameter is not given, the `sphinx` application component will be used.
* @return integer the minimum of the specified column values.
*/
public function min($q, $db = null)
{
$this->select = ["MIN($q)"];
return $this->createCommand($db)->queryScalar();
}
/**
* Returns the maximum of the specified column values.
* @param string $q the column name or expression.
* Make sure you properly quote column names in the expression.
* @param Connection $db the Sphinx connection used to generate the SQL statement.
* If this parameter is not given, the `sphinx` application component will be used.
* @return integer the maximum of the specified column values.
*/
public function max($q, $db = null)
{
$this->select = ["MAX($q)"];
return $this->createCommand($db)->queryScalar();
}
/**
* Returns a value indicating whether the query result contains any row of data.
* @param Connection $db the Sphinx connection used to generate the SQL statement.
* If this parameter is not given, the `sphinx` application component will be used.
* @return boolean whether the query result contains any row of data.
*/
public function exists($db = null)
{
$this->select = [new Expression('1')];
return $this->scalar($db) !== false;
}
/**
* Sets the SELECT part of the query.
* @param string|array $columns the columns to be selected.
* Columns can be specified in either a string (e.g. "id, name") or an array (e.g. ['id', 'name']).
* The method will automatically quote the column names unless a column contains some parenthesis
* (which means the column contains a Sphinx expression).
* @param string $option additional option that should be appended to the 'SELECT' keyword.
* @return static the query object itself
*/
public function select($columns, $option = null)
{
if (!is_array($columns)) {
$columns = preg_split('/\s*,\s*/', trim($columns), -1, PREG_SPLIT_NO_EMPTY);
}
$this->select = $columns;
$this->selectOption = $option;
return $this;
}
/**
* Sets the value indicating whether to SELECT DISTINCT or not.
* @param boolean $value whether to SELECT DISTINCT or not.
* @return static the query object itself
*/
public function distinct($value = true)
{
$this->distinct = $value;
return $this;
}
/**
* Sets the FROM part of the query.
* @param string|array $tables the table(s) to be selected from. This can be either a string (e.g. `'idx_user'`)
* or an array (e.g. `['idx_user', 'idx_user_delta']`) specifying one or several index names.
* The method will automatically quote the table names unless it contains some parenthesis
* (which means the table is given as a sub-query or Sphinx expression).
* @return static the query object itself
*/
public function from($tables)
{
if (!is_array($tables)) {
$tables = preg_split('/\s*,\s*/', trim($tables), -1, PREG_SPLIT_NO_EMPTY);
}
$this->from = $tables;
return $this;
}
/**
* Sets the fulltext query text. This text will be composed into
* MATCH operator inside the WHERE clause.
* Note: this value will be processed by [[Connection::escapeMatchValue()]],
@ -405,210 +187,35 @@ class Query extends Component implements QueryInterface
}
/**
* Sets the WHERE part of the query.
*
* The method requires a $condition parameter, and optionally a $params parameter
* specifying the values to be bound to the query.
*
* The $condition parameter should be either a string (e.g. 'id=1') or an array.
* If the latter, it must be in one of the following two formats:
*
* - hash format: `['column1' => value1, 'column2' => value2, ...]`
* - operator format: `[operator, operand1, operand2, ...]`
*
* A condition in hash format represents the following SQL expression in general:
* `column1=value1 AND column2=value2 AND ...`. In case when a value is an array or a Query object,
* an `IN` expression will be generated. And if a value is null, `IS NULL` will be used
* in the generated expression. Below are some examples:
*
* - `['type' => 1, 'status' => 2]` generates `(type = 1) AND (status = 2)`.
* - `['id' => [1, 2, 3], 'status' => 2]` generates `(id IN (1, 2, 3)) AND (status = 2)`.
* - `['status' => null] generates `status IS NULL`.
* - `['id' => $query]` generates `id IN (...sub-query...)`
*
* A condition in operator format generates the SQL expression according to the specified operator, which
* can be one of the followings:
*
* - `and`: the operands should be concatenated together using `AND`. For example,
* `['and', 'id=1', 'id=2']` will generate `id=1 AND id=2`. If an operand is an array,
* it will be converted into a string using the rules described here. For example,
* `['and', 'type=1', ['or', 'id=1', 'id=2']]` will generate `type=1 AND (id=1 OR id=2)`.
* The method will NOT do any quoting or escaping.
*
* - `or`: similar to the `and` operator except that the operands are concatenated using `OR`.
*
* - `between`: operand 1 should be the column name, and operand 2 and 3 should be the
* starting and ending values of the range that the column is in.
* For example, `['between', 'id', 1, 10]` will generate `id BETWEEN 1 AND 10`.
*
* - `not between`: similar to `between` except the `BETWEEN` is replaced with `NOT BETWEEN`
* in the generated condition.
*
* - `in`: operand 1 should be a column or DB expression with parenthesis. Operand 2 can be an array
* or a Query object. If the former, the array represents the range of the values that the column
* or DB expression should be in. If the latter, a sub-query will be generated to represent the range.
* For example, `['in', 'id', [1, 2, 3]]` will generate `id IN (1, 2, 3)`;
* `['in', 'id', (new Query)->select('id')->from('user'))]` will generate
* `id IN (SELECT id FROM user)`. The method will properly quote the column name and escape values in the range.
* The `in` operator also supports composite columns. In this case, operand 1 should be an array of the columns,
* while operand 2 should be an array of arrays or a `Query` object representing the range of the columns.
*
* - `not in`: similar to the `in` operator except that `IN` is replaced with `NOT IN` in the generated condition.
*
* - `like`: operand 1 should be a column or DB expression, and operand 2 be a string or an array representing
* the values that the column or DB expression should be like.
* For example, `['like', 'name', '%tester%']` will generate `name LIKE '%tester%'`.
* When the value range is given as an array, multiple `LIKE` predicates will be generated and concatenated
* using `AND`. For example, `['like', 'name', ['%test%', '%sample%']]` will generate
* `name LIKE '%test%' AND name LIKE '%sample%'`.
* The method will properly quote the column name and escape values in the range.
* Sometimes, you may want to add the percentage characters to the matching value by yourself, you may supply
* a third operand `false` to do so. For example, `['like', 'name', '%tester', false]` will generate `name LIKE '%tester'`.
*
* - `or like`: similar to the `like` operator except that `OR` is used to concatenate the `LIKE`
* predicates when operand 2 is an array.
*
* - `not like`: similar to the `like` operator except that `LIKE` is replaced with `NOT LIKE`
* in the generated condition.
*
* - `or not like`: similar to the `not like` operator except that `OR` is used to concatenate
* the `NOT LIKE` predicates.
*
* @param string|array $condition the conditions that should be put in the WHERE part.
* @param array $params the parameters (name => value) to be bound to the query.
* @return static the query object itself
* @see andWhere()
* @see orWhere()
* @inheritdoc
*/
public function where($condition, $params = [])
public function join($type, $table, $on = '', $params = [])
{
$this->where = $condition;
$this->addParams($params);
return $this;
throw new NotSupportedException('"' . __METHOD__ . '" is not supported.');
}
/**
* Adds an additional WHERE condition to the existing one.
* The new condition and the existing one will be joined using the 'AND' operator.
* @param string|array $condition the new WHERE condition. Please refer to [[where()]]
* on how to specify this parameter.
* @param array $params the parameters (name => value) to be bound to the query.
* @return static the query object itself
* @see where()
* @see orWhere()
* @inheritdoc
*/
public function andWhere($condition, $params = [])
public function innerJoin($table, $on = '', $params = [])
{
if ($this->where === null) {
$this->where = $condition;
} else {
$this->where = ['and', $this->where, $condition];
}
$this->addParams($params);
return $this;
}
/**
* Adds an additional WHERE condition to the existing one.
* The new condition and the existing one will be joined using the 'OR' operator.
* @param string|array $condition the new WHERE condition. Please refer to [[where()]]
* on how to specify this parameter.
* @param array $params the parameters (name => value) to be bound to the query.
* @return static the query object itself
* @see where()
* @see andWhere()
*/
public function orWhere($condition, $params = [])
{
if ($this->where === null) {
$this->where = $condition;
} else {
$this->where = ['or', $this->where, $condition];
}
$this->addParams($params);
return $this;
}
/**
* Sets the GROUP BY part of the query.
* @param string|array $columns the columns to be grouped by.
* Columns can be specified in either a string (e.g. "id, name") or an array (e.g. ['id', 'name']).
* The method will automatically quote the column names unless a column contains some parenthesis
* (which means the column contains a DB expression).
* @return static the query object itself
* @see addGroupBy()
*/
public function groupBy($columns)
{
if (!is_array($columns)) {
$columns = preg_split('/\s*,\s*/', trim($columns), -1, PREG_SPLIT_NO_EMPTY);
}
$this->groupBy = $columns;
return $this;
}
/**
* Adds additional group-by columns to the existing ones.
* @param string|array $columns additional columns to be grouped by.
* Columns can be specified in either a string (e.g. "id, name") or an array (e.g. ['id', 'name']).
* The method will automatically quote the column names unless a column contains some parenthesis
* (which means the column contains a DB expression).
* @return static the query object itself
* @see groupBy()
*/
public function addGroupBy($columns)
{
if (!is_array($columns)) {
$columns = preg_split('/\s*,\s*/', trim($columns), -1, PREG_SPLIT_NO_EMPTY);
}
if ($this->groupBy === null) {
$this->groupBy = $columns;
} else {
$this->groupBy = array_merge($this->groupBy, $columns);
}
return $this;
throw new NotSupportedException('"' . __METHOD__ . '" is not supported.');
}
/**
* Sets the parameters to be bound to the query.
* @param array $params list of query parameter values indexed by parameter placeholders.
* For example, `[':name' => 'Dan', ':age' => 31]`.
* @return static the query object itself
* @see addParams()
* @inheritdoc
*/
public function params($params)
public function leftJoin($table, $on = '', $params = [])
{
$this->params = $params;
return $this;
throw new NotSupportedException('"' . __METHOD__ . '" is not supported.');
}
/**
* Adds additional parameters to be bound to the query.
* @param array $params list of query parameter values indexed by parameter placeholders.
* For example, `[':name' => 'Dan', ':age' => 31]`.
* @return static the query object itself
* @see params()
* @inheritdoc
*/
public function addParams($params)
public function rightJoin($table, $on = '', $params = [])
{
if (!empty($params)) {
if (empty($this->params)) {
$this->params = $params;
} else {
foreach ($params as $name => $value) {
if (is_integer($name)) {
$this->params[] = $value;
} else {
$this->params[$name] = $value;
}
}
}
}
return $this;
throw new NotSupportedException('"' . __METHOD__ . '" is not supported.');
}
/**
@ -759,4 +366,36 @@ class Query extends Component implements QueryInterface
->callSnippets($from, $source, $match, $this->snippetOptions)
->queryColumn();
}
/**
* Creates a new Query object and copies its property values from an existing one.
* The properties being copies are the ones to be used by query builders.
* @param Query $from the source query object
* @return Query the new Query object
*/
public static function create($from)
{
return new self([
'where' => $from->where,
'limit' => $from->limit,
'offset' => $from->offset,
'orderBy' => $from->orderBy,
'indexBy' => $from->indexBy,
'select' => $from->select,
'selectOption' => $from->selectOption,
'distinct' => $from->distinct,
'from' => $from->from,
'groupBy' => $from->groupBy,
'join' => $from->join,
'having' => $from->having,
'union' => $from->union,
'params' => $from->params,
// Sphinx specifics :
'options' => $from->options,
'within' => $from->within,
'match' => $from->match,
'snippetCallback' => $from->snippetCallback,
'snippetOptions' => $from->snippetOptions,
]);
}
}

117
extensions/sphinx/QueryBuilder.php

@ -8,6 +8,7 @@
namespace yii\sphinx;
use yii\base\InvalidParamException;
use yii\base\NotSupportedException;
use yii\base\Object;
use yii\db\Exception;
use yii\db\Expression;
@ -38,6 +39,24 @@ class QueryBuilder extends Object
*/
public $separator = " ";
/**
* @var array map of query condition to builder methods.
* These methods are used by [[buildCondition]] to build SQL conditions from array syntax.
*/
protected $conditionBuilders = [
'AND' => 'buildAndCondition',
'OR' => 'buildAndCondition',
'BETWEEN' => 'buildBetweenCondition',
'NOT BETWEEN' => 'buildBetweenCondition',
'IN' => 'buildInCondition',
'NOT IN' => 'buildInCondition',
'LIKE' => 'buildLikeCondition',
'NOT LIKE' => 'buildLikeCondition',
'OR LIKE' => 'buildLikeCondition',
'OR NOT LIKE' => 'buildLikeCondition',
'NOT' => 'buildNotCondition',
];
/**
* Constructor.
@ -55,12 +74,19 @@ class QueryBuilder extends Object
* @param Query $query the [[Query]] object from which the SQL statement will be generated
* @param array $params the parameters to be bound to the generated SQL statement. These parameters will
* be included in the result with the additional parameters generated during the query building process.
* @throws NotSupportedException if query contains 'join' option.
* @return array the generated SQL statement (the first array element) and the corresponding
* parameters to be bound to the SQL statement (the second array element). The parameters returned
* include those provided in `$params`.
*/
public function build($query, $params = [])
{
$query = $query->prepare($this);
if (!empty($query->join)) {
throw new NotSupportedException('Build of "' . get_class($query) . '::join" is not supported.');
}
$params = empty($params) ? $query->params : array_merge($params, $query->params);
$from = $query->from;
@ -76,6 +102,7 @@ class QueryBuilder extends Object
$this->buildWhere($query->from, $query->where, $params, $query->match),
$this->buildGroupBy($query->groupBy),
$this->buildWithin($query->within),
$this->buildHaving($query->from, $query->having, $params),
$this->buildOrderBy($query->orderBy),
$this->buildLimit($query->limit, $query->offset),
$this->buildOption($query->options, $params),
@ -501,15 +528,7 @@ class QueryBuilder extends Object
if (empty($condition)) {
return '';
}
$indexSchemas = [];
if (!empty($indexes)) {
foreach ($indexes as $indexName) {
$index = $this->db->getIndexSchema($indexName);
if ($index !== null) {
$indexSchemas[] = $index;
}
}
}
$indexSchemas = $this->getIndexSchemas($indexes);
$where = $this->buildCondition($indexSchemas, $condition, $params);
return $where === '' ? '' : 'WHERE ' . $where;
@ -525,6 +544,24 @@ class QueryBuilder extends Object
}
/**
* @param string[] $indexes list of index names, which affected by query
* @param string|array $condition
* @param array $params the binding parameters to be populated
* @return string the HAVING clause built from [[Query::$having]].
*/
public function buildHaving($indexes, $condition, &$params)
{
if (empty($condition)) {
return '';
}
$indexSchemas = $this->getIndexSchemas($indexes);
$having = $this->buildCondition($indexSchemas, $condition, $params);
return $having === '' ? '' : 'HAVING ' . $having;
}
/**
* Builds the ORDER BY and LIMIT/OFFSET clauses and appends them to the given SQL.
* @param string $sql the existing SQL (without ORDER BY/LIMIT/OFFSET)
* @param array $orderBy the order by columns. See [[Query::orderBy]] for more details on how to specify this parameter.
@ -623,19 +660,6 @@ class QueryBuilder extends Object
*/
public function buildCondition($indexes, $condition, &$params)
{
static $builders = [
'AND' => 'buildAndCondition',
'OR' => 'buildAndCondition',
'BETWEEN' => 'buildBetweenCondition',
'NOT BETWEEN' => 'buildBetweenCondition',
'IN' => 'buildInCondition',
'NOT IN' => 'buildInCondition',
'LIKE' => 'buildLikeCondition',
'NOT LIKE' => 'buildLikeCondition',
'OR LIKE' => 'buildLikeCondition',
'OR NOT LIKE' => 'buildLikeCondition',
];
if (!is_array($condition)) {
return (string) $condition;
} elseif (empty($condition)) {
@ -643,15 +667,14 @@ class QueryBuilder extends Object
}
if (isset($condition[0])) { // operator format: operator, operand 1, operand 2, ...
$operator = strtoupper($condition[0]);
if (isset($builders[$operator])) {
$method = $builders[$operator];
if (isset($this->conditionBuilders[$operator])) {
$method = $this->conditionBuilders[$operator];
} else {
$method = 'buildSimpleCondition';
}
array_shift($condition);
return $this->$method($indexes, $operator, $condition, $params);
} else { // hash format: 'column1' => 'value1', 'column2' => 'value2', ...
return $this->buildHashCondition($indexes, $condition, $params);
}
}
@ -714,6 +737,32 @@ class QueryBuilder extends Object
}
/**
* Inverts an SQL expressions with `NOT` operator.
* @param IndexSchema[] $indexes list of indexes, which affected by query
* @param string $operator the operator to use for connecting the given operands
* @param array $operands the SQL expressions to connect.
* @param array $params the binding parameters to be populated
* @return string the generated SQL expression
* @throws InvalidParamException if wrong number of operands have been given.
*/
public function buildNotCondition($indexes, $operator, $operands, &$params)
{
if (count($operands) != 1) {
throw new InvalidParamException("Operator '$operator' requires exactly one operand.");
}
$operand = reset($operands);
if (is_array($operand)) {
$operand = $this->buildCondition($indexes, $operand, $params);
}
if ($operand === '') {
return '';
}
return "$operator ($operand)";
}
/**
* Creates an SQL expressions with the `BETWEEN` operator.
* @param IndexSchema[] $indexes list of indexes, which affected by query
* @param string $operator the operator to use (e.g. `BETWEEN` or `NOT BETWEEN`)
@ -1042,4 +1091,22 @@ class QueryBuilder extends Object
return "$column $operator $phName";
}
}
/**
* @param array $indexes index names.
* @return IndexSchema[] index schemas.
*/
private function getIndexSchemas($indexes)
{
$indexSchemas = [];
if (!empty($indexes)) {
foreach ($indexes as $indexName) {
$index = $this->db->getIndexSchema($indexName);
if ($index !== null) {
$indexSchemas[] = $index;
}
}
}
return $indexSchemas;
}
}

2
framework/CHANGELOG.md

@ -9,7 +9,9 @@ Yii Framework 2 Change Log
- Bug #5314: Fixed typo in the implementation of `yii\web\Session::getHasSessionId()` (qiangxue)
- Bug #5323: Nested dropdown does not work for `yii\bootstrap\DropDown` (aryraditya)
- Bug #5336: `yii\bootstrap\DropDown` should register bootstrap plugin asset (zelenin)
- Bug #5379: `Module::afterAction()` was called even when `beforeAction()` returned false (cebe)
- Bug #5423: `yii\behaviors\Cors` causes "undefined index" error when its `cors` is configured (qiangxue)
- Bug #5424: `Html::addCssStyle()` wasn't correctly setting style passed in array (kartik-v, samdark)
- Bug: Date and time formatting now assumes UTC as the timezone for input dates unless a timezone is explicitly given (cebe)
- Enh #4040: Added `$viewFile` and `$params` to the `EVENT_BEFORE_RENDER` and `EVENT_AFTER_RENDER` events for `View` (qiangxue)
- Enh #4275: Added `removeChildren()` to `yii\rbac\ManagerInterface` and implementations (samdark)

20
framework/base/Controller.php

@ -134,6 +134,7 @@ class Controller extends Component implements ViewContextInterface
$modules = [];
$runAction = true;
// call beforeAction on modules
foreach ($this->getModules() as $module) {
if ($module->beforeAction($action)) {
array_unshift($modules, $module);
@ -145,16 +146,17 @@ class Controller extends Component implements ViewContextInterface
$result = null;
if ($runAction) {
if ($this->beforeAction($action)) {
$result = $action->runWithParams($params);
$result = $this->afterAction($action, $result);
}
}
if ($runAction && $this->beforeAction($action)) {
// run the action
$result = $action->runWithParams($params);
foreach ($modules as $module) {
/* @var $module Module */
$result = $module->afterAction($action, $result);
$result = $this->afterAction($action, $result);
// call afterAction on modules
foreach ($modules as $module) {
/* @var $module Module */
$result = $module->afterAction($action, $result);
}
}
$this->action = $oldAction;

18
framework/db/ActiveQuery.php

@ -58,7 +58,7 @@ namespace yii\db;
* A relation is specified by [[link]] which represents the association between columns
* of different tables; and the multiplicity of the relation is indicated by [[multiple]].
*
* If a relation involves a pivot table, it may be specified by [[via()]] or [[viaTable()]] method.
* If a relation involves a junction table, it may be specified by [[via()]] or [[viaTable()]] method.
* These methods may only be called in a relational context. Same is true for [[inverseOf()]], which
* marks a relation as inverse of another relation and [[onCondition()]] which adds a condition that
* is to be added to relational query join condition.
@ -175,8 +175,8 @@ class ActiveQuery extends Query implements ActiveQueryInterface
$where = $this->where;
if ($this->via instanceof self) {
// via pivot table
$viaModels = $this->via->findPivotRows([$this->primaryModel]);
// via junction table
$viaModels = $this->via->findJunctionRows([$this->primaryModel]);
$this->filterByModels($viaModels);
} elseif (is_array($this->via)) {
// via relation
@ -655,9 +655,9 @@ class ActiveQuery extends Query implements ActiveQueryInterface
}
/**
* Specifies the pivot table for a relational query.
* Specifies the junction table for a relational query.
*
* Use this method to specify a pivot table when declaring a relation in the [[ActiveRecord]] class:
* Use this method to specify a junction table when declaring a relation in the [[ActiveRecord]] class:
*
* ```php
* public function getItems()
@ -667,11 +667,11 @@ class ActiveQuery extends Query implements ActiveQueryInterface
* }
* ```
*
* @param string $tableName the name of the pivot table.
* @param array $link the link between the pivot table and the table associated with [[primaryModel]].
* The keys of the array represent the columns in the pivot table, and the values represent the columns
* @param string $tableName the name of the junction table.
* @param array $link the link between the junction table and the table associated with [[primaryModel]].
* The keys of the array represent the columns in the junction table, and the values represent the columns
* in the [[primaryModel]] table.
* @param callable $callable a PHP callback for customizing the relation associated with the pivot table.
* @param callable $callable a PHP callback for customizing the relation associated with the junction table.
* Its signature should be `function($query)`, where `$query` is the query to be customized.
* @return static
* @see via()

4
framework/db/ActiveQueryInterface.php

@ -80,9 +80,9 @@ interface ActiveQueryInterface extends QueryInterface
public function with();
/**
* Specifies the relation associated with the pivot table for use in relational query.
* Specifies the relation associated with the junction table for use in relational query.
* @param string $relationName the relation name. This refers to a relation declared in the [[ActiveRelationTrait::primaryModel|primaryModel]] of the relation.
* @param callable $callable a PHP callback for customizing the relation associated with the pivot table.
* @param callable $callable a PHP callback for customizing the relation associated with the junction table.
* Its signature should be `function($query)`, where `$query` is the query to be customized.
* @return static the relation object itself.
*/

8
framework/db/ActiveRecordInterface.php

@ -365,15 +365,15 @@ interface ActiveRecordInterface
* to be the corresponding primary key value(s) in the other record.
* The record with the foreign key will be saved into database without performing validation.
*
* If the relationship involves a pivot table, a new row will be inserted into the
* pivot table which contains the primary key values from both records.
* If the relationship involves a junction table, a new row will be inserted into the
* junction table which contains the primary key values from both records.
*
* This method requires that the primary key value is not null.
*
* @param string $name the case sensitive name of the relationship.
* @param static $model the record to be linked with the current one.
* @param array $extraColumns additional column values to be saved into the pivot table.
* This parameter is only meaningful for a relationship involving a pivot table
* @param array $extraColumns additional column values to be saved into the junction table.
* This parameter is only meaningful for a relationship involving a junction table
* (i.e., a relation set with `[[ActiveQueryInterface::via()]]`.)
*/
public function link($name, $model, $extraColumns = []);

12
framework/db/ActiveRelationTrait.php

@ -44,7 +44,7 @@ trait ActiveRelationTrait
*/
public $link;
/**
* @var array|object the query associated with the pivot table. Please call [[via()]]
* @var array|object the query associated with the junction table. Please call [[via()]]
* to set this property instead of directly setting it.
* This property is only used in relational context.
* @see via()
@ -78,7 +78,7 @@ trait ActiveRelationTrait
}
/**
* Specifies the relation associated with the pivot table.
* Specifies the relation associated with the junction table.
*
* Use this method to specify a pivot record/table when declaring a relation in the [[ActiveRecord]] class:
*
@ -96,7 +96,7 @@ trait ActiveRelationTrait
* ```
*
* @param string $relationName the relation name. This refers to a relation declared in [[primaryModel]].
* @param callable $callable a PHP callback for customizing the relation associated with the pivot table.
* @param callable $callable a PHP callback for customizing the relation associated with the junction table.
* Its signature should be `function($query)`, where `$query` is the query to be customized.
* @return static the relation object itself.
*/
@ -195,10 +195,10 @@ trait ActiveRelationTrait
}
if ($this->via instanceof self) {
// via pivot table
// via junction table
/* @var $viaQuery ActiveRelationTrait */
$viaQuery = $this->via;
$viaModels = $viaQuery->findPivotRows($primaryModels);
$viaModels = $viaQuery->findJunctionRows($primaryModels);
$this->filterByModels($viaModels);
} elseif (is_array($this->via)) {
// via relation
@ -490,7 +490,7 @@ trait ActiveRelationTrait
* @param array $primaryModels either array of AR instances or arrays
* @return array
*/
private function findPivotRows($primaryModels)
private function findJunctionRows($primaryModels)
{
if (empty($primaryModels)) {
return [];

8
framework/db/BaseActiveRecord.php

@ -1138,15 +1138,15 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
* to be the corresponding primary key value(s) in the other model.
* The model with the foreign key will be saved into database without performing validation.
*
* If the relationship involves a pivot table, a new row will be inserted into the
* pivot table which contains the primary key values from both models.
* If the relationship involves a junction table, a new row will be inserted into the
* junction table which contains the primary key values from both models.
*
* Note that this method requires that the primary key value is not null.
*
* @param string $name the case sensitive name of the relationship
* @param ActiveRecordInterface $model the model to be linked with the current one.
* @param array $extraColumns additional column values to be saved into the pivot table.
* This parameter is only meaningful for a relationship involving a pivot table
* @param array $extraColumns additional column values to be saved into the junction table.
* This parameter is only meaningful for a relationship involving a junction table
* (i.e., a relation set with [[ActiveRelationTrait::via()]] or `[[ActiveQuery::viaTable()]]`.)
* @throws InvalidCallException if the method is unable to link two models.
*/

4
framework/db/Connection.php

@ -15,11 +15,11 @@ use yii\base\NotSupportedException;
use yii\caching\Cache;
/**
* Connection represents a connection to a database via [PDO](http://www.php.net/manual/en/ref.pdo.php).
* Connection represents a connection to a database via [PDO](php.net/manual/en/book.pdo.php).
*
* Connection works together with [[Command]], [[DataReader]] and [[Transaction]]
* to provide data access to various DBMS in a common set of APIs. They are a thin wrapper
* of the [[PDO PHP extension]](http://www.php.net/manual/en/ref.pdo.php).
* of the [[PDO PHP extension]](php.net/manual/en/book.pdo.php).
*
* Connection supports database replication and read-write splitting. In particular, a Connection component
* can be configured with multiple [[masters]] and [[slaves]]. It will do load balancing and failover by choosing

6
framework/filters/Cors.php

@ -120,7 +120,7 @@ class Cors extends ActionFilter
}
/**
* Extract CORS headers fron the request
* Extract CORS headers from the request
* @return array CORS headers to handle
*/
public function extractHeaders()
@ -176,7 +176,7 @@ class Cors extends ActionFilter
* Handle classic CORS request to avoid duplicate code
* @param string $type the kind of headers we would handle
* @param array $requestHeaders CORS headers request by client
* @param array $responseHeaders CORS response headers sent to the clinet
* @param array $responseHeaders CORS response headers sent to the client
*/
protected function prepareAllowHeaders($type, $requestHeaders, &$responseHeaders)
{
@ -204,7 +204,7 @@ class Cors extends ActionFilter
/**
* Adds the CORS headers to the response
* @param Response $response
* @param array CORS headers which have been compouted
* @param array CORS headers which have been computed
*/
public function addCorsHeaders($response, $headers)
{

4
framework/helpers/BaseHtml.php

@ -1703,9 +1703,9 @@ class BaseHtml
}
}
}
$style = static::cssStyleFromArray(array_merge($oldStyle, $newStyle));
$style = array_merge($oldStyle, $newStyle);
}
$options['style'] = $style;
$options['style'] = is_array($style) ? static::cssStyleFromArray($style) : $style;
}
/**

6
framework/i18n/Formatter.php

@ -258,6 +258,7 @@ class Formatter extends Component
/**
* Formats the value as is without any formatting.
* This method simply returns back the parameter without any format.
* The only exception is a `null` value which will be formatted using [[nullDisplay]].
* @param mixed $value the value to be formatted.
* @return string the formatted result.
*/
@ -342,14 +343,15 @@ class Formatter extends Component
/**
* Formats the value as an image tag.
* @param mixed $value the value to be formatted.
* @param string $altText an optional `alt`-tag to be added to the image.
* @return string the formatted result.
*/
public function asImage($value)
public function asImage($value, $altText = '')
{
if ($value === null) {
return $this->nullDisplay;
}
return Html::img($value);
return Html::img($value, ['alt' => $altText]);
}
/**

1
framework/messages/config.php

@ -38,6 +38,7 @@ return [
'.hgignore',
'.hgkeep',
'/messages',
'/BaseYii.php', // contains examples about Yii:t()
],
// array, list of patterns that specify which files (not directories) should be processed.
// If empty or not set, all files will be processed.

86
framework/messages/el/yii.php

@ -17,49 +17,87 @@
* NOTE: this file must be saved in UTF-8 encoding.
*/
return [
'Are you sure you want to delete this item?' => 'Είστε σίγουροι για τη διαγραφή του αντικειμένου;',
'Only files with these MIME types are allowed: {mimeTypes}.' => 'Επιτρέπονται μόνο αρχεία με τους ακόλουθους τύπους MIME: {mimeTypes}.',
'The requested view "{name}" was not found.' => 'Δε βρέθηκε η αιτούμενη όψη "{name}".',
'in {delta, plural, =1{a day} other{# days}}' => 'σε {delta, plural, =1{μία ημέρα} other{# ημέρες}}',
'in {delta, plural, =1{a minute} other{# minutes}}' => 'σε {delta, plural, =1{ένα λεπτό} other{# λεπτά}}',
'in {delta, plural, =1{a month} other{# months}}' => 'σε {delta, plural, =1{ένα μήνα} other{# μήνες}}',
'in {delta, plural, =1{a second} other{# seconds}}' => 'σε {delta, plural, =1{ένα δευτερόλεπτο} other{# δευτερόλεπτα}}',
'in {delta, plural, =1{a year} other{# years}}' => 'σε {delta, plural, =1{ένα έτος} other{# έτη}}',
'in {delta, plural, =1{an hour} other{# hours}}' => 'σε {delta, plural, =1{μία ώρα} other{# ώρες}}',
'just now' => 'μόλις τώρα',
'{delta, plural, =1{a day} other{# days}} ago' => 'πριν {delta, plural, =1{μία ημέρα} other{# ημέρες}}',
'{delta, plural, =1{a minute} other{# minutes}} ago' => 'πριν {delta, plural, =1{ένα λεπτό} other{# λεπτά}}',
'{delta, plural, =1{a month} other{# months}} ago' => 'πριν {delta, plural, =1{ένα μήνα} other{# μήνες}}',
'{delta, plural, =1{a second} other{# seconds}} ago' => 'πριν {delta, plural, =1{ένα δευτερόλεπτο} other{# δευτερόλεπτα}}',
'{delta, plural, =1{a year} other{# years}} ago' => 'πριν {delta, plural, =1{ένα έτος} other{# έτη}}',
'{delta, plural, =1{an hour} other{# hours}} ago' => 'πριν {delta, plural, =1{μία ώρα} other{# ώρες}}',
'{nFormatted} B' => '{nFormatted} B',
'{nFormatted} GB' => '{nFormatted} GB',
'{nFormatted} GiB' => '{nFormatted} GiB',
'{nFormatted} KB' => '{nFormatted} KB',
'{nFormatted} KiB' => '{nFormatted} KiB',
'{nFormatted} MB' => '{nFormatted} MB',
'{nFormatted} MiB' => '{nFormatted} MiB',
'{nFormatted} PB' => '{nFormatted} PB',
'{nFormatted} PiB' => '{nFormatted} PiB',
'{nFormatted} TB' => '{nFormatted} TB',
'{nFormatted} TiB' => '{nFormatted} TiB',
'{nFormatted} {n, plural, =1{byte} other{bytes}}' => '{nFormatted} {n, plural, =1{byte} other{bytes}}',
'{nFormatted} {n, plural, =1{gibibyte} other{gibibytes}}' => '{nFormatted} {n, plural, =1{gibibyte} other{gibibytes}}',
'{nFormatted} {n, plural, =1{gigabyte} other{gigabytes}}' => '{nFormatted} {n, plural, =1{gigabyte} other{gigabytes}}',
'{nFormatted} {n, plural, =1{kibibyte} other{kibibytes}}' => '{nFormatted} {n, plural, =1{kibibyte} other{kibibytes}}',
'{nFormatted} {n, plural, =1{kilobyte} other{kilobytes}}' => '{nFormatted} {n, plural, =1{kilobyte} other{kilobytes}}',
'{nFormatted} {n, plural, =1{mebibyte} other{mebibytes}}' => '{nFormatted} {n, plural, =1{mebibyte} other{mebibytes}}',
'{nFormatted} {n, plural, =1{megabyte} other{megabytes}}' => '{nFormatted} {n, plural, =1{megabyte} other{megabytes}}',
'{nFormatted} {n, plural, =1{pebibyte} other{pebibytes}}' => '{nFormatted} {n, plural, =1{pebibyte} other{pebibytes}}',
'{nFormatted} {n, plural, =1{petabyte} other{petabytes}}' => '{nFormatted} {n, plural, =1{petabyte} other{petabytes}}',
'{nFormatted} {n, plural, =1{tebibyte} other{tebibytes}}' => '{nFormatted} {n, plural, =1{tebibyte} other{tebibytes}}',
'{nFormatted} {n, plural, =1{terabyte} other{terabytes}}' => '{nFormatted} {n, plural, =1{terabyte} other{terabytes}}',
'No help for unknown command "{command}".' => 'Δεν υπάρχει βοήθεια για την άγνωστη εντολή "{command}".',
'No help for unknown sub-command "{command}".' => 'Δεν υπάρχει βοήθεια για την άγνωστη υπό-εντολή "{command}".',
'Unknown command "{command}".' => 'Άγνωστη εντολή "{command}".',
'(not set)' => '(μη ορισμένο)',
'An internal server error occurred.' => 'Σφάλμα διακομιστή.',
'An internal server error occurred.' => 'Υπήρξε ένα εσωτερικό σφάλμα του διακομιστή.',
'Delete' => 'Διαγραφή',
'Error' => 'Σφάλμα',
'File upload failed.' => 'Η μεταφόρτωση απέτυχε.',
'Home' => 'Αρχική',
'Invalid data received for parameter "{param}".' => 'Μη έγκυρα δεδομένα για την παράμετρο "{param}".',
'Login Required' => 'Απαιτείται είσοδος',
'Missing required arguments: {params}' => 'Απουσιάζουν απαραίτητες επιλογές: {params}',
'Missing required arguments: {params}' => 'Απουσιάζουν απαραίτητα ορίσματα: {params}',
'Missing required parameters: {params}' => 'Απουσιάζουν απαραίτητες παράμετροι: {params}',
'No' => 'Όχι',
'No help for unknown command "{command}".' => 'Δεν υπάρχει τεκμηρίωση για την εντολή "{command}".',
'No help for unknown sub-command "{command}".' => 'Δεν υπάρχει τεκμηρίωση για την υπό-εντολή "{command}".',
'No results found.' => 'Δεν βρέθηκαν αποτελέσματα.',
'No results found.' => 'Δε βρέθηκαν αποτελέσματα.',
'Only files with these extensions are allowed: {extensions}.' => 'Επιτρέπονται αρχεία μόνο με καταλήξεις: {extensions}.',
'Page not found.' => 'Η σελίδα δεν βρέθηκε.',
'Page not found.' => 'Η σελίδα δε βρέθηκε.',
'Please fix the following errors:' => 'Παρακαλώ διορθώστε τα παρακάτω σφάλματα:',
'Please upload a file.' => 'Παρακαλώ μεταφορτώστε ένα αρχείο.',
'Showing <b>{begin, number}-{end, number}</b> of <b>{totalCount, number}</b> {totalCount, plural, one{item} other{items}}.' => 'Παρουσιάζονται <b>{begin, number}-{end, number}</b> από <b>{totalCount, number}</b>.',
'Showing <b>{begin, number}-{end, number}</b> of <b>{totalCount, number}</b> {totalCount, plural, one{item} other{items}}.' => 'Εμφανίζονται <b>{begin, number}-{end, number}</b> από <b>{totalCount, number}</b>.',
'The file "{file}" is not an image.' => 'Το αρχείο «{file}» δεν είναι εικόνα.',
'The file "{file}" is too big. Its size cannot exceed {limit, number} {limit, plural, one{byte} other{bytes}}.' => 'Το αρχείο «{file}» είναι πολύ μεγάλο . Το μέγεθος του δεν μπορεί να είναι πάνω από {limit, number} {limit, plural, one{byte} other{bytes}}.',
'The file "{file}" is too small. Its size cannot be smaller than {limit, number} {limit, plural, one{byte} other{bytes}}.' => 'Το αρχείο «{file}» είναι πολύ μικρό. Το μέγεθος του δεν μπορεί να είναι μικρότερο από {limit, number} {limit, plural, one{byte} few{bytes} many{bytes} other{bytes}}.',
'The format of {attribute} is invalid.' => 'Ο τύπος του «{attribute}» δεν είναι έγκυρος.',
'The image "{file}" is too large. The height cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Το αρχείο «{file}» είναι πολύ μεγάλο. Το ύψος δεν μπορεί να είναι μεγαλύτερο από {limit, number} {limit, plural, one{pixel} few{pixels} many{pixels} other{pixels}}.',
'The image "{file}" is too large. The width cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Το αρχείο «{file}» είναι πολύ μεγάλο. Το πλάτος δεν μπορεί να είναι μεγαλύτερο από {limit, number} {limit, plural, one{pixel} few{pixels} many{pixels} other{pixels}}.',
'The image "{file}" is too small. The height cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Το αρχείο «{file}» είναι πολύ μικρό. To ύψος δεν μπορεί να είναι μικρότερο από {limit, number} {limit, plural, one{pixel} few{pixels} many{pixels} other{pixels}}.',
'The image "{file}" is too small. The width cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Το αρχείο «{file}» είναι πολύ μικρό. Το πλάτος του δεν μπορεί να είναι μικρότερο από {limit, number} {limit, plural, one{pixel} few{pixels} many{pixels} other{pixels}}.',
'The file "{file}" is too big. Its size cannot exceed {limit, number} {limit, plural, one{byte} other{bytes}}.' => 'Το αρχείο «{file}» είναι πολύ μεγάλο . Το μέγεθός του δεν μπορεί να είναι πάνω από {limit, number} {limit, plural, one{byte} other{bytes}}.',
'The file "{file}" is too small. Its size cannot be smaller than {limit, number} {limit, plural, one{byte} other{bytes}}.' => 'Το αρχείο «{file}» είναι πολύ μικρό. Το μέγεθός του δεν μπορεί να είναι μικρότερο από {limit, number} {limit, plural, one{byte} few{bytes} many{bytes} other{bytes}}.',
'The format of {attribute} is invalid.' => 'Η μορφή του «{attribute}» δεν είναι έγκυρη.',
'The image "{file}" is too large. The height cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Η εικόνα «{file}» είναι πολύ μεγάλη. Το ύψος δεν μπορεί να είναι μεγαλύτερο από {limit, number} {limit, plural, one{pixel} few{pixels} many{pixels} other{pixels}}.',
'The image "{file}" is too large. The width cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Η εικόνα «{file}» είναι πολύ μεγάλη. Το πλάτος δεν μπορεί να είναι μεγαλύτερο από {limit, number} {limit, plural, one{pixel} few{pixels} many{pixels} other{pixels}}.',
'The image "{file}" is too small. The height cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Η εικόνα «{file}» είναι πολύ μικρή. To ύψος δεν μπορεί να είναι μικρότερο από {limit, number} {limit, plural, one{pixel} few{pixels} many{pixels} other{pixels}}.',
'The image "{file}" is too small. The width cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.' => 'Η εικόνα «{file}» είναι πολύ μικρή. Το πλάτος του δεν μπορεί να είναι μικρότερο από {limit, number} {limit, plural, one{pixel} few{pixels} many{pixels} other{pixels}}.',
'The verification code is incorrect.' => 'Ο κωδικός επαλήθευσης είναι εσφαλμένος.',
'Total <b>{count, number}</b> {count, plural, one{item} other{items}}.' => 'Συνολικά <b>{count, number}</b> {count, plural, one{αντικείμενο} few{αντικείμενα} many{αντικείμενα} other{αντικείμενα}}.',
'Unable to verify your data submission.' => 'Δεν ήταν δυνατή η επαλήθευση των απεσταλμένων δεδομένων.',
'Unknown command "{command}".' => 'Άγνωστη εντολή "{command}".',
'Unknown option: --{name}' => 'Άγνωστη επιλογή : --{name}',
'Unknown option: --{name}' => 'Άγνωστη επιλογή: --{name}',
'Update' => 'Ενημέρωση',
'View' => 'Προβολή',
'Yes' => 'Ναι',
'You are not allowed to perform this action.' => 'Δεν επιτρέπεται να εκτελέσετε αυτή τη δράση.',
'You can upload at most {limit, number} {limit, plural, one{file} other{files}}.' => 'Μπορείτε να μεταφορτώσετε το πολύ {limit, number} {limit, plural, one{αρχείο} few{αρχεία} many{αρχεία} other{αρχεία}}.',
'You are not allowed to perform this action.' => 'Δεν επιτρέπεται να εκτελέσετε αυτή την ενέργεια.',
'You can upload at most {limit, number} {limit, plural, one{file} other{files}}.' => 'Μπορείτε να ανεβάσετε το πολύ {limit, number} {limit, plural, one{αρχείο} few{αρχεία} many{αρχεία} other{αρχεία}}.',
'the input value' => 'η τιμή εισόδου',
'{attribute} "{value}" has already been taken.' => '{attribute} «{value}» έχει ήδη καταχωρηθεί.',
'{attribute} "{value}" has already been taken.' => 'Το {attribute} «{value}» έχει ήδη καταχωρηθεί.',
'{attribute} cannot be blank.' => 'Το «{attribute}» δεν μπορεί να είναι κενό.',
'{attribute} is invalid.' => 'Το «{attribute}» δεν είναι έγκυρο.',
'{attribute} is not a valid URL.' => 'Το «{attribute}» δεν είναι έγκυρο URL.',
'{attribute} is not a valid email address.' => 'Η διεύθυνση email «{attribute}» δεν είναι έγκυρη .',
'{attribute} is not a valid URL.' => 'Το «{attribute}» δεν είναι έγκυρη διεύθυνση URL.',
'{attribute} is not a valid email address.' => 'Η διεύθυνση email «{attribute}» δεν είναι έγκυρη.',
'{attribute} must be "{requiredValue}".' => 'Το «{attribute}» πρέπει να είναι «{requiredValue}».',
'{attribute} must be a number.' => 'Το «{attribute}» πρέπει να είναι αριθμός.',
'{attribute} must be a string.' => 'Το «{attribute}» πρέπει να είναι συμβολοσειρά.',
@ -69,10 +107,10 @@ return [
'{attribute} must be greater than or equal to "{compareValue}".' => 'Το «{attribute}» πρέπει να είναι μεγαλύτερο ή ίσο με «{compareValue}».',
'{attribute} must be less than "{compareValue}".' => 'Το «{attribute}» πρέπει να είναι μικρότερο από «{compareValue}».',
'{attribute} must be less than or equal to "{compareValue}".' => 'Το «{attribute}» πρέπει να είναι μικρότερο ή ίσο με «{compareValue}».',
'{attribute} must be no greater than {max}.' => 'Το «{attribute}» πρέπει να μην ξεπερνά το {max}.',
'{attribute} must be no less than {min}.' => 'Το «{attribute}» πρέπει να μην είναι λιγότερο από {min}.',
'{attribute} must be no greater than {max}.' => 'Το «{attribute}» δεν πρέπει να ξεπερνά το {max}.',
'{attribute} must be no less than {min}.' => 'Το «{attribute}» δεν πρέπει να είναι λιγότερο από {min}.',
'{attribute} must be repeated exactly.' => 'Το «{attribute}» πρέπει να επαναληφθεί ακριβώς.',
'{attribute} must not be equal to "{compareValue}".' => 'Το «{attribute}» πρέπει να μην είναι ίσο με «{compareValue}».',
'{attribute} must not be equal to "{compareValue}".' => 'Το «{attribute}» δεν πρέπει να είναι ίσο με «{compareValue}».',
'{attribute} should contain at least {min, number} {min, plural, one{character} other{characters}}.' => 'Το «{attribute}» πρέπει να περιέχει το λιγότερο {min, number} {min, plural, one{χαρακτήρα} few{χαρακτήρες} many{χαρακτήρες} other{χαρακτήρες}}.',
'{attribute} should contain at most {max, number} {max, plural, one{character} other{characters}}.' => 'Το «{attribute}» πρέπει να περιέχει το πολύ {max, number} {max, plural, one{χαρακτήρα} few{χαρακτήρες} many{χαρακτήρες} other{χαρακτήρες}}.',
'{attribute} should contain {length, number} {length, plural, one{character} other{characters}}.' => 'Το «{attribute}» πρέπει να περιέχει {length, number} {length, plural, one{χαρακτήρα} few{χαρακτήρες} many{χαρακτήρες} other{χαρακτήρες}}.',

2
framework/views/errorHandler/callStackItem.php

@ -17,7 +17,7 @@
<span class="text"><?php if ($file !== null) echo 'in ' . $handler->htmlEncode($file); ?></span>
<?php if ($method !== null): ?>
<span class="call">
<?php if ($file !== null) echo '&ndash;' ?>
<?php if ($file !== null) echo '&ndash;'; ?>
<?= ($class !== null ? $handler->addTypeLinks("$class::$method") : $handler->htmlEncode($method)) . '(' . $handler->argumentsToString($args) . ')' ?>
</span>
<?php endif; ?>

4
framework/web/DbSession.php

@ -65,6 +65,10 @@ class DbSession extends Session
*
* When using DbSession in a production server, we recommend you create a DB index for the 'expire'
* column in the session table to improve the performance.
*
* Note that according to the php.ini setting of `session.hash_function`, you may need to adjust
* the length of the `id` column. For example, if `session.hash_function=sha256`, you should use
* length 64 instead of 40.
*/
public $sessionTable = '{{%session}}';

98
tests/unit/extensions/authclient/BaseClientTest.php

@ -55,25 +55,99 @@ class BaseClientTest extends TestCase
}
/**
* Data provider for [[testNormalizeUserAttributes()]]
* @return array test data
*/
public function dataProviderNormalizeUserAttributes()
{
return [
[
[
'name' => 'raw/name',
'email' => 'raw/email',
],
[
'raw/name' => 'name value',
'raw/email' => 'email value',
],
[
'name' => 'name value',
'email' => 'email value',
],
],
[
[
'name' => function ($attributes) {
return $attributes['firstName'] . ' ' . $attributes['lastName'];
},
],
[
'firstName' => 'John',
'lastName' => 'Smith',
],
[
'name' => 'John Smith',
],
],
[
[
'email' => ['emails', 'prime'],
],
[
'emails' => [
'prime' => 'some@email.com'
],
],
[
'email' => 'some@email.com',
],
],
[
[
'email' => ['emails', 0],
'secondaryEmail' => ['emails', 1],
],
[
'emails' => [
'some@email.com',
],
],
[
'email' => 'some@email.com',
],
],
[
[
'name' => 'file_get_contents',
],
[
'file_get_contents' => 'value',
],
[
'name' => 'value',
],
],
];
}
/**
* @dataProvider dataProviderNormalizeUserAttributes
*
* @depends testSetGet
*
* @param array $normalizeUserAttributeMap
* @param array $rawUserAttributes
* @param array $expectedNormalizedUserAttributes
*/
public function testNormalizeUserAttributes()
public function testNormalizeUserAttributes($normalizeUserAttributeMap, $rawUserAttributes, $expectedNormalizedUserAttributes)
{
$client = new Client();
$normalizeUserAttributeMap = [
'raw/name' => 'name',
'raw/email' => 'email',
];
$client->setNormalizeUserAttributeMap($normalizeUserAttributeMap);
$rawUserAttributes = [
'raw/name' => 'name value',
'raw/email' => 'email value',
];
$client->setUserAttributes($rawUserAttributes);
$normalizedUserAttributes = $client->getUserAttributes();
$expectedNormalizedUserAttributes = array_combine(array_keys($normalizeUserAttributeMap), array_values($rawUserAttributes));
$this->assertEquals($expectedNormalizedUserAttributes, $normalizedUserAttributes);
$this->assertEquals(array_merge($rawUserAttributes, $expectedNormalizedUserAttributes), $normalizedUserAttributes);
}
}

38
tests/unit/extensions/mongodb/ConnectionTest.php

@ -61,7 +61,45 @@ class ConnectionTest extends MongoDbTestCase
}
/**
* Data provider for [[testFetchDefaultDatabaseName()]]
* @return array test data
*/
public function dataProviderFetchDefaultDatabaseName()
{
return [
[
'mongodb://travis:test@localhost:27017/dbname',
'dbname',
],
[
'mongodb://travis:test@localhost:27017/dbname?replicaSet=test&connectTimeoutMS=300000',
'dbname',
],
];
}
/**
* @dataProvider dataProviderFetchDefaultDatabaseName
*
* @param string $dsn
* @param string $databaseName
*/
public function testFetchDefaultDatabaseName($dsn, $databaseName)
{
$connection = new Connection();
$connection->dsn = $dsn;
$reflection = new \ReflectionObject($connection);
$method = $reflection->getMethod('fetchDefaultDatabaseName');
$method->setAccessible(true);
$method->invoke($connection);
$this->assertEquals($databaseName, $connection->defaultDatabaseName);
}
/**
* @depends testGetDatabase
* @depends testFetchDefaultDatabaseName
*/
public function testGetDefaultDatabase()
{

16
tests/unit/extensions/sphinx/QueryTest.php

@ -132,6 +132,22 @@ class QueryTest extends SphinxTestCase
$this->assertEquals(['team', 'company', 'age'], $query->groupBy);
}
public function testHaving()
{
$query = new Query;
$query->having('id = :id', [':id' => 1]);
$this->assertEquals('id = :id', $query->having);
$this->assertEquals([':id' => 1], $query->params);
$query->andHaving('name = :name', [':name' => 'something']);
$this->assertEquals(['and', 'id = :id', 'name = :name'], $query->having);
$this->assertEquals([':id' => 1, ':name' => 'something'], $query->params);
$query->orHaving('age = :age', [':age' => '30']);
$this->assertEquals(['or', ['and', 'id = :id', 'name = :name'], 'age = :age'], $query->having);
$this->assertEquals([':id' => 1, ':name' => 'something', ':age' => '30'], $query->params);
}
public function testOrder()
{
$query = new Query;

137
tests/unit/framework/web/UserTest.php

@ -0,0 +1,137 @@
<?php
namespace yii\web;
/**
* Mock for the time() function for web classes
* @return int
*/
function time()
{
return \yiiunit\framework\web\UserTest::$time ?: \time();
}
namespace yiiunit\framework\web;
use yii\base\NotSupportedException;
use yii\base\Component;
use yii\rbac\PhpManager;
use yii\web\IdentityInterface;
use yii\web\UrlManager;
use yii\web\UrlRule;
use yii\web\Request;
use Yii;
use yiiunit\TestCase;
/**
* @group web
*/
class UserTest extends TestCase
{
/**
* @var integer virtual time to be returned by mocked time() function.
* Null means normal time() behavior.
*/
public static $time;
protected function tearDown()
{
Yii::$app->session->removeAll();
static::$time = null;
parent::tearDown();
}
public function testLoginExpires()
{
if (getenv('TRAVIS') == 'true') {
$this->markTestSkipped('Can not reliably test this on travis-ci.');
}
$appConfig = [
'components' => [
'user' => [
'identityClass' => UserIdentity::className(),
'authTimeout' => 10,
],
'authManager' => [
'class' => PhpManager::className(),
'itemFile' => '@runtime/user_test_rbac_items.php',
'assignmentFile' => '@runtime/user_test_rbac_assignments.php',
'ruleFile' => '@runtime/user_test_rbac_rules.php',
]
],
];
$this->mockWebApplication($appConfig);
$am = Yii::$app->authManager;
$am->removeAll();
$am->add($role = $am->createPermission('rUser'));
$am->add($perm = $am->createPermission('doSomething'));
$am->addChild($role, $perm);
$am->assign($role, 'user1');
Yii::$app->session->removeAll();
static::$time = \time();
Yii::$app->user->login(UserIdentity::findIdentity('user1'));
// print_r(Yii::$app->session);
// print_r($_SESSION);
$this->mockWebApplication($appConfig);
$this->assertFalse(Yii::$app->user->isGuest);
$this->assertTrue(Yii::$app->user->can('doSomething'));
static::$time += 5;
$this->mockWebApplication($appConfig);
$this->assertFalse(Yii::$app->user->isGuest);
$this->assertTrue(Yii::$app->user->can('doSomething'));
static::$time += 11;
$this->mockWebApplication($appConfig);
$this->assertTrue(Yii::$app->user->isGuest);
$this->assertFalse(Yii::$app->user->can('doSomething'));
}
}
class UserIdentity extends Component implements IdentityInterface
{
private static $ids = [
'user1',
'user2',
'user3',
];
private $_id;
public static function findIdentity($id)
{
if (in_array($id, static::$ids)) {
$identitiy = new static();
$identitiy->_id = $id;
return $identitiy;
}
}
public static function findIdentityByAccessToken($token, $type = null)
{
throw new NotSupportedException();
}
public function getId()
{
return $this->_id;
}
public function getAuthKey()
{
throw new NotSupportedException();
}
public function validateAuthKey($authKey)
{
throw new NotSupportedException();
}
}
Loading…
Cancel
Save