Commit 28fd9167 by pana1990

Replace 'p. ej.' with 'ej.' [skip ci]

parent 9510d6d8
Eventos
=======
Los eventos permiten inyectar código dentro de otro código existente en ciertos puntos de ejecución. Se pueden adjuntar
código personalizado a un evento, cuando se lance (triggered), el código se ejecutará automáticamente. Por ejemplo, un
objeto `mailer` puede lanzar el evento `messageSent` cuando se envía un mensaje correctamente. Si se quiere rastrear
Los eventos permiten inyectar código dentro de otro código existente en ciertos puntos de ejecución. Se pueden adjuntar
código personalizado a un evento, cuando se lance (triggered), el código se ejecutará automáticamente. Por ejemplo, un
objeto `mailer` puede lanzar el evento `messageSent` cuando se envía un mensaje correctamente. Si se quiere rastrear
el correcto envío del mensaje, se puede, simplemente, añadir un código de seguimiento al evento `messageSent`.
Yii introduce una clase base [[yii\base\Component]] para soportar eventos. Si una clase necesita lanzar un evento,
Yii introduce una clase base [[yii\base\Component]] para soportar eventos. Si una clase necesita lanzar un evento,
este debe extender a [[yii\base\Component]] o a una clase hija.
Gestor de Eventos <a name="event-handlers"></a>
-----------------
Un gestor de eventos es una
[llamada de retorno PHP (PHP callback)](http://php.net/manual/es/language.types.callable.php) que se ejecuta cuando se
Un gestor de eventos es una
[llamada de retorno PHP (PHP callback)](http://php.net/manual/es/language.types.callable.php) que se ejecuta cuando se
lanza el evento al que corresponde. Se puede usar cualquier llamada de retorno de las enumeradas a continuación:
- una función de PHP global especificada como una cadena de texto (sin paréntesis), p. ej. `'trim'`;
- un método de objeto especificado como un array de un objeto y un nombre de método como una cadena de texto
(sin paréntesis), p. ej. `[$object, 'methodNAme']`;
- un método de clase estático especificado como un array de un nombre de clase y un método como una cadena de texto
(sin paréntesis), p. ej. `[$class, 'methodName']`;
- una función anónima, p. ej. `function ($event) { ... }`.
- una función de PHP global especificada como una cadena de texto (sin paréntesis), ej. `'trim'`;
- un método de objeto especificado como un array de un objeto y un nombre de método como una cadena de texto
(sin paréntesis), ej. `[$object, 'methodNAme']`;
- un método de clase estático especificado como un array de un nombre de clase y un método como una cadena de texto
(sin paréntesis), ej. `[$class, 'methodName']`;
- una función anónima, ej. `function ($event) { ... }`.
La firma de un gestor de eventos es:
......@@ -31,12 +31,12 @@ function ($event) {
}
```
Un gestor de eventos puede obtener la siguiente información acerca de un evento ya sucedido mediante el parámetro
Un gestor de eventos puede obtener la siguiente información acerca de un evento ya sucedido mediante el parámetro
`$event`:
- [[yii\base\Event::name|event name]]
- [[yii\base\Event::sender|event sender]]: el objeto desde el que se ha ejecutado `trigger()`
- [[yii\base\Event::data|custom data]]: los datos que se proporcionan al adjuntar el gestor de eventos
- [[yii\base\Event::data|custom data]]: los datos que se proporcionan al adjuntar el gestor de eventos
(se explicará más adelante)
Añadir Gestores de Eventos <a name="attaching-event-handlers"></a>
......@@ -62,16 +62,16 @@ $foo->on(Foo::EVENT_HELLO, function ($event) {
});
```
También se pueden adjuntar gestores de eventos mediante [configuraciones](concept-configurations.md). Se pueden
También se pueden adjuntar gestores de eventos mediante [configuraciones](concept-configurations.md). Se pueden
encontrar más de talles en la sección [Configuraciones](concept-configurations.md#configuration-format).
Cuando se adjunta un gestor de eventos, se pueden proporcionar datos adicionales como tercer parámetro de
[[yii\base\Component::on()]]. El gestor podrá acceder a los datos cuando se lance el evento y se ejecute el gestor.
Cuando se adjunta un gestor de eventos, se pueden proporcionar datos adicionales como tercer parámetro de
[[yii\base\Component::on()]]. El gestor podrá acceder a los datos cuando se lance el evento y se ejecute el gestor.
Por ejemplo:
```php
```php
// El siguiente código muestra "abc" cuando se lanza el evento
// ya que $event->data contiene los datos enviados en el tercer parámetro de "on"
// ya que $event->data contiene los datos enviados en el tercer parámetro de "on"
$foo->on(Foo::EVENT_HELLO, 'function_name', 'abc');
function function_name($event) {
......@@ -82,8 +82,8 @@ function function_name($event) {
Ordenación de Gestores de Eventos
---------------------------------
Se puede adjuntar uno o más gestores a un único evento. Cuando se lanza un evento, se ejecutarán los gestores adjuntos
en el orden que se hayan añadido al evento. Si un gestor necesita parar la invocación de los gestores que le siguen,
Se puede adjuntar uno o más gestores a un único evento. Cuando se lanza un evento, se ejecutarán los gestores adjuntos
en el orden que se hayan añadido al evento. Si un gestor necesita parar la invocación de los gestores que le siguen,
se puede establecer la propiedad [[yii\base\Event::handled]] del parámetro `$event` para que sea `true`:
```php
......@@ -92,9 +92,9 @@ $foo->on(Foo::EVENT_HELLO, function ($event) {
});
```
De forma predeterminada, cada nuevo gestor añadido se pone a la cola de la lista de gestores del evento. Por lo tanto,
el gestor se ejecutará en el último lugar cuando se lance el evento. Para insertar un nuevo gestor al principio de la
cola de gestores para que sea ejecutado primero, se debe llamar a [[yii\base\Component::on()]], pasando al cuarto
De forma predeterminada, cada nuevo gestor añadido se pone a la cola de la lista de gestores del evento. Por lo tanto,
el gestor se ejecutará en el último lugar cuando se lance el evento. Para insertar un nuevo gestor al principio de la
cola de gestores para que sea ejecutado primero, se debe llamar a [[yii\base\Component::on()]], pasando al cuarto
parámetro `$append` el valor `false`:
```php
......@@ -106,8 +106,8 @@ $foo->on(Foo::EVENT_HELLO, function ($event) {
Lanzamiento de Eventos <a name="triggering-events"></a>
----------------------
Los eventos se lanzan llamando al método [[yii\base\Component::trigger()]]. El método requiere un *nombre de evento*,
y de forma opcional un objeto de evento que describa los parámetros que se enviarán a los gestores de eventos. Por
Los eventos se lanzan llamando al método [[yii\base\Component::trigger()]]. El método requiere un *nombre de evento*,
y de forma opcional un objeto de evento que describa los parámetros que se enviarán a los gestores de eventos. Por
ejemplo:
```php
......@@ -129,15 +129,15 @@ class Foo extends Component
Con el código anterior, cada llamada a `bar()` lanzará un evento llamado `hello`
> Consejo: Se recomienda usar las constantes de clase para representar nombres de eventos. En el anterior ejemplo, la
constante `EVENT_HELLO` representa el evento `hello`. Este enfoque proporciona tres beneficios. Primero, previene
errores tipográficos. Segundo, puede hacer que los IDEs reconozcan los eventos en las funciones de auto-completado.
> Consejo: Se recomienda usar las constantes de clase para representar nombres de eventos. En el anterior ejemplo, la
constante `EVENT_HELLO` representa el evento `hello`. Este enfoque proporciona tres beneficios. Primero, previene
errores tipográficos. Segundo, puede hacer que los IDEs reconozcan los eventos en las funciones de auto-completado.
Tercero, se puede ver que eventos soporta una clase simplemente revisando la declaración de constantes.
A veces cuando se lanza un evento se puede querer pasar información adicional al gestor de eventos. Por ejemplo, un
`mailer` puede querer enviar la información del mensaje para que los gestores del evento `messageSent` para que los
gestores puedan saber las particularidades del mensaje enviado. Para hacerlo, se puede proporcionar un objeto de tipo
evento como segundo parámetro al método [[yii\base\Component::trigger()]]. El objeto de tipo evento debe ser una
A veces cuando se lanza un evento se puede querer pasar información adicional al gestor de eventos. Por ejemplo, un
`mailer` puede querer enviar la información del mensaje para que los gestores del evento `messageSent` para que los
gestores puedan saber las particularidades del mensaje enviado. Para hacerlo, se puede proporcionar un objeto de tipo
evento como segundo parámetro al método [[yii\base\Component::trigger()]]. El objeto de tipo evento debe ser una
instancia de la clase [[yii\base\Event]] o de sus hijas. Por ejemplo:
```php
......@@ -187,11 +187,11 @@ $foo->off(Foo::EVENT_HELLO, ['app\components\Bar', 'methodName']);
$foo->off(Foo::EVENT_HELLO, $anonymousFunction);
```
Tenga en cuenta que en general no se debe intentar desadjuntar las funciones anónimas a no ser que se almacene donde
se ha adjuntado al evento. En el anterior ejemplo, se asume que la función anónima se almacena como variable
Tenga en cuenta que en general no se debe intentar desadjuntar las funciones anónimas a no ser que se almacene donde
se ha adjuntado al evento. En el anterior ejemplo, se asume que la función anónima se almacena como variable
`$anonymousFunction`.
Para desadjuntar TODOS los gestores de un evento, se puede llamar [[yii\base\Component::off()]] sin el segundo
Para desadjuntar TODOS los gestores de un evento, se puede llamar [[yii\base\Component::off()]] sin el segundo
parámetro:
```php
......@@ -201,14 +201,14 @@ $foo->off(Foo::EVENT_HELLO);
Nivel de Clase (Class-Level) Gestores de Eventos <a name="class-level-event-handlers"></a>
------------------------------------------------
En las subsecciones anteriores se ha descrito como adjuntar un gestor a un evento a *nivel de instancia*. A veces, se
puede querer que un gestor responda todos los eventos de *todos* las instancias de una clase en lugar de una instancia
especifica. En lugar de adjuntar un gestor de eventos a una instancia, se puede adjuntar un gestor a *nivel de clase*
En las subsecciones anteriores se ha descrito como adjuntar un gestor a un evento a *nivel de instancia*. A veces, se
puede querer que un gestor responda todos los eventos de *todos* las instancias de una clase en lugar de una instancia
especifica. En lugar de adjuntar un gestor de eventos a una instancia, se puede adjuntar un gestor a *nivel de clase*
llamando al método estático [[yii\base\Event::on()]].
Por ejemplo, un objeto de tipo [Active Record](db-active-record.md) lanzará un evento
[[yii\db\BaseActiveRecord::EVENT_AFTER_INSERT|EVENT_AFTER_INSERT]] cada vez que inserte un nuevo registro en la base
de datos. Para poder registrar las inserciones efectuadas por *todos* los objetos
Por ejemplo, un objeto de tipo [Active Record](db-active-record.md) lanzará un evento
[[yii\db\BaseActiveRecord::EVENT_AFTER_INSERT|EVENT_AFTER_INSERT]] cada vez que inserte un nuevo registro en la base
de datos. Para poder registrar las inserciones efectuadas por *todos* los objetos
[Active Record](db-active-record.md), se puede usar el siguiente código:
```php
......@@ -221,15 +221,15 @@ Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function
});
```
Se invocará al gestor de eventos cada vez que una instancia de [[yii\db\ActiveRecord|ActiveRecord]], o de uno de sus
clases hijas, lance un evento de tipo [[yii\db\BaseActiveRecord::EVENT_AFTER_INSERT|EVENT_AFTER_INSERT]]. Se puede
Se invocará al gestor de eventos cada vez que una instancia de [[yii\db\ActiveRecord|ActiveRecord]], o de uno de sus
clases hijas, lance un evento de tipo [[yii\db\BaseActiveRecord::EVENT_AFTER_INSERT|EVENT_AFTER_INSERT]]. Se puede
obtener el objeto que ha lanzado el evento mediante `$event->sender` en el gestor.
Cuando un objeto lanza un evento, primero llamará los gestores a nivel de instancia, y a continuación los gestores a
Cuando un objeto lanza un evento, primero llamará los gestores a nivel de instancia, y a continuación los gestores a
nivel de clase.
Se puede lanzar un evento de tipo *nivel de clase* llamando al método estático [[yii\base\Event::trigger()]]. Un
evento de nivel de clase no se asocia a un objeto en particular. Como resultado, esto provocará solamente la
Se puede lanzar un evento de tipo *nivel de clase* llamando al método estático [[yii\base\Event::trigger()]]. Un
evento de nivel de clase no se asocia a un objeto en particular. Como resultado, esto provocará solamente la
invocación de los gestores de eventos a nivel de clase.
```php
......@@ -242,11 +242,11 @@ Event::on(Foo::className(), Foo::EVENT_HELLO, function ($event) {
Event::trigger(Foo::className(), Foo::EVENT_HELLO);
```
Tenga en cuenta que en este caso, el `$event->sender` hace referencia al nombre de la clase que lanza el evento en
Tenga en cuenta que en este caso, el `$event->sender` hace referencia al nombre de la clase que lanza el evento en
lugar de a la instancia del objeto.
> Nota: Debido a que los gestores a nivel de clase responderán a los eventos lanzados por cualquier instancia de la
clase, o cualquier clase hija, se debe usar con cuidado, especialmente en las clases de bajo nivel (low-level), tales
> Nota: Debido a que los gestores a nivel de clase responderán a los eventos lanzados por cualquier instancia de la
clase, o cualquier clase hija, se debe usar con cuidado, especialmente en las clases de bajo nivel (low-level), tales
como [[yii\base\Object]].
Para desadjuntar un gestor de eventos a nivel de clase, se tiene que llamar a [[yii\base\Event::off()]]. Por ejemplo:
......@@ -262,12 +262,12 @@ Event::off(Foo::className(), Foo::EVENT_HELLO);
Eventos Globales <a name="global-events"></a>
----------------
Yii soporta los llamados *eventos globales*, que en realidad es un truco basado en el gestor de eventos descrito
anteriormente. El evento global requiere un Singleton globalmente accesible, tal como la instancia de
Yii soporta los llamados *eventos globales*, que en realidad es un truco basado en el gestor de eventos descrito
anteriormente. El evento global requiere un Singleton globalmente accesible, tal como la instancia de
[aplicación](structure-applications.md) en si misma.
Para crear un evento global, un evento remitente (event sender) llama al método `trigger()` del Singleton para lanzar
el evento, en lugar de llamar al propio método `trigger()` del remitente. De forma similar, los gestores de eventos se
Para crear un evento global, un evento remitente (event sender) llama al método `trigger()` del Singleton para lanzar
el evento, en lugar de llamar al propio método `trigger()` del remitente. De forma similar, los gestores de eventos se
adjuntan al evento del Singleton. Por ejemplo:
```php
......@@ -282,10 +282,10 @@ Yii::$app->on('bar', function ($event) {
Yii::$app->trigger('bar', new Event(['sender' => new Foo]));
```
Un beneficio de usar eventos globales es que no se necesita un objeto cuando se adjuntan gestores a un evento para que
sean lanzados por el objeto. En su lugar, los gestores adjuntos y el lanzamiento de eventos se efectúan en el
Singleton (p. ej. la instancia de la aplicación).
Un beneficio de usar eventos globales es que no se necesita un objeto cuando se adjuntan gestores a un evento para que
sean lanzados por el objeto. En su lugar, los gestores adjuntos y el lanzamiento de eventos se efectúan en el
Singleton (ej. la instancia de la aplicación).
Sin embargo, debido a que los `namespaces` de los eventos globales son compartidos por todas partes, se les deben
asignar nombres bien pensados, como puede ser la introducción de algún `namespace`
(p. ej. "frontend.mail.sent", "backend.mail.sent").
Sin embargo, debido a que los `namespaces` de los eventos globales son compartidos por todas partes, se les deben
asignar nombres bien pensados, como puede ser la introducción de algún `namespace`
(ej. "frontend.mail.sent", "backend.mail.sent").
Propiedades
===========
En PHP, las variables miembro de clases también llamadas *propiedades*, son parte de la definición de la clase, y se
usan para representar el estado de una instancia de la clase (p. ej. para diferenciar una instancia de clase de otra).
A la práctica, a menudo, se puede querer gestionar la lectura o escritura de las propiedades de algunos momentos. Por
ejemplo, se puede querer eliminar los espacios en blanco (trim) de una cadena de texto cada vez que esta se asigne a
En PHP, las variables miembro de clases también llamadas *propiedades*, son parte de la definición de la clase, y se
usan para representar el estado de una instancia de la clase (ej. para diferenciar una instancia de clase de otra).
A la práctica, a menudo, se puede querer gestionar la lectura o escritura de las propiedades de algunos momentos. Por
ejemplo, se puede querer eliminar los espacios en blanco (trim) de una cadena de texto cada vez que esta se asigne a
una propiedad de tipo `label`. Se *podría* usar el siguiente código para realizar esta tarea:
```php
$object->label = trim($label);
```
La desventaja del código anterior es que se tendría que ejecutar `trim()` en todas las partes del código que pudieran
establecer la propiedad `label`. Si en el futuro, la propiedad `label` tiene que seguir otro funcionamiento, como por
ejemplo que la primera letra tiene que estar en mayúsculas, se tendrán que modificar todas las secciones de código que
asignen el valor a la propiedad `label`. La repetición de código conlleva a bugs, y es una practica que se tiene que
La desventaja del código anterior es que se tendría que ejecutar `trim()` en todas las partes del código que pudieran
establecer la propiedad `label`. Si en el futuro, la propiedad `label` tiene que seguir otro funcionamiento, como por
ejemplo que la primera letra tiene que estar en mayúsculas, se tendrán que modificar todas las secciones de código que
asignen el valor a la propiedad `label`. La repetición de código conlleva a bugs, y es una practica que se tiene que
evitar en la medida de lo posible.
Para solventar este problema, Yii introduce la clase base llamada [[yii\base\Object]] que da soporte a la definición
de propiedades basada en los métodos de clase *getter* y *setter*. Si una clase necesita más funcionalidad, debe
Para solventar este problema, Yii introduce la clase base llamada [[yii\base\Object]] que da soporte a la definición
de propiedades basada en los métodos de clase *getter* y *setter*. Si una clase necesita más funcionalidad, debe
extender a la clase [[yii\base\Object]] o a alguna de sus hijas.
> Información: Casi todas las clases del núcleo (core) en el framework Yii extienden a [[yii\base\Object]] o a una de
sus clases hijas. Esto significa que siempre que se encuentre un getter o un setter en una clase del núcleo, se
> Información: Casi todas las clases del núcleo (core) en el framework Yii extienden a [[yii\base\Object]] o a una de
sus clases hijas. Esto significa que siempre que se encuentre un getter o un setter en una clase del núcleo, se
puede utilizar como una propiedad.
Un método getter es un método cuyo nombre empieza por la palabra `get`: un metodo setter empieza por `set`. El nombre
añadido detrás del prefijo `get` o `set` define el nombre de la propiedad. Por ejemplo, un getter `getLabel()` y/o un
Un método getter es un método cuyo nombre empieza por la palabra `get`: un metodo setter empieza por `set`. El nombre
añadido detrás del prefijo `get` o `set` define el nombre de la propiedad. Por ejemplo, un getter `getLabel()` y/o un
setter `setLabel()` definen la propiedad `label`, como se muestra a continuación:
```php
......@@ -50,11 +50,11 @@ class Foo extends Object
}
```
(Para ser claros, los métodos getter y setter crean la propiedad `label`, que en este caso hace una referencia interna
(Para ser claros, los métodos getter y setter crean la propiedad `label`, que en este caso hace una referencia interna
al nombre de atributo privado `_label`.)
Las propiedades definidas por los getter y los setters se pueden usar como variables de clase miembro. La principal
diferencia radica en que cuando esta propiedad se lea, se ejecutará su correspondiente método getter; cuando se asigne
Las propiedades definidas por los getter y los setters se pueden usar como variables de clase miembro. La principal
diferencia radica en que cuando esta propiedad se lea, se ejecutará su correspondiente método getter; cuando se asigne
un valor a la propiedad, se ejecutará el correspondiente método setter. Por ejemplo:
```php
......@@ -65,24 +65,24 @@ $label = $object->label;
$object->label = 'abc';
```
Una propiedad definida por un getter sin un setter es de tipo *sólo lectura*. Si se intenta asignar un valor a esta
propiedad se producirá una excepción de tipo [[yii\base\InvalidCallException|InvalidCallException]]. Del mismo modo
que una propiedad definida con un setter pero sin getter será de tipo *sólo escritura*, cualquier intento de lectura
Una propiedad definida por un getter sin un setter es de tipo *sólo lectura*. Si se intenta asignar un valor a esta
propiedad se producirá una excepción de tipo [[yii\base\InvalidCallException|InvalidCallException]]. Del mismo modo
que una propiedad definida con un setter pero sin getter será de tipo *sólo escritura*, cualquier intento de lectura
de esta propiedad producirá una excepción. No es común tener variables de tipo sólo escritura.
Hay varias reglas especiales y limitaciones en las propiedades definidas mediante getters y setters:
* Los nombres de estas propiedades son *case-insensitive*. Por ejemplo, `$object->label` y `$object->Label` son la
* Los nombres de estas propiedades son *case-insensitive*. Por ejemplo, `$object->label` y `$object->Label` son la
misma. Esto se debe a que los nombres de los métodos en PHP son case-insensitive.
* Si el nombre de una propiedad de este tipo es igual al de una variable miembro de la clase, la segunda tendrá
prioridad. Por ejemplo, si la anterior clase `Foo` tiene la variable miembro `label`, entonces la asignación
* Si el nombre de una propiedad de este tipo es igual al de una variable miembro de la clase, la segunda tendrá
prioridad. Por ejemplo, si la anterior clase `Foo` tiene la variable miembro `label`, entonces la asignación
`$object->label = 'abc'` afectará a la *variable miembro* 'label'; no se ejecutará el método setter `setLabel()`.
* Estas variables no soportan la visibilidad. No hay diferencia en definir los métodos getter o setter en una
* Estas variables no soportan la visibilidad. No hay diferencia en definir los métodos getter o setter en una
propiedad public, protected, o private.
* Las propiedades sólo se pueden definir por getters y setters *no estáticos*. Los métodos estáticos no se tratarán de
* Las propiedades sólo se pueden definir por getters y setters *no estáticos*. Los métodos estáticos no se tratarán de
la misma manera.
Volviendo de nuevo al problema descrito al principio de la guía, en lugar de ejecutar `trim()` cada vez que se asigne
un valor a `label`, ahora `trim()` sólo necesita ser invocado dentro del setter `setLabel()`. I si se tiene que añadir
Volviendo de nuevo al problema descrito al principio de la guía, en lugar de ejecutar `trim()` cada vez que se asigne
un valor a `label`, ahora `trim()` sólo necesita ser invocado dentro del setter `setLabel()`. I si se tiene que añadir
un nuevo requerimiento, para que `label` empiece con una letra mayúscula, se puede modificar rápidamente el método `
setLabel()` sin tener que modificar más secciones de código. El cambio afectará a cada asignación de `label`.
\ No newline at end of file
......@@ -3,11 +3,11 @@
> Nota: Esta sección está en desarrollo.
Yii proporciona una capa de acceso básico a bases de datos como se describe en la sección
[Objetos de Acceso a Bases de Datos](db-dao.md). La capa de acceso a bases de datos proporciona un método de bajo
nivel (low-level) para interaccionar con la base de datos. Aunque a veces puede ser útil la escritura de sentencias
SQLs puras, en otras situaciones puede ser pesado y propenso a errores. Otra manera de tratar con bases de datos puede
ser el uso de Constructores de Consultas (Query Builder). El Constructor de Consultas proporciona un medio orientado a
Yii proporciona una capa de acceso básico a bases de datos como se describe en la sección
[Objetos de Acceso a Bases de Datos](db-dao.md). La capa de acceso a bases de datos proporciona un método de bajo
nivel (low-level) para interaccionar con la base de datos. Aunque a veces puede ser útil la escritura de sentencias
SQLs puras, en otras situaciones puede ser pesado y propenso a errores. Otra manera de tratar con bases de datos puede
ser el uso de Constructores de Consultas (Query Builder). El Constructor de Consultas proporciona un medio orientado a
objetos para generar las consultas que se ejecutarán.
Un uso típico de Constructor de Consultas puede ser el siguiente:
......@@ -36,12 +36,12 @@ $rows = $command->queryAll();
Métodos de Consulta
-------------------
Como se puede observar, primero se debe tratar con [[yii\db\Query]]. En realidad, `Query` sólo se encarga de
representar diversa información de la consulta. La lógica para generar la consulta se efectúa mediante
[[yii\db\QueryBuilder]] cuando se llama al método `createCommand()`, y la ejecución de la consulta la efectúa
Como se puede observar, primero se debe tratar con [[yii\db\Query]]. En realidad, `Query` sólo se encarga de
representar diversa información de la consulta. La lógica para generar la consulta se efectúa mediante
[[yii\db\QueryBuilder]] cuando se llama al método `createCommand()`, y la ejecución de la consulta la efectúa
[[yii\db\Command]].
Se ha establecido, por convenio, que [[yii\db\Query]] proporcione un conjunto de métodos de consulta comunes que
Se ha establecido, por convenio, que [[yii\db\Query]] proporcione un conjunto de métodos de consulta comunes que
construirán la consulta, la ejecutarán, y devolverán el resultado. Por ejemplo:
- [[yii\db\Query::all()|all()]]: construye la consulta, la ejecuta y devuelve todos los resultados en formato de array.
......@@ -49,14 +49,14 @@ construirán la consulta, la ejecutarán, y devolverán el resultado. Por ejempl
- [[yii\db\Query::column()|column()]]: devuelve la primera columna del resultado.
- [[yii\db\Query::scalar()|scalar()]]: devuelve la primera columna en la primera fila del resultado.
- [[yii\db\Query::exists()|exists()]]: devuelve un valor indicando si la el resultado devuelve algo.
- [[yii\db\Query::count()|count()]]: devuelve el resultado de la consulta `COUNT`. Otros métodos similares incluidos
son `sum($q)`, `average($q)`, `max($q)`, `min($q)`, que soportan las llamadas funciones de agregación. El parámetro
- [[yii\db\Query::count()|count()]]: devuelve el resultado de la consulta `COUNT`. Otros métodos similares incluidos
son `sum($q)`, `average($q)`, `max($q)`, `min($q)`, que soportan las llamadas funciones de agregación. El parámetro
`$q` es obligatorio en estos métodos y puede ser el nombre de la columna o expresión.
Construcción de Consultas
-------------------------
A continuación se explicará como construir una sentencia SQL que incluya varias clausulas. Para simplificarlo, usamos
A continuación se explicará como construir una sentencia SQL que incluya varias clausulas. Para simplificarlo, usamos
`$query` para representar el objeto [[yii\db\Query]]:
### `SELECT`
......@@ -68,7 +68,7 @@ $query->select('id, name')
->from('user');
```
Las opciones de select se pueden especificar como una cadena de texto (string) separada por comas o como un array. La
Las opciones de select se pueden especificar como una cadena de texto (string) separada por comas o como un array. La
sintaxis del array es especialmente útil cuando se forma la selección dinámicamente.
```php
......@@ -76,14 +76,14 @@ $query->select(['id', 'name'])
->from('user');
```
> Información: Se debe usar siempre el formato array si la clausula `SELECT` contiene expresiones SQL. Esto se debe a
que una expresión SQL como `CONCAT(first_name, last_name) AS full_name` puede contener comas. Si se junta con otra
cadena de texto de otra columna, puede ser que la expresión se divida en varias partes por comas, esto puede
> Información: Se debe usar siempre el formato array si la clausula `SELECT` contiene expresiones SQL. Esto se debe a
que una expresión SQL como `CONCAT(first_name, last_name) AS full_name` puede contener comas. Si se junta con otra
cadena de texto de otra columna, puede ser que la expresión se divida en varias partes por comas, esto puede
conllevar a errores.
Cuando se especifican columnas, se pueden incluir los prefijos de las tablas o alias de columnas, p. ej. `user.id`,
`user.id AS user_id`. Si se usa un array para especificar las columnas, también se pueden usar las claves del array
para especificar los alias de columna, p. ej. `['user_id' => 'user.id', 'user_name' => 'user.name']`.
Cuando se especifican columnas, se pueden incluir los prefijos de las tablas o alias de columnas, ej. `user.id`,
`user.id AS user_id`. Si se usa un array para especificar las columnas, también se pueden usar las claves del array
para especificar los alias de columna, ej. `['user_id' => 'user.id', 'user_name' => 'user.name']`.
A partir de la versión 2.0.1, también se pueden seleccionar subconsultas como columnas. Por ejemplo:
......@@ -108,23 +108,23 @@ Para especificar de que tabla(s) se quieren seleccionar los datos, se llama a `f
$query->select('*')->from('user');
```
Se pueden especificar múltiples tablas usando una cadena de texto separado por comas o un array. Los nombres de tablas
pueden contener prefijos de esquema (p. ej. `'public.user'`) y/o alias de tablas (p. ej. `'user u'). El método
entrecomillara automáticamente los nombres de tablas a menos que contengan algún paréntesis (que significa que se
Se pueden especificar múltiples tablas usando una cadena de texto separado por comas o un array. Los nombres de tablas
pueden contener prefijos de esquema (ej. `'public.user'`) y/o alias de tablas (ej. `'user u'). El método
entrecomillara automáticamente los nombres de tablas a menos que contengan algún paréntesis (que significa que se
proporciona la tabla como una subconsulta o una expresión de BD). Por ejemplo:
```php
$query->select('u.*, p.*')->from(['user u', 'post p']);
```
Cuando se especifican las tablas como un array, también se pueden usar las claves de los arrays como alias de tablas
Cuando se especifican las tablas como un array, también se pueden usar las claves de los arrays como alias de tablas
(si una tabla no necesita alias, no se usa una clave en formato texto). Por ejemplo:
```php
$query->select('u.*, p.*')->from(['u' => 'user', 'p' => 'post']);
```
Se puede especificar una subconsulta usando un objeto `Query`. En este caso, la clave del array correspondiente se
Se puede especificar una subconsulta usando un objeto `Query`. En este caso, la clave del array correspondiente se
usará como alias para la subconsulta.
```php
......@@ -134,7 +134,7 @@ $query->select('*')->from(['u' => $subQuery]);
### `WHERE`
Habitualmente se seleccionan los datos basándose en ciertos criterios. El Constructor de Consultas tiene algunos
Habitualmente se seleccionan los datos basándose en ciertos criterios. El Constructor de Consultas tiene algunos
métodos útiles para especificarlos, el más poderoso de estos es `where`, y se puede usar de múltiples formas.
La manera más simple para aplicar una condición es usar una cadena de texto:
......@@ -143,7 +143,7 @@ La manera más simple para aplicar una condición es usar una cadena de texto:
$query->where('status=:status', [':status' => $status]);
```
Cuando se usan cadenas de texto, hay que asegurarse que se unen los parámetros de la consulta, no crear una consulta
Cuando se usan cadenas de texto, hay que asegurarse que se unen los parámetros de la consulta, no crear una consulta
mediante concatenación de cadenas de texto. El enfoque anterior es seguro, el que se muestra a continuación, no lo es:
```php
......@@ -173,7 +173,7 @@ El código generará la el siguiente SQL:
WHERE (`status` = 10) AND (`type` = 2) AND (`id` IN (4, 8, 15, 16, 23, 42))
```
El valor NULO es un valor especial en las bases de datos, y el Constructor de Consultas lo gestiona inteligentemente.
El valor NULO es un valor especial en las bases de datos, y el Constructor de Consultas lo gestiona inteligentemente.
Este código:
```php
......@@ -203,56 +203,56 @@ Otra manera de usar el método es el formato de operando que es `[operator, oper
El operando puede ser uno de los siguientes (ver también [[yii\db\QueryInterface::where()]]):
- `and`: los operandos deben concatenerase usando `AND`. por ejemplo, `['and', 'id=1', 'id=2']` generará
`id=1 AND id=2`. Si el operando es un array, se convertirá en una cadena de texto usando las reglas aquí descritas.
Por ejemplo, `['and', 'type=1', ['or', 'id=1', 'id=2']]` generará `type=1 AND (id=1 OR id=2)`. El método no
- `and`: los operandos deben concatenerase usando `AND`. por ejemplo, `['and', 'id=1', 'id=2']` generará
`id=1 AND id=2`. Si el operando es un array, se convertirá en una cadena de texto usando las reglas aquí descritas.
Por ejemplo, `['and', 'type=1', ['or', 'id=1', 'id=2']]` generará `type=1 AND (id=1 OR id=2)`. El método no
ejecutará ningún filtrado ni entrecomillado.
- `or`: similar al operando `and` exceptuando que los operando son concatenados usando `OR`.
- `between`: el operando 1 debe ser el nombre de columna, y los operandos 2 y 3 deben ser los valores iniciales y
finales del rango en el que se encuentra la columna. Por ejemplo, `['between', 'id', 1, 10]` generará
- `between`: el operando 1 debe ser el nombre de columna, y los operandos 2 y 3 deben ser los valores iniciales y
finales del rango en el que se encuentra la columna. Por ejemplo, `['between', 'id', 1, 10]` generará
`id BETWEEN 1 AND 10`.
- `not between`: similar a `between` exceptuando que `BETWEEN` se reemplaza por `NOT BETWEEN` en la condición
- `not between`: similar a `between` exceptuando que `BETWEEN` se reemplaza por `NOT BETWEEN` en la condición
generada.
- `in`: el operando 1 debe ser una columna o una expresión de BD. El operando 2 puede ser un array o un objeto de tipo
`Query`. Generará una condición `IN`. Si el operando 2 es un array, representará el rango de valores que puede
albergar la columna o la expresión de BD; Si el operando 2 es un objeto de tipo `Query`, se generará una subconsulta
y se usará como rango de la columna o de la expresión de BD. Por ejemplo, `['in', 'id', [1, 2, 3]]` generará
`id IN (1, 2, 3)`. El método entrecomillará adecuadamente el nombre de columna y filtrará los valores del rango. El
operando `in` también soporta columnas compuestas. En este caso, el operando 1 debe se un array de columnas,
mientras que el operando 2 debe ser un array de arrays o un objeto de tipo `Query` que represente el rango de las
- `in`: el operando 1 debe ser una columna o una expresión de BD. El operando 2 puede ser un array o un objeto de tipo
`Query`. Generará una condición `IN`. Si el operando 2 es un array, representará el rango de valores que puede
albergar la columna o la expresión de BD; Si el operando 2 es un objeto de tipo `Query`, se generará una subconsulta
y se usará como rango de la columna o de la expresión de BD. Por ejemplo, `['in', 'id', [1, 2, 3]]` generará
`id IN (1, 2, 3)`. El método entrecomillará adecuadamente el nombre de columna y filtrará los valores del rango. El
operando `in` también soporta columnas compuestas. En este caso, el operando 1 debe se un array de columnas,
mientras que el operando 2 debe ser un array de arrays o un objeto de tipo `Query` que represente el rango de las
columnas.
- `not in`: similar que el operando `in` exceptuando que `IN` se reemplaza por `NOT IN` en la condición generada.
- `like`: el operando 1 debe ser una columna o una expresión de BD, y el operando 2 debe ser una cadena de texto o un
array que represente los valores a los que tienen que asemejarse la columna o la expresión de BD.Por ejemplo,
`['like', 'name', 'tester']` generará `name LIKE '%tester%'`. Cuando se da el valor rango como un array, se
generarán múltiples predicados `LIKE` y se concatenaran usando `AND`. Por ejemplo,
`['like', 'name', ['test', 'sample']]` generará `name LIKE '%test%' AND name LIKE '%sample%'`. También se puede
proporcionar un tercer operando opcional para especificar como deben filtrarse los caracteres especiales en los
valores. El operando debe se un array que mapeen los caracteres especiales a sus caracteres filtrados asociados. Si
no se proporciona este operando, se aplicará el mapeo de filtrado predeterminado. Se puede usar `false` o un array
vacío para indicar que los valores ya están filtrados y no se necesita aplicar ningún filtro. Hay que tener en
cuenta que cuando se usa un el mapeo de filtrado (o no se especifica el tercer operando), los valores se encerraran
- `like`: el operando 1 debe ser una columna o una expresión de BD, y el operando 2 debe ser una cadena de texto o un
array que represente los valores a los que tienen que asemejarse la columna o la expresión de BD.Por ejemplo,
`['like', 'name', 'tester']` generará `name LIKE '%tester%'`. Cuando se da el valor rango como un array, se
generarán múltiples predicados `LIKE` y se concatenaran usando `AND`. Por ejemplo,
`['like', 'name', ['test', 'sample']]` generará `name LIKE '%test%' AND name LIKE '%sample%'`. También se puede
proporcionar un tercer operando opcional para especificar como deben filtrarse los caracteres especiales en los
valores. El operando debe se un array que mapeen los caracteres especiales a sus caracteres filtrados asociados. Si
no se proporciona este operando, se aplicará el mapeo de filtrado predeterminado. Se puede usar `false` o un array
vacío para indicar que los valores ya están filtrados y no se necesita aplicar ningún filtro. Hay que tener en
cuenta que cuando se usa un el mapeo de filtrado (o no se especifica el tercer operando), los valores se encerraran
automáticamente entre un par de caracteres de porcentaje.
> Nota: Cuando se usa PostgreSQL también se puede usar
[`ilike`](http://www.postgresql.org/docs/8.3/static/functions-matching.html#FUNCTIONS-LIKE) en lugar de `like` para
> Nota: Cuando se usa PostgreSQL también se puede usar
[`ilike`](http://www.postgresql.org/docs/8.3/static/functions-matching.html#FUNCTIONS-LIKE) en lugar de `like` para
filtrar resultados insensibles a mayúsculas (case-insensitive).
- `or like`: similar al operando `like` exceptuando que se usa `OR` para concatenar los predicados `LIKE` cuando haya
- `or like`: similar al operando `like` exceptuando que se usa `OR` para concatenar los predicados `LIKE` cuando haya
un segundo operando en un array.
- `not like`: similar al operando `like` exceptuando que se usa `LIKE` en lugar de `NOT LIKE` en las condiciones
- `not like`: similar al operando `like` exceptuando que se usa `LIKE` en lugar de `NOT LIKE` en las condiciones
generadas.
- `or not like`: similar al operando `not like` exceptuando que se usa `OR` para concatenar los predicados `NOT LIKE`.
- `exists`: requiere un operando que debe ser una instancia de [[yii\db\Query]] que represente la subconsulta. Esto
- `exists`: requiere un operando que debe ser una instancia de [[yii\db\Query]] que represente la subconsulta. Esto
generará una expresión `EXISTS (sub-query)`.
- `not exists`: similar al operando `exists` y genera una expresión `NOT EXISTS (sub-query)`.
......@@ -291,10 +291,10 @@ WHERE (`status` = 10) AND (`title` LIKE '%yii%')
#### Construcción de Condiciones de Filtro
Cuando se generan condiciones de filtro basadas en datos recibidos de usuarios (inputs), a menudo se quieren gestionar
de forma especial las "datos vacíos" para ignorarlos en los filtros. Por ejemplo, teniendo un formulario HTML que
obtiene el nombre de usuario y la dirección de correo electrónico. Si el usuario solo rellena el campo de nombre de
usuario, se puede querer generar una consulta para saber si el nombre de usuario recibido es valido. Se puede usar
Cuando se generan condiciones de filtro basadas en datos recibidos de usuarios (inputs), a menudo se quieren gestionar
de forma especial las "datos vacíos" para ignorarlos en los filtros. Por ejemplo, teniendo un formulario HTML que
obtiene el nombre de usuario y la dirección de correo electrónico. Si el usuario solo rellena el campo de nombre de
usuario, se puede querer generar una consulta para saber si el nombre de usuario recibido es valido. Se puede usar
`filterWhere()` para conseguirlo:
```php
......@@ -305,12 +305,12 @@ $query->filterWhere([
]);
```
El método `filterWhere()` es muy similar al método `where()`. La principal diferencia es que el `filterWhere()`
eliminará los valores vacíos de las condiciones proporcionadas. Por lo tanto si `$email` es "vació", la consulta
resultante será `...WHERE username=:username`; y si tanto `$username` como `$email` son "vacías", la consulta no
El método `filterWhere()` es muy similar al método `where()`. La principal diferencia es que el `filterWhere()`
eliminará los valores vacíos de las condiciones proporcionadas. Por lo tanto si `$email` es "vació", la consulta
resultante será `...WHERE username=:username`; y si tanto `$username` como `$email` son "vacías", la consulta no
tendrá `WHERE`.
Decimos que un valor es *vacío* si es nulo, una cadena de texto vacía, una cadena de texto que consista en espacios en
Decimos que un valor es *vacío* si es nulo, una cadena de texto vacía, una cadena de texto que consista en espacios en
blanco o un array vacío.
También se pueden usar `andFilterWhere()` y `orFilterWhere()` para añadir más condiciones de filtro.
......@@ -342,7 +342,7 @@ Si se quieren añadir otro campo después de usar `groupBy`:
$query->addGroupBy(['created_at', 'updated_at']);
```
Para añadir la condición `HAVING` se pueden usar los métodos `having` y `andHaving` y `orHaving`. Los parámetros para
Para añadir la condición `HAVING` se pueden usar los métodos `having` y `andHaving` y `orHaving`. Los parámetros para
ellos son similares a los del grupo de métodos `where`:
```php
......@@ -379,7 +379,7 @@ $query->select(['user.name AS author', 'post.title as title'])
->leftJoin('post', 'post.user_id = user.id');
```
En el código, el primer parámetro del método `leftjoin` especifica la tabla a la que aplicar el join. El segundo
En el código, el primer parámetro del método `leftjoin` especifica la tabla a la que aplicar el join. El segundo
parámetro, define la condición del join.
Si la aplicación de bases de datos soporta otros tipos de joins, se pueden usar mediante el método `join` genérico:
......@@ -390,8 +390,8 @@ $query->join('FULL OUTER JOIN', 'post', 'post.user_id = user.id');
El primer argumento es el tipo de join a realizar. El segundo es la tabla a la que aplicar el join, y el tercero es la condición:
Como en `FROM`, también se pueden efectuar joins con subconsultas. Para hacerlo, se debe especificar la subconsulta
como un array que tiene que contener un elemento. El valor del array tiene que ser un objeto de tipo `Query` que
Como en `FROM`, también se pueden efectuar joins con subconsultas. Para hacerlo, se debe especificar la subconsulta
como un array que tiene que contener un elemento. El valor del array tiene que ser un objeto de tipo `Query` que
represente la subconsulta, mientras que la clave del array es el alias de la subconsulta. Por ejemplo:
```php
......@@ -400,8 +400,8 @@ $query->leftJoin(['u' => $subQuery], 'u.id=author_id');
### `UNION`
En SQL `UNION` agrega resultados de una consulta a otra consulta. Las columnas devueltas por ambas consultas deben
coincidir. En Yii para construirla, primero se pueden formar dos objetos de tipo query y después usar el método
En SQL `UNION` agrega resultados de una consulta a otra consulta. Las columnas devueltas por ambas consultas deben
coincidir. En Yii para construirla, primero se pueden formar dos objetos de tipo query y después usar el método
`union`:
```php
......@@ -417,9 +417,9 @@ $query->union($anotherQuery);
Consulta por Lotes
---------------
Cuando se trabaja con grandes cantidades de datos, los métodos como [[yii\db\Query::all()]] no son adecuados ya que
requieren la carga de todos los datos en memoria. Para mantener los requerimientos de memoria reducidos, Yii
proporciona soporte a las llamadas consultas por lotes (batch query). Una consulta por lotes usa un cursor de datos y
Cuando se trabaja con grandes cantidades de datos, los métodos como [[yii\db\Query::all()]] no son adecuados ya que
requieren la carga de todos los datos en memoria. Para mantener los requerimientos de memoria reducidos, Yii
proporciona soporte a las llamadas consultas por lotes (batch query). Una consulta por lotes usa un cursor de datos y
recupera los datos en bloques.
Las consultas por lotes se pueden usar del siguiente modo:
......@@ -441,17 +441,17 @@ foreach ($query->each() as $user) {
}
```
Los métodos [[yii\db\Query::batch()]] y [[yii\db\Query::each()]] devuelven un objeto [[yii\db\BatchQueryResult]] que
implementa una interfaz `Iterator` y así se puede usar en el constructor `foreach`. Durante la primera iteración, se
efectúa una consulta SQL a la base de datos. Desde entonces, los datos se recuperan por lotes en las iteraciones. El
tamaño predeterminado de los lotes es 100, que significa que se recuperan 100 filas de datos en cada lote. Se puede
Los métodos [[yii\db\Query::batch()]] y [[yii\db\Query::each()]] devuelven un objeto [[yii\db\BatchQueryResult]] que
implementa una interfaz `Iterator` y así se puede usar en el constructor `foreach`. Durante la primera iteración, se
efectúa una consulta SQL a la base de datos. Desde entonces, los datos se recuperan por lotes en las iteraciones. El
tamaño predeterminado de los lotes es 100, que significa que se recuperan 100 filas de datos en cada lote. Se puede
modificar el tamaño de los lotes pasando pasando un primer parámetro a los métodos `batch()` o `each()`.
En comparación con [[yii\db\Query::all()]], las consultas por lotes sólo cargan 100 filas de datos en memoria cada
vez. Si el procesan los datos y después se descartan inmediatamente, las consultas por lotes, pueden ayudar a mantener
En comparación con [[yii\db\Query::all()]], las consultas por lotes sólo cargan 100 filas de datos en memoria cada
vez. Si el procesan los datos y después se descartan inmediatamente, las consultas por lotes, pueden ayudar a mantener
el uso de memora bajo un limite.
Si se especifica que el resultado de la consulta tiene que ser indexado por alguna columna mediante
Si se especifica que el resultado de la consulta tiene que ser indexado por alguna columna mediante
[[yii\db\Query::indexBy()]], las consultas por lotes seguirán manteniendo el indice adecuado. Por ejemplo,
```php
......
Clase auxiliar Html (Html helper)
=================================
Todas las aplicaciones web generan grandes cantidades de marcado HTML (HTML markup). Si el marcado es estático, se
puede realizar de forma efectiva
[mezclando PHP y HTML en un mismo archivo](http://php.net/manual/es/language.basic-syntax.phpmode.php) pero cuando se
generan dinámicamente empieza a complicarse su gestion sin ayuda extra. Yii proporciona esta ayuda que proporciona un
Todas las aplicaciones web generan grandes cantidades de marcado HTML (HTML markup). Si el marcado es estático, se
puede realizar de forma efectiva
[mezclando PHP y HTML en un mismo archivo](http://php.net/manual/es/language.basic-syntax.phpmode.php) pero cuando se
generan dinámicamente empieza a complicarse su gestion sin ayuda extra. Yii proporciona esta ayuda que proporciona un
conjunto de métodos estáticos para gestionar las etiquetas HTML usadas más comúnmente, sus opciones y contenidos.
> Nota: Si el marcado es casi estático, es preferible usar HTML directamente. No es necesario encapsularlo todo con
> Nota: Si el marcado es casi estático, es preferible usar HTML directamente. No es necesario encapsularlo todo con
llamadas a la clase auxiliar Html.
Lo fundamental <a name="basics"></a>
--------------
Teniendo en cuenta que la construcción de HTML dinámico mediante la concatenación de cadenas de texto se complica
rápidamente, Yii proporciona un conjunto de métodos para manipular las opciones de etiquetas y la construcción de las
Teniendo en cuenta que la construcción de HTML dinámico mediante la concatenación de cadenas de texto se complica
rápidamente, Yii proporciona un conjunto de métodos para manipular las opciones de etiquetas y la construcción de las
mismas basadas en estas opciones.
### Generación de etiquetas
......@@ -25,10 +25,10 @@ El código de generación de etiquetas es similar al siguiente:
<?= Html::tag('p', Html::encode($user->name), ['class' => 'username']) ?>
```
El primer argumento es el nombre de la etiqueta. El segundo es el contenido que se ubicara entre la etiqueta de
apertura y la de cierre. Hay que tener en cuenta que estamos usando `Html::encode`. Esto es debido a que el contenido
no se codifica automáticamente para permitir usar HTML cuando se necesite. La tercera opción es un array de opciones
HTML o, en otras palabras, los atributos de las etiquetas. En este array la clave representa el nombre del atributo
El primer argumento es el nombre de la etiqueta. El segundo es el contenido que se ubicara entre la etiqueta de
apertura y la de cierre. Hay que tener en cuenta que estamos usando `Html::encode`. Esto es debido a que el contenido
no se codifica automáticamente para permitir usar HTML cuando se necesite. La tercera opción es un array de opciones
HTML o, en otras palabras, los atributos de las etiquetas. En este array la clave representa el nombre del atributo
como podría ser `class`, `href` o `target` y el valor es su valor.
El código anterior generara el siguiente HTML:
......@@ -37,25 +37,25 @@ El código anterior generara el siguiente HTML:
<p class="username">samdark</p>
```
Si se necesita solo la apertura o el cierre de una etiqueta, se pueden usar los métodos `Html::beginTag()` y
Si se necesita solo la apertura o el cierre de una etiqueta, se pueden usar los métodos `Html::beginTag()` y
`Html::endTag()`.
Las opciones se usan en muchos métodos de la clase auxiliar Html y en varios widgets. En todos estos casos hay cierta
Las opciones se usan en muchos métodos de la clase auxiliar Html y en varios widgets. En todos estos casos hay cierta
gestión adicional que se debe conocer:
- Si un valor es `null`, el correspondiente atributo no se renderizará.
- Los atributos cuyos valores son de tipo booleano serán tratados como
- Los atributos cuyos valores son de tipo booleano serán tratados como
[atributos booleanos](http://www.w3.org/TR/html5/infrastructure.html#boolean-attributes).
- Los valores de los atributos se codificaran en HTML usando [[yii\helpers\Html::encode()|Html::encode()]].
- El atributo "data" puede recibir un array. En este caso, se "expandirá" y se renderizará una lista de atributos
`data` p. ej. `'data' => ['id' => 1, 'name' => 'yii']` se convierte en `data-id="1" data-name="yii"`.
- El atributo "data" puede recibir JSON. Se gestionará de la misma manera que un array p. ej.
`'data' => ['params' => ['id' => 1, 'name' => 'yii'], 'status' => 'ok']` se convierte en
- El atributo "data" puede recibir un array. En este caso, se "expandirá" y se renderizará una lista de atributos
`data` ej. `'data' => ['id' => 1, 'name' => 'yii']` se convierte en `data-id="1" data-name="yii"`.
- El atributo "data" puede recibir JSON. Se gestionará de la misma manera que un array ej.
`'data' => ['params' => ['id' => 1, 'name' => 'yii'], 'status' => 'ok']` se convierte en
`data-params='{"id":1,"name":"yii"}' data-status="ok"`.
### Formación de clases y estilos dinámicamente
Cuando se construyen opciones para etiquetas HTML, a menudo nos encontramos con valores predeterminados que hay que
Cuando se construyen opciones para etiquetas HTML, a menudo nos encontramos con valores predeterminados que hay que
modificar. Para añadir o eliminar clases CSS se puede usar el siguiente ejemplo:
```php
......@@ -68,7 +68,7 @@ if ($type === 'success') {
echo Html::tag('div', 'Pwede na', $options);
// cuando $type sea 'success' se renderizará
// cuando $type sea 'success' se renderizará
// <div class="btn btn-success">Pwede na</div>
```
......@@ -84,22 +84,22 @@ Html::addCssStyle($options, 'height: 200px; positon: absolute;');
Html::removeCssStyle($options, ['width', 'height']);
```
Cuando se usa [[yii\helpers\Html::addCssStyle()|addCssStyle()]] se puede especificar si un array de pares clave-valor
corresponde a nombres y valores de la propiedad CSS correspondiente o a una cadena de texto como por ejemplo
`width: 100px; height: 200px;`. Estos formatos se pueden "hacer" y "deshacer" usando
[[yii\helpers\Html::cssStyleFromArray()|cssStyleFromArray()]] y
[[yii\helpers\Html::cssStyleToArray()|cssStyleToArray()]]. El método
[[yii\helpers\Html::removeCssStyle()|removeCssStyle()]] un array de propiedades que se eliminarán. Si sólo se
Cuando se usa [[yii\helpers\Html::addCssStyle()|addCssStyle()]] se puede especificar si un array de pares clave-valor
corresponde a nombres y valores de la propiedad CSS correspondiente o a una cadena de texto como por ejemplo
`width: 100px; height: 200px;`. Estos formatos se pueden "hacer" y "deshacer" usando
[[yii\helpers\Html::cssStyleFromArray()|cssStyleFromArray()]] y
[[yii\helpers\Html::cssStyleToArray()|cssStyleToArray()]]. El método
[[yii\helpers\Html::removeCssStyle()|removeCssStyle()]] un array de propiedades que se eliminarán. Si sólo se
eliminará una propiedad, se puede especificar como una cadena de texto.
Codificación y Descodificación de contenido <a name="encoding-and-decoding-content"></a>
-------------------------------------------
Para que el contenido se muestre correctamente y de forma segura en caracteres especiales HTML el contenido debe ser
codificado. En PHP esto se hace con [htmlspecialchars](http://www.php.net/manual/en/function.htmlspecialchars.php) y
[htmlspecialchars_decode](http://www.php.net/manual/en/function.htmlspecialchars-decode.php). El problema con el uso
de estos métodos directamente es que se tiene que especificar la codificación y opciones extra cada vez. Ya que las
opciones siempre son las mismas y la codificación debe coincidir con la de la aplicación para prevenir problemas de
Para que el contenido se muestre correctamente y de forma segura en caracteres especiales HTML el contenido debe ser
codificado. En PHP esto se hace con [htmlspecialchars](http://www.php.net/manual/en/function.htmlspecialchars.php) y
[htmlspecialchars_decode](http://www.php.net/manual/en/function.htmlspecialchars-decode.php). El problema con el uso
de estos métodos directamente es que se tiene que especificar la codificación y opciones extra cada vez. Ya que las
opciones siempre son las mismas y la codificación debe coincidir con la de la aplicación para prevenir problemas de
seguridad, Yii proporciona dos métodos simples y compactos:
```php
......@@ -112,25 +112,25 @@ $decodedUserName = Html::decode($userName);
Formularios
-----------
El trato con el marcado de formularios es una tarea repetitiva y propensa a errores. Por esto hay un grupo de métodos
El trato con el marcado de formularios es una tarea repetitiva y propensa a errores. Por esto hay un grupo de métodos
para ayudar a gestionarlos.
> Nota: hay que considerar la opción de usar [[yii\widgets\ActiveForm|ActiveForm]] en caso que se gestionen
> Nota: hay que considerar la opción de usar [[yii\widgets\ActiveForm|ActiveForm]] en caso que se gestionen
formularios que requieran validaciones.
### Abrir y cerrar un formulario
Se puede abrir un formulario con el metodo [[yii\helpers\Html::beginForm()|beginForm()]] como se muestra a
Se puede abrir un formulario con el metodo [[yii\helpers\Html::beginForm()|beginForm()]] como se muestra a
continuación:
```php
<?= Html::beginForm(['order/update', 'id' => $id], 'post', ['enctype' => 'multipart/form-data']) ?>
```
El primer argumento es la URL a la que se enviaran los datos del formulario. Se puede especificar en formato de ruta
de Yii con los parámetros aceptados por [[yii\helpers\Url::to()|Url::to()]]. El segundo es el método que se usara.
`post` es el método predeterminado. El tercero es un array de opciones para la etiqueta `form`. En este caso cambiamos
el método de codificación del formulario de `data` en una petición POST a `multipart/form-data`. Esto se requiere
El primer argumento es la URL a la que se enviaran los datos del formulario. Se puede especificar en formato de ruta
de Yii con los parámetros aceptados por [[yii\helpers\Url::to()|Url::to()]]. El segundo es el método que se usara.
`post` es el método predeterminado. El tercero es un array de opciones para la etiqueta `form`. En este caso cambiamos
el método de codificación del formulario de `data` en una petición POST a `multipart/form-data`. Esto se requiere
cuando se quieren subir archivos.
El cierre de la etiqueta `form` es simple:
......@@ -149,14 +149,14 @@ Para generar botones se puede usar el siguiente código:
<?= Html::resetButton('Reset', ['class' => 'reset']) ?>
```
El primer argumento para los tres métodos es el titulo del botón y el segundo son las opciones. El titulo no esta
codificado pero si se usan datos recibidos por el usuario, deben codificarse mediante
El primer argumento para los tres métodos es el titulo del botón y el segundo son las opciones. El titulo no esta
codificado pero si se usan datos recibidos por el usuario, deben codificarse mediante
[[yii\helpers\Html::encode()|Html::encode()]].
### Inputs
Hay dos grupos en los métodos input. Unos empiezan con `active` y se llaman inputs activos y los otros no empiezan
así. Los inputs activos obtienen datos del modelo y del atributo especificado y los datos de los inputs normales se
Hay dos grupos en los métodos input. Unos empiezan con `active` y se llaman inputs activos y los otros no empiezan
así. Los inputs activos obtienen datos del modelo y del atributo especificado y los datos de los inputs normales se
especifica directamente.
Los métodos más genéricos son:
......@@ -200,7 +200,7 @@ Las listas desplegables (dropdown list) se pueden renderizar como se muestra a c
<?= Html::activeListBox($users, 'id', ArrayHelper::map($userModels, 'id', 'name')) ?>
```
El primer argumento es el nombre del input, el segundo es el valor seleccionado actualmente y el tercero es el array
El primer argumento es el nombre del input, el segundo es el valor seleccionado actualmente y el tercero es el array
de pares clave-valor donde la clave es al lista de valores y el valor del array es la lista a mostrar.
Si se quiere habilitar la selección múltiple, se puede usar la lista seleccionable (checkbox list):
......@@ -219,7 +219,7 @@ Si no, se puede usar la lista de opciones (radio list):
### Labels y errores
De forma parecida que en los imputs hay dos métodos para generar labels. El activo que obtiene los datos del modelo y
De forma parecida que en los imputs hay dos métodos para generar labels. El activo que obtiene los datos del modelo y
el no-activo que acepta datos directamente:
```php
......@@ -241,7 +241,7 @@ Para mostrar un error individual:
### Nombres y valores
Existen métodos para obtener nombres, IDs y valores para los campos de entrada (inputs) basados en el modelo. Estos se
Existen métodos para obtener nombres, IDs y valores para los campos de entrada (inputs) basados en el modelo. Estos se
usan principalmente internamente pero a veces pueden resultar prácticos:
```php
......@@ -258,11 +258,11 @@ echo Html::getAttributeValue($post, 'title');
echo Html::getAttributeValue($post, '[0]authors[0]');
```
En el ejemplo anterior, el primer argumento es el modelo y el segundo es el atributo de expresión. En su forma más
simple es su nombre de atributo pero podría ser un nombre de atributo prefijado y/o añadido como sufijo con los
En el ejemplo anterior, el primer argumento es el modelo y el segundo es el atributo de expresión. En su forma más
simple es su nombre de atributo pero podría ser un nombre de atributo prefijado y/o añadido como sufijo con los
indices de un array, esto se usa principalmente para mostrar inputs en formatos de tablas:
- `[0]content` se usa en campos de entrada de datos en formato de tablas para representar el atributo "content" para
- `[0]content` se usa en campos de entrada de datos en formato de tablas para representar el atributo "content" para
el primer modelo del input en formato de tabla;
- `dates[0]` representa el primer elemento del array del atributo "dates";
- `[0]dates[0]` representa el primer elemento del array del atributo "dates" para el primer modelo en formato de tabla.
......@@ -305,12 +305,12 @@ genera
<![endif]-->
```
El primer argumento es la URL. El segundo es un array de opciones. Adicionalmente, para regular las opciones se puede
El primer argumento es la URL. El segundo es un array de opciones. Adicionalmente, para regular las opciones se puede
especificar:
- `condition` para envolver `<link` con los comentarios condicionales con condiciones especificas. Esperamos que sean
- `condition` para envolver `<link` con los comentarios condicionales con condiciones especificas. Esperamos que sean
necesarios los comentarios condicionales ;)
- `noscript` se puede establecer como `true` para envolver `<link` con la etiqueta `<noscript>` por lo que el sólo se
- `noscript` se puede establecer como `true` para envolver `<link` con la etiqueta `<noscript>` por lo que el sólo se
incluirá si el navegador no soporta JavaScript o si lo ha deshabilitado el usuario.
Para enlazar un archivo JavaScript:
......@@ -319,8 +319,8 @@ Para enlazar un archivo JavaScript:
<?= Html::jsFile('@web/js/main.js') ?>
```
Es igual que con las CSS, el primer argumento especifica el enlace al fichero que se quiere incluir. Las opciones se
pueden pasar como segundo argumento. En las opciones se puede especificar `condition` del mismo modo que se puede usar
Es igual que con las CSS, el primer argumento especifica el enlace al fichero que se quiere incluir. Las opciones se
pueden pasar como segundo argumento. En las opciones se puede especificar `condition` del mismo modo que se puede usar
para `cssFile`.
Enlaces
......@@ -332,9 +332,9 @@ Existe un método para generar hipervínculos a conveniencia:
<?= Html::a('Profile', ['user/view', 'id' => $id], ['class' => 'profile-link']) ?>
```
El primer argumento es el titulo. No está codificado por lo que si se usan datos enviados por el usuario se tienen que
codificar usando `Html::encode()`. El segundo argumento es el que se introducirá en `href` de la etiqueta `<a`. Se
puede revisar [Url::to()](helper-url.md) para obtener más detalles de los valores que acepta. El tercer argumento es
El primer argumento es el titulo. No está codificado por lo que si se usan datos enviados por el usuario se tienen que
codificar usando `Html::encode()`. El segundo argumento es el que se introducirá en `href` de la etiqueta `<a`. Se
puede revisar [Url::to()](helper-url.md) para obtener más detalles de los valores que acepta. El tercer argumento es
un array de las propiedades de la etiqueta.
Si se requiere generar enlaces de tipo `mailto` se puede usar el siguiente código:
......@@ -356,7 +356,7 @@ genera
<img src="http://example.com/images/logo.png" alt="My logo" />
```
Aparte de los [aliases](concept-aliases.md) el primer argumento puede aceptar rutas, parámetros y URLs. Del mismo modo
Aparte de los [aliases](concept-aliases.md) el primer argumento puede aceptar rutas, parámetros y URLs. Del mismo modo
que [Url::to()](helper-url.md).
Listas
......
......@@ -6,7 +6,7 @@ La clase auxiliar URL proporciona un conjunto de métodos estáticos para gestio
Obtener URLs Comunes
--------------------
Se pueden usar dos métodos para obtener URLs comunes: URL de inicio (home URL) y URL base (base URL) de la petición
Se pueden usar dos métodos para obtener URLs comunes: URL de inicio (home URL) y URL base (base URL) de la petición
(request) actual. Para obtener la URL de inicio se puede usar el siguiente código:
```php
......@@ -15,7 +15,7 @@ $absoluteHomeUrl = Url::home(true);
$httpsAbsoluteHomeUrl = Url::home('https');
```
Si no se pasan parámetros, las URLs generadas son relativas. Se puede pasar `true`para obtener la URL absoluta del
Si no se pasan parámetros, las URLs generadas son relativas. Se puede pasar `true`para obtener la URL absoluta del
esquema actual o especificar el esquema explícitamente (`https`, `http`).
Para obtener la URL base de la petición actual, se puede usar el siguiente código:
......@@ -31,14 +31,14 @@ El único parámetro del método funciona exactamente igual que para `Url::home(
Creación de URLs
----------------
Para crear una URL para una ruta determinada se puede usar `Url::toRoute()`. El metodo utiliza [[\yii\web\UrlManager]]
Para crear una URL para una ruta determinada se puede usar `Url::toRoute()`. El metodo utiliza [[\yii\web\UrlManager]]
para crear una URL:
```php
$url = Url::toRoute(['product/view', 'id' => 42]);
```
Se puede especificar la ruta como una cadena de texto, p. ej. `site/index`. También se puede usar un array si se
Se puede especificar la ruta como una cadena de texto, ej. `site/index`. También se puede usar un array si se
quieren especificar parámetros para la URL que se esta generando. El formato del array debe ser:
```php
......@@ -53,14 +53,14 @@ Si se quiere crear una URL con un enlace, se puede usar el formato de array con
['site/index', 'param1' => 'value1', '#' => 'name']
```
Una ruta puede ser absoluta o relativa. Una ruta absoluta tiene una barra al principio (p. ej. `/site/index`),
mientras que una ruta relativa no la tiene (p. ej. `site/index` o `index`). Una ruta relativa se convertirá en una
Una ruta puede ser absoluta o relativa. Una ruta absoluta tiene una barra al principio (ej. `/site/index`),
mientras que una ruta relativa no la tiene (ej. `site/index` o `index`). Una ruta relativa se convertirá en una
ruta absoluta siguiendo las siguientes normas:
- Si la ruta es una cadena vacía, se usará la [[\yii\web\Controller::route|route]] actual;
- Si la ruta no contiene barras (p. ej. `index`), se considerará que es el ID de una acción del controlador actual y
- Si la ruta no contiene barras (ej. `index`), se considerará que es el ID de una acción del controlador actual y
se antepondrá con [[\yii\web\Controller::uniqueId]];
- Si la ruta no tiene barra inicial (p. ej. `site/index`), se considerará que es una ruta relativa del modulo actual y
- Si la ruta no tiene barra inicial (ej. `site/index`), se considerará que es una ruta relativa del modulo actual y
se le antepondrá el [[\yii\base\Module::uniqueId|uniqueId]] del modulo.
A continuación se muestran varios ejemplos del uso de este método:
......@@ -79,21 +79,21 @@ echo Url::toRoute('site/index', true);
echo Url::toRoute('site/index', 'https');
```
El otro método `Url::to()` es muy similar a [[toRoute()]]. La única diferencia es que este método requiere que la ruta
El otro método `Url::to()` es muy similar a [[toRoute()]]. La única diferencia es que este método requiere que la ruta
especificada sea un array. Si se pasa una cadena de texto, se tratara como una URL.
El primer argumento puede ser:
- un array: se llamará a [[toRoute()]] para generar la URL. Por ejemplo: `['site/index']`,
`['post/index', 'page' => 2]`. Se puede revisar [[toRoute()]] para obtener más detalles acerca de como especificar
- un array: se llamará a [[toRoute()]] para generar la URL. Por ejemplo: `['site/index']`,
`['post/index', 'page' => 2]`. Se puede revisar [[toRoute()]] para obtener más detalles acerca de como especificar
una ruta.
- una cadena que empiece por `@`: se tratará como un alias, y se devolverá la cadena correspondiente asociada a este
- una cadena que empiece por `@`: se tratará como un alias, y se devolverá la cadena correspondiente asociada a este
alias.
- una cadena vacía: se devolverá la URL de la petición actual;
- una cadena de texto: se devolverá sin alteraciones.
Cuando se especifique `$schema` (tanto una cadena de text como `true`), se devolverá una URL con información del host
(obtenida mediante [[\yii\web\UrlManager::hostInfo]]). Si `$url` ya es una URL absoluta, su esquema se reemplazará con
Cuando se especifique `$schema` (tanto una cadena de text como `true`), se devolverá una URL con información del host
(obtenida mediante [[\yii\web\UrlManager::hostInfo]]). Si `$url` ya es una URL absoluta, su esquema se reemplazará con
el especificado.
A continuación se muestran algunos ejemplos de uso:
......@@ -124,7 +124,7 @@ echo Url::to('@web/images/logo.gif', 'https');
Recordar la URL para utilizarla más adelante
--------------------------------------------
Hay casos en que se necesita recordar la URL y después usarla durante el procesamiento de una de las peticiones
Hay casos en que se necesita recordar la URL y después usarla durante el procesamiento de una de las peticiones
secuenciales. Se puede logar de la siguiente manera:
```php
......@@ -148,7 +148,7 @@ $productUrl = Url::previous('product');
Reconocer la relatividad de URLs
--------------------------------
Para descubrir si una URL es relativa, es decir, que no contenga información del host, se puede utilizar el siguiente
Para descubrir si una URL es relativa, es decir, que no contenga información del host, se puede utilizar el siguiente
código:
```php
......
Gestión de Errores
==================
Yii incluye un [[yii\web\ErrorHandler|error handler]] que permite una gestión de errores mucho más práctica que
Yii incluye un [[yii\web\ErrorHandler|error handler]] que permite una gestión de errores mucho más práctica que
anteriormente. En particular, el gestor de errores de Yii hace lo siguiente para mejorar la gestión de errores:
* Todos los errores no fatales (p. ej. advertencias (warning), avisos (notices)) se convierten en excepciones
* Todos los errores no fatales (ej. advertencias (warning), avisos (notices)) se convierten en excepciones
capturables.
* Las excepciones y los errores fatales de PHP se muestran con una pila de llamadas (call stack) de información
* Las excepciones y los errores fatales de PHP se muestran con una pila de llamadas (call stack) de información
detallada y lineas de código fuente.
* Soporta el uso de [acciones de controlador](structure-controllers.md#actions) dedicadas para mostrar errores.
* Soporta diferentes formatos de respuesta (response) de errores.
El [[yii\web\ErrorHandler|error handler]] esta habilitado de forma predeterminada. Se puede deshabilitar definiendo la
constante `YII_ENABLE_ERROR_HANDLER` con valor false en el
El [[yii\web\ErrorHandler|error handler]] esta habilitado de forma predeterminada. Se puede deshabilitar definiendo la
constante `YII_ENABLE_ERROR_HANDLER` con valor false en el
[script de entrada (entry script)](structure-entry-scripts.md) de la aplicación.
## Uso del Gestor de Errores <a name="using-error-handler"></a>
El [[yii\web\ErrorHandler|error handler]] se registra como un
[componente de aplicación](structure-application-components.md) llamado `errorHandler`. Se puede configurar en la
El [[yii\web\ErrorHandler|error handler]] se registra como un
[componente de aplicación](structure-application-components.md) llamado `errorHandler`. Se puede configurar en la
configuración de la aplicación como en el siguiente ejemplo:
```php
......@@ -31,10 +31,10 @@ return [
];
```
Con la anterior configuración, el numero del lineas de código fuente que se mostrará en las páginas de excepciones
Con la anterior configuración, el numero del lineas de código fuente que se mostrará en las páginas de excepciones
será como máximo de 20.
Como se ha mencionado, el gestor de errores convierte todos los errores de PHP no fatales en excepciones capturables.
Como se ha mencionado, el gestor de errores convierte todos los errores de PHP no fatales en excepciones capturables.
Esto significa que se puede usar el siguiente código para tratar los errores PHP:
```php
......@@ -50,9 +50,9 @@ try {
// la ejecución continua ...
```
Si se quiere mostrar una página de error que muestra al usuario que su petición no es válida o no es la esperada, se
puede simplemente lanzar una excepción de tipo [[yii\web\HttpException|HTTP exception]], como podría ser
[[yii\web\NotFoundHttpException]]. El gestor de errores establecerá correctamente el código de estado HTTP de la
Si se quiere mostrar una página de error que muestra al usuario que su petición no es válida o no es la esperada, se
puede simplemente lanzar una excepción de tipo [[yii\web\HttpException|HTTP exception]], como podría ser
[[yii\web\NotFoundHttpException]]. El gestor de errores establecerá correctamente el código de estado HTTP de la
respuesta y usará la vista de error apropiada para mostrar el mensaje.
```php
......@@ -63,32 +63,32 @@ throw new NotFoundHttpException();
## Personalizar la Visualización de Errores <a name="customizing-error-display"></a>
El [[yii\web\ErrorHandler|error handler]] ajusta la visualización del error conforme al valor de la constante
`YII_DEBUG`. Cuando `YII_DEBUG` es `true` (es decir, en modo depuración (debug)), el gestor de errores mostrara las
excepciones con una pila detallada de información y con lineas de código fuente para ayudar a depurar. Y cuando la
variable `YII_DEBUG` es `false`, solo se mostrará el mensaje de error para prevenir la revelación de información
El [[yii\web\ErrorHandler|error handler]] ajusta la visualización del error conforme al valor de la constante
`YII_DEBUG`. Cuando `YII_DEBUG` es `true` (es decir, en modo depuración (debug)), el gestor de errores mostrara las
excepciones con una pila detallada de información y con lineas de código fuente para ayudar a depurar. Y cuando la
variable `YII_DEBUG` es `false`, solo se mostrará el mensaje de error para prevenir la revelación de información
sensible de la aplicación.
> Información: Si una excepción es descendiente de [[yii\base\UserException]], no se mostrará la pila de llamadas
independientemente del valor de `YII_DEBUG`. Esto es debido a que se considera que estas excepciones se deben a
> Información: Si una excepción es descendiente de [[yii\base\UserException]], no se mostrará la pila de llamadas
independientemente del valor de `YII_DEBUG`. Esto es debido a que se considera que estas excepciones se deben a
errores cometidos por los usuarios y los desarrolladores no necesitan corregirlas.
De forma predeterminada, el [[yii\web\ErrorHandler|error handler]] muestra los errores usando dos
De forma predeterminada, el [[yii\web\ErrorHandler|error handler]] muestra los errores usando dos
[vistas](structure-views.md):
* `@yii/views/errorHandler/error.php`: se usa cuando deben mostrarse los errores SIN la información de la pila de
* `@yii/views/errorHandler/error.php`: se usa cuando deben mostrarse los errores SIN la información de la pila de
llamadas. Cuando `YII_DEBUG` es falos, este es el único error que se mostrara.
* `@yii/views/errorHandler/exception.php`: se usa cuando los errores deben mostrarse CON la información de la pila de
* `@yii/views/errorHandler/exception.php`: se usa cuando los errores deben mostrarse CON la información de la pila de
llamadas.
Se pueden configurar las propiedades [[yii\web\ErrorHandler::errorView|errorView]] y
[[yii\web\ErrorHandler::exceptionView|exceptionView]] el gestor de errores para usar nuestros propias vistas para
Se pueden configurar las propiedades [[yii\web\ErrorHandler::errorView|errorView]] y
[[yii\web\ErrorHandler::exceptionView|exceptionView]] el gestor de errores para usar nuestros propias vistas para
personalizar la visualización de los errores.
### Uso de Acciones de Error <a name="using-error-actions"></a>
Una mejor manera de personalizar la visualización de errores es usar un [acción](structure-controllers.md) de error
dedicada. Para hacerlo, primero se debe configurar la propiedad [[yii\web\ErrorHandler::errorAction|errorAction]] del
Una mejor manera de personalizar la visualización de errores es usar un [acción](structure-controllers.md) de error
dedicada. Para hacerlo, primero se debe configurar la propiedad [[yii\web\ErrorHandler::errorAction|errorAction]] del
componente `errorHandler` como en el siguiente ejemplo:
```php
......@@ -101,8 +101,8 @@ return [
];
```
La propiedad [[yii\web\ErrorHandler::errorAction|errorAction]] vincula una [ruta](structure-controllers.md#routes) a
una acción. La configuración anterior declara que cuando un error tiene que mostrarse sin la pila de información de
La propiedad [[yii\web\ErrorHandler::errorAction|errorAction]] vincula una [ruta](structure-controllers.md#routes) a
una acción. La configuración anterior declara que cuando un error tiene que mostrarse sin la pila de información de
llamadas, se debe ejecutar la acción `site/error`.
Se puede crear una acción `site/error` como se hace a continuación,
......@@ -126,10 +126,10 @@ class SiteController extends Controller
}
```
El código anterior define la acción `error` usando la clase [[yii\web\ErrorAction]] que renderiza un error usando la
El código anterior define la acción `error` usando la clase [[yii\web\ErrorAction]] que renderiza un error usando la
vista llamada `error`.
Además, usando [[yii\web\ErrorAction]], también se puede definir la acción `error` usando un método de acción como en
Además, usando [[yii\web\ErrorAction]], también se puede definir la acción `error` usando un método de acción como en
el siguiente ejemplo,
```php
......@@ -142,24 +142,24 @@ public function actionError()
}
```
Ahora se debe crear un archivo de vista ubicado en `views/sites/error.php`. En este archivo de vista, se puede acceder
Ahora se debe crear un archivo de vista ubicado en `views/sites/error.php`. En este archivo de vista, se puede acceder
a las siguientes variables si se define el error como un [[yii\web\ErrorAction]]:
* `name`: el nombre del error;
* `message`: el mensaje del error;
* `exception`: el objeto de excepción a través del cual se puede obtener más información útil, tal como el código de
* `exception`: el objeto de excepción a través del cual se puede obtener más información útil, tal como el código de
estado HTTP, el código de error, la pila de llamadas del error, etc.
> Información: Tanto la [plantilla de aplicación básica](start-installation.md) como la
> Información: Tanto la [plantilla de aplicación básica](start-installation.md) como la
[plantilla de aplicación avanzada](tutorial-advanced-app.md), ya incorporan la acción de error y la vista de error.
### Personalizar el Formato de Respuesta de Error <a name="error-format"></a>
El gestor de errores muestra los errores de siguiente la configuración del formato de las
[respuestas](runtime-responses.md). Si el [[yii\web\Response::format response format]] es `html`, se usará la vista de
error o excepción para mostrar los errores tal y como se ha descrito en la anterior subsección. Para otros tipos de
formatos de respuesta, el gestor de errores asignara la representación del array de la excepción a la propiedad
[[yii\web\Response::data]] que posteriormente podrá convertirse al formato deseado. Por ejemplo, si el formato de
El gestor de errores muestra los errores de siguiente la configuración del formato de las
[respuestas](runtime-responses.md). Si el [[yii\web\Response::format response format]] es `html`, se usará la vista de
error o excepción para mostrar los errores tal y como se ha descrito en la anterior subsección. Para otros tipos de
formatos de respuesta, el gestor de errores asignara la representación del array de la excepción a la propiedad
[[yii\web\Response::data]] que posteriormente podrá convertirse al formato deseado. Por ejemplo, si el formato de
respuesta es `json`, obtendremos la siguiente respuesta:
```
......@@ -177,7 +177,7 @@ Content-Type: application/json; charset=UTF-8
}
```
Se puede personalizar el formato de respuestas de error respondiendo al evento `beforeSend` del componente `response`
Se puede personalizar el formato de respuestas de error respondiendo al evento `beforeSend` del componente `response`
en la configuración de la aplicación:
```php
......
Registro de anotaciones
=======================
Yii proporciona un poderoso framework dedicado al registro de anotaciones (logging) que es altamente personalizable y
extensible. Usando este framework se pueden guardar fácilmente anotaciones (logs) de varios tipos de mensajes,
Yii proporciona un poderoso framework dedicado al registro de anotaciones (logging) que es altamente personalizable y
extensible. Usando este framework se pueden guardar fácilmente anotaciones (logs) de varios tipos de mensajes,
filtrarlos, y unificarlos en diferentes destinos que pueden ser archivos, bases de datos o emails.
Usar el framework de registro de anotaciones de Yii involucra los siguientes pasos:
* Registrar [mensajes de las anotaciones](#log-messages) en distintos lugares del código;
* Configurar los [destinos de las anotaciones](#log-targets) en la configuración de la aplicación para filtrar y
* Configurar los [destinos de las anotaciones](#log-targets) en la configuración de la aplicación para filtrar y
exportar los mensajes de las anotaciones;
* Examinar los mensajes filtrados de los las anotaciones exportadas para diferentes destinos
(p. ej. [Yii debugger](tool-debugger.md)).
* Examinar los mensajes filtrados de los las anotaciones exportadas para diferentes destinos
(ej. [Yii debugger](tool-debugger.md)).
En esta sección, se describirán principalmente los dos primeros pasos.
......@@ -20,56 +20,56 @@ En esta sección, se describirán principalmente los dos primeros pasos.
Registrar mensajes de anotación es tan simple como llamar a uno de los siguientes métodos de registro de anotaciones.
* [[Yii::trace()]]: registra un mensaje para trazar el funcionamiento de una sección de código. Se usa principalmente
* [[Yii::trace()]]: registra un mensaje para trazar el funcionamiento de una sección de código. Se usa principalmente
para tareas de desarrollo.
* [[Yii::info()]]: registra un mensaje que transmite información útil.
* [[Yii::warning()]]: registra un mensaje de advertencia que indica que ha sucedido algo inesperado.
* [[Yii::error()]]: registra un error fatal que debe ser investigado tan pronto como sea posible.
Estos métodos registran mensajes de varios *niveles de severidad* y *categorías*. Comparten el mismo registro de
función `function ($message, $category = 'application')`, donde `$message` representa el mensaje del registro que
tiene que ser registrado, mientras que `$category` es la categoría del registro de mensaje. El código del siguiente
Estos métodos registran mensajes de varios *niveles de severidad* y *categorías*. Comparten el mismo registro de
función `function ($message, $category = 'application')`, donde `$message` representa el mensaje del registro que
tiene que ser registrado, mientras que `$category` es la categoría del registro de mensaje. El código del siguiente
ejemplo registra la huella del mensaje para la categoría `application`:
```php
Yii::trace('start calculating average revenue');
```
> Información: Los mensajes de registro pueden ser tanto cadenas de texto como datos complejos, como arrays u objetos.
Es responsabilidad de los [destinos de registros](#log-targets) tratar los mensajes de registro de manera apropiada.
De forma predeterminada, si un mensaje de registro no es una cadena de texto, se exporta como si fuera un string
> Información: Los mensajes de registro pueden ser tanto cadenas de texto como datos complejos, como arrays u objetos.
Es responsabilidad de los [destinos de registros](#log-targets) tratar los mensajes de registro de manera apropiada.
De forma predeterminada, si un mensaje de registro no es una cadena de texto, se exporta como si fuera un string
llamando a [[yii\helpers\VarDumper::export()]].
Para organizar mejor y filtrar los mensajes de registro, se recomienda especificar una categoría apropiada para cada
mensaje de registro. Se puede elegir un sistema de nombres jerárquicos por categorías que facilite a los
[destino de registros](#log-targets) el filtrado de mensajes basándose en categorías. Una manera simple pero
efectiva de organizarlos es usar la constante predefinida (magic constant) de PHP `__METHOD__` como nombre de
Para organizar mejor y filtrar los mensajes de registro, se recomienda especificar una categoría apropiada para cada
mensaje de registro. Se puede elegir un sistema de nombres jerárquicos por categorías que facilite a los
[destino de registros](#log-targets) el filtrado de mensajes basándose en categorías. Una manera simple pero
efectiva de organizarlos es usar la constante predefinida (magic constant) de PHP `__METHOD__` como nombre de
categoría. Además este es el enfoque que se usa en el código del núcleo (core) del framework Yii. Por ejemplo,
```php
Yii::trace('start calculating average revenue', __METHOD__);
```
La constante `__METHOD__` equivale al nombre del método (con el prefijo del nombre completo del nombre de clase) donde
se encuentra la constante. Por ejemplo, es igual a la cadena `'app\controllers\RevenueController::calculate'` si la
La constante `__METHOD__` equivale al nombre del método (con el prefijo del nombre completo del nombre de clase) donde
se encuentra la constante. Por ejemplo, es igual a la cadena `'app\controllers\RevenueController::calculate'` si la
linea anterior de código se llamara dentro de este método.
> Información: Los métodos de registro de anotaciones descritos anteriormente en realidad son accesos directos al
método [[yii\log\Logger::log()|log()]] del [[yii\log\Logger|logger object]] que es un singleton accesible a través
de la expresión `Yii::getLogger()`. Cuando se hayan registrado suficientes mensajes o cuando la aplicación haya
finalizado, el objeto de registro llamará [[yii\log\Dispatcher|message dispatcher]] para enviar los mensajes de
> Información: Los métodos de registro de anotaciones descritos anteriormente en realidad son accesos directos al
método [[yii\log\Logger::log()|log()]] del [[yii\log\Logger|logger object]] que es un singleton accesible a través
de la expresión `Yii::getLogger()`. Cuando se hayan registrado suficientes mensajes o cuando la aplicación haya
finalizado, el objeto de registro llamará [[yii\log\Dispatcher|message dispatcher]] para enviar los mensajes de
registro registrados a los [destiinos de registros](#log-targets).
## Destino de Registros <a name="log-targets"></a>
Un destino de registro es una instancia de la clase [[yii\log\Target]] o de una clase hija. Este filtra los
mensajes de registro por sus niveles de severidad y sus categorías y después los exporta a algún medio. Por ejemplo,
un [[yii\log\DbTarget|database target]] exporta los mensajes de registro filtrados a una tabla de base de datos,
mientras que un [[yii\log\EmailTarget|email target]] exporta los mensajes de registro a una dirección de correo
Un destino de registro es una instancia de la clase [[yii\log\Target]] o de una clase hija. Este filtra los
mensajes de registro por sus niveles de severidad y sus categorías y después los exporta a algún medio. Por ejemplo,
un [[yii\log\DbTarget|database target]] exporta los mensajes de registro filtrados a una tabla de base de datos,
mientras que un [[yii\log\EmailTarget|email target]] exporta los mensajes de registro a una dirección de correo
electrónico específica.
Se pueden registrar múltiples destinos de registros en una aplicación configurándolos en la
[aplicación de componente](structure-application-components.md) `log` dentro de la configuración de aplicación, como
Se pueden registrar múltiples destinos de registros en una aplicación configurándolos en la
[aplicación de componente](structure-application-components.md) `log` dentro de la configuración de aplicación, como
en el siguiente ejemplo:
```php
......@@ -100,17 +100,17 @@ return [
];
```
> Nota: El componente `log` debe cargarse durante el proceso de [bootstrapping](runtime-bootstrapping.md) para que
pueda enviar los mensajes de registro a los destinos inmediatamente. Este es el motivo por el que se lista en el
> Nota: El componente `log` debe cargarse durante el proceso de [bootstrapping](runtime-bootstrapping.md) para que
pueda enviar los mensajes de registro a los destinos inmediatamente. Este es el motivo por el que se lista en el
array `bootstrap` como se muestra más arriba.
En el anterior código, se registran dos destinos de registros en la propiedad [[yii\log\Dispatcher::targets]]
* el primer destino gestiona los errores y las advertencias y las guarda en una tabla de la base de datos;
* el segundo destino gestiona mensajes los mensajes de error de las categorías cuyos nombres empiecen por
* el segundo destino gestiona mensajes los mensajes de error de las categorías cuyos nombres empiecen por
`yii\db\` y los envía por email a las direcciones `admin@example.com` y `developer@example.com`.
Yii incluye los siguientes destinos. En la API de documentación se pueden referencias a estas clases e
Yii incluye los siguientes destinos. En la API de documentación se pueden referencias a estas clases e
información de configuración y uso.
* [[yii\log\DbTarget]]: almacena los mensajes de registro en una tabla de la base de datos.
......@@ -122,8 +122,8 @@ A continuación, se describirá las características más comunes de todos los d
### Filtrado de Mensajes <a name="message-filtering"></a>
Se pueden configurar las propiedades [[yii\log\Target::levels|levels]] y [[yii\log\Target::categories|categories]]
para cada destino de registros, con estas se especifican los niveles de severidad y las categorías de mensajes que
Se pueden configurar las propiedades [[yii\log\Target::levels|levels]] y [[yii\log\Target::categories|categories]]
para cada destino de registros, con estas se especifican los niveles de severidad y las categorías de mensajes que
deberán procesar sus destinos.
La propiedad [[yii\log\Target::levels|levels]] es un array que consta de uno o varios de los siguientes valores:
......@@ -132,29 +132,29 @@ La propiedad [[yii\log\Target::levels|levels]] es un array que consta de uno o v
* `warning`: correspondiente a los mensajes registrados por [[Yii::warning()]].
* `info`: correspondiente a los mensajes registrados por [[Yii::info()]].
* `trace`: correspondiente a los mensajes registrados por [[Yii::trace()]].
* `profile`: correspondiente a los mensajes registrados por [[Yii::beginProfile()]] y [[Yii::endProfile()]], que se
explicará más detalladamente en la subsección [Perfiles](#performance-profiling).
* `profile`: correspondiente a los mensajes registrados por [[Yii::beginProfile()]] y [[Yii::endProfile()]], que se
explicará más detalladamente en la subsección [Perfiles](#performance-profiling).
Si no se especifica la propiedad [[yii\log\Target::levels|levels]], significa que el destino procesará los
Si no se especifica la propiedad [[yii\log\Target::levels|levels]], significa que el destino procesará los
mensajes de *cualquier* nivel de severidad.
La propiedad [[yii\log\Target::categories|categories]] es un array que consta de categorías de mensaje o patrones. El
destino sólo procesará mensajes de las categorías que se puedan encontrar o si coinciden con algún patrón listado
en el array. Un patrón de categoría es un nombre de categoría al que se le añade un asterisco `*` al final. Un nombre
de categoría coincide con un patrón si empieza por el mismo prefijo que el patrón. Por ejemplo,
`yii\db\Command::execute` y `yii\db\Command::query` que se usan como nombres de categoría para los mensajes
La propiedad [[yii\log\Target::categories|categories]] es un array que consta de categorías de mensaje o patrones. El
destino sólo procesará mensajes de las categorías que se puedan encontrar o si coinciden con algún patrón listado
en el array. Un patrón de categoría es un nombre de categoría al que se le añade un asterisco `*` al final. Un nombre
de categoría coincide con un patrón si empieza por el mismo prefijo que el patrón. Por ejemplo,
`yii\db\Command::execute` y `yii\db\Command::query` que se usan como nombres de categoría para los mensajes
registrados en la clase [[yii\db\Command]], coinciden con el patrón `yii\db\*`.
Si no se especifica la propiedad [[yii\log\Target::categories|categories]], significa que el destino procesará
Si no se especifica la propiedad [[yii\log\Target::categories|categories]], significa que el destino procesará
los mensajes de *todas* las categorías.
Además añadiendo las categorías en listas blancas (whitelisting) mediante la propiedad
[[yii\log\Target::categories|categories]], también se pueden añadir ciertas categorías en listas negras (blacklist)
configurando la propiedad [[yii\log\Target::except|except]]. Si se encuentra la categoría de un mensaje o coincide
Además añadiendo las categorías en listas blancas (whitelisting) mediante la propiedad
[[yii\log\Target::categories|categories]], también se pueden añadir ciertas categorías en listas negras (blacklist)
configurando la propiedad [[yii\log\Target::except|except]]. Si se encuentra la categoría de un mensaje o coincide
algún patrón con esta propiedad, NO será procesada por el destino.
La siguiente configuración de destinos especifica que el destino solo debe procesar los mensajes de error y
de advertencia de las categorías que coincidan con alguno de los siguientes patrones `yii\db\*` o
La siguiente configuración de destinos especifica que el destino solo debe procesar los mensajes de error y
de advertencia de las categorías que coincidan con alguno de los siguientes patrones `yii\db\*` o
`yii\web\HttpException:*`, pero no con `yii\web\HttpException:404`.
```php
......@@ -171,31 +171,31 @@ de advertencia de las categorías que coincidan con alguno de los siguientes pat
]
```
> Información: Cuando se captura una excepción de tipo HTTP por el [gestor de errores](runtime-handling-errors.md), se
registrará un mensaje de error con el nombre de categoría con formato `yii\web\HttpException:ErrorCode`. Por
ejemplo, la excepción [[yii\web\NotFoundHttpException]] causará un mensaje de error del tipo
> Información: Cuando se captura una excepción de tipo HTTP por el [gestor de errores](runtime-handling-errors.md), se
registrará un mensaje de error con el nombre de categoría con formato `yii\web\HttpException:ErrorCode`. Por
ejemplo, la excepción [[yii\web\NotFoundHttpException]] causará un mensaje de error del tipo
`yii\web\HttpException:404`.
### Formato de los Mensajes <a name="message-formatting"></a>
Los destinos exportan los mensajes de registro filtrados en cierto formato. Por ejemplo, is se instala un
destino de registros de la calse [[yii\log\FileTarget]], encontraremos un registro similar en el archivo de
Los destinos exportan los mensajes de registro filtrados en cierto formato. Por ejemplo, is se instala un
destino de registros de la calse [[yii\log\FileTarget]], encontraremos un registro similar en el archivo de
registro `runtime/log/app.log`:
```
2014-10-04 18:10:15 [::1][][-][trace][yii\base\Module::getModule] Loading module: debug
```
De forma predeterminada los mensajes de registro se formatearan por [[yii\log\Target::formatMessage()]] como en el
De forma predeterminada los mensajes de registro se formatearan por [[yii\log\Target::formatMessage()]] como en el
siguiente ejemplo:
```
Timestamp [IP address][User ID][Session ID][Severity Level][Category] Message Text
```
Se puede personalizar el formato configurando la propiedad [[yii\log\Target::prefix]] que es un PHP ejecutable y
devuelve un prefijo de mensaje personalizado. Por ejemplo, el siguiente código configura un destino de registro
anteponiendo a cada mensaje de registro el ID de usuario (se eliminan la dirección IP y el ID por razones de
Se puede personalizar el formato configurando la propiedad [[yii\log\Target::prefix]] que es un PHP ejecutable y
devuelve un prefijo de mensaje personalizado. Por ejemplo, el siguiente código configura un destino de registro
anteponiendo a cada mensaje de registro el ID de usuario (se eliminan la dirección IP y el ID por razones de
privacidad).
```php
......@@ -209,11 +209,11 @@ privacidad).
]
```
Además de prefijos de mensaje, destinos de registros también añaden alguna información de contexto en cada lote
de mensajes de registro. De forma predeterminada, se incluyen los valores de las siguientes variables globales de
PHP: `$_GET`, `$_POST`, `$_FILES`, `$_COOKIE`, `$_SESSION` y `$_SERVER`. Se puede ajustar el comportamiento
configurando la propiedad [[yii\log\Target::logVars]] con los nombres de las variables globales que se quieran incluir
con el destino del registro. Por ejemplo, la siguiente configuración de destino de registros especifica que
Además de prefijos de mensaje, destinos de registros también añaden alguna información de contexto en cada lote
de mensajes de registro. De forma predeterminada, se incluyen los valores de las siguientes variables globales de
PHP: `$_GET`, `$_POST`, `$_FILES`, `$_COOKIE`, `$_SESSION` y `$_SERVER`. Se puede ajustar el comportamiento
configurando la propiedad [[yii\log\Target::logVars]] con los nombres de las variables globales que se quieran incluir
con el destino del registro. Por ejemplo, la siguiente configuración de destino de registros especifica que
sólo se añadirá al mensaje de registro el valor de la variable `$_SERVER`.
```php
......@@ -223,14 +223,14 @@ sólo se añadirá al mensaje de registro el valor de la variable `$_SERVER`.
]
```
Se puede configurar `logVars` para que sea un array vacío para deshabilitar totalmente la inclusión de información de
contexto. O si se desea implementar un método propio de proporcionar información de contexto se puede sobrescribir el
Se puede configurar `logVars` para que sea un array vacío para deshabilitar totalmente la inclusión de información de
contexto. O si se desea implementar un método propio de proporcionar información de contexto se puede sobrescribir el
método [[yii\log\Target::getContextMessage()]].
### Nivel de Seguimiento de Mensajes <a name="trace-level"></a>
Durante el desarrollo, a veces se quiere visualizar de donde proviene cada mensaje de registro. Se puede lograr
configurando la propiedad [[yii\log\Dispatcher::traceLevel|traceLevel]] del componente `log` como en el siguiente
Durante el desarrollo, a veces se quiere visualizar de donde proviene cada mensaje de registro. Se puede lograr
configurando la propiedad [[yii\log\Dispatcher::traceLevel|traceLevel]] del componente `log` como en el siguiente
ejemplo:
```php
......@@ -245,20 +245,20 @@ return [
];
```
La configuración de aplicación anterior establece el [[yii\log\Dispatcher::traceLevel|traceLevel]] para que sea 3 si
`YII_DEBUG` esta habilitado y 0 si esta deshabilitado. Esto significa que si `YII_DEBUG` esta habilitado, a cada
mensaje de registro se le añadirán como mucho 3 niveles de la pila de llamadas del mensaje que se este registrando; y
La configuración de aplicación anterior establece el [[yii\log\Dispatcher::traceLevel|traceLevel]] para que sea 3 si
`YII_DEBUG` esta habilitado y 0 si esta deshabilitado. Esto significa que si `YII_DEBUG` esta habilitado, a cada
mensaje de registro se le añadirán como mucho 3 niveles de la pila de llamadas del mensaje que se este registrando; y
si `YII_DEBUG` está deshabilitado, no se incluirá información de la pila de llamadas.
> Información: Obtener información de la pila de llamadas no es trivial. Por lo tanto, sólo se debe usar esta
> Información: Obtener información de la pila de llamadas no es trivial. Por lo tanto, sólo se debe usar esta
característica durante el desarrollo o cuando se depura la aplicación.
### Liberación (Flushing) y Exportación de Mensajes <a name="flushing-exporting"></a>
Como se ha comentado anteriormente, los mensajes de registro se mantienen en un array por el
[[yii\log\Logger|logger object]]. Para limitar el consumo de memoria de este array, el componente encargado del
registro de mensajes enviará los mensajes registrados a los [destinos de registros](#log-targets) cada vez que el
array acumule un cierto número de mensajes de registro. Se puede personalizar el número configurando la propiedad
Como se ha comentado anteriormente, los mensajes de registro se mantienen en un array por el
[[yii\log\Logger|logger object]]. Para limitar el consumo de memoria de este array, el componente encargado del
registro de mensajes enviará los mensajes registrados a los [destinos de registros](#log-targets) cada vez que el
array acumule un cierto número de mensajes de registro. Se puede personalizar el número configurando la propiedad
[[yii\log\Dispatcher::flushInterval|flushInterval]] del componente `log`:
```php
......@@ -273,13 +273,13 @@ return [
];
```
> Información: También se produce la liberación de mensajes cuando la aplicación finaliza, esto asegura que los
> Información: También se produce la liberación de mensajes cuando la aplicación finaliza, esto asegura que los
destinos de los registros reciban los mensajes de registro.
Cuando el [[yii\log\Logger|logger object]] libera los mensajes de registro enviándolos a los
[destinos de registros](#log-targets), estos no se exportan inmediatamente. La exportación de mensajes solo se
produce cuando un destino de registros acumula un cierto número de mensajes filtrados. Se puede personalizar este
número configurando la propiedad [[yii\log\Target::exportInterval|exportInterval]] de un
Cuando el [[yii\log\Logger|logger object]] libera los mensajes de registro enviándolos a los
[destinos de registros](#log-targets), estos no se exportan inmediatamente. La exportación de mensajes solo se
produce cuando un destino de registros acumula un cierto número de mensajes filtrados. Se puede personalizar este
número configurando la propiedad [[yii\log\Target::exportInterval|exportInterval]] de un
[destinos de registros](#log-targets) individual, como se muestra a continuación,
```php
......@@ -289,11 +289,11 @@ número configurando la propiedad [[yii\log\Target::exportInterval|exportInterva
]
```
Debido al nivel de configuración de la liberación y exportación de mensajes, de forma predeterminada cuando se llama a
`Yii::trace()` o cualquier otro método de registro de mensajes, NO veremos el registro de mensaje inmediatamente en
los destinos de registros. Esto podría ser un problema para algunas aplicaciones de consola de ejecución
prolongada (long-running). Para hacer que los mensajes de registro aparezcan inmediatamente en los destinos de
registro se deben establecer [[yii\log\Dispatcher::flushInterval|flushInterval]] y
Debido al nivel de configuración de la liberación y exportación de mensajes, de forma predeterminada cuando se llama a
`Yii::trace()` o cualquier otro método de registro de mensajes, NO veremos el registro de mensaje inmediatamente en
los destinos de registros. Esto podría ser un problema para algunas aplicaciones de consola de ejecución
prolongada (long-running). Para hacer que los mensajes de registro aparezcan inmediatamente en los destinos de
registro se deben establecer [[yii\log\Dispatcher::flushInterval|flushInterval]] y
[[yii\log\Target::exportInterval|exportInterval]] para que tengan valor 1 como se muestra a continuación:
```php
......@@ -317,15 +317,15 @@ return [
### Conmutación de Destinos de Registros <a name="toggling-log-targets"></a>
Se puede habilitar o deshabilitar un destino de registro configuración su propiedad
[[yii\log\Target::enabled|enabled]]. Esto se puede llevar a cabo a mediante la configuración del destino de
Se puede habilitar o deshabilitar un destino de registro configuración su propiedad
[[yii\log\Target::enabled|enabled]]. Esto se puede llevar a cabo a mediante la configuración del destino de
registros o con la siguiente declaración PHP de código:
```php
Yii::$app->log->targets['file']->enabled = false;
```
El código anterior requiere que se asocie un destino como `file`, como se muestra a continuación usando las
El código anterior requiere que se asocie un destino como `file`, como se muestra a continuación usando las
claves de texto en el array `targets`:
```php
......@@ -348,19 +348,19 @@ return [
### Creación de Nuevos Destinos <a name="new-targets"></a>
La creación de nuevas clases de destinos de registro es muy simple. Se necesita implementar el método
[[yii\log\Target::export()]] enviando el contenido del array [[yii\log\Target::messages]] al medio designado. Se puede
llamar al método [[yii\log\Target::formatMessage()]] para formatear los mensajes. Se pueden encontrar más detalles de
La creación de nuevas clases de destinos de registro es muy simple. Se necesita implementar el método
[[yii\log\Target::export()]] enviando el contenido del array [[yii\log\Target::messages]] al medio designado. Se puede
llamar al método [[yii\log\Target::formatMessage()]] para formatear los mensajes. Se pueden encontrar más detalles de
destinos de registros en las clases incluidas en la distribución de Yii.
## Perfilado de Rendimiento <a name="performance-profiling"></a>
El Perfilado de rendimiento es un tipo especial de registro de mensajes que se usa para medir el tiempo que tardan en
ejecutarse ciertos bloques de código y encontrar donde están los cuellos de botella de rendimiento. Por ejemplo, la
clase [[yii\db\Command]] utiliza el perfilado de rendimiento para encontrar conocer el tiempo que tarda cada consulta
El Perfilado de rendimiento es un tipo especial de registro de mensajes que se usa para medir el tiempo que tardan en
ejecutarse ciertos bloques de código y encontrar donde están los cuellos de botella de rendimiento. Por ejemplo, la
clase [[yii\db\Command]] utiliza el perfilado de rendimiento para encontrar conocer el tiempo que tarda cada consulta
a la base de datos.
Para usar el perfilado de rendimiento, primero debemos identificar los bloques de código que tienen que ser
Para usar el perfilado de rendimiento, primero debemos identificar los bloques de código que tienen que ser
perfilados, para poder enmarcar su contenido como en el siguiente ejemplo:
```php
......@@ -371,8 +371,8 @@ perfilados, para poder enmarcar su contenido como en el siguiente ejemplo:
\Yii::endProfile('myBenchmark');
```
Donde `myBenchmark` representa un token único para identificar el bloque de código. Después cuando se examine el
resulte del perfilado, se podrá usar este token para encontrar el tiempo que ha necesitado el correspondiente bloque
Donde `myBenchmark` representa un token único para identificar el bloque de código. Después cuando se examine el
resulte del perfilado, se podrá usar este token para encontrar el tiempo que ha necesitado el correspondiente bloque
de código.
Es importante asegurarse de que los pares de `beginProfile` y `endProfile` estén bien anidados. Por ejemplo,
......@@ -389,10 +389,10 @@ Es importante asegurarse de que los pares de `beginProfile` y `endProfile` esté
\Yii::endProfile('block1');
```
Si nos dejamos el `\Yii::endProfile('block1')` o lo intercambiamos `\Yii::endProfile('block1')` con
Si nos dejamos el `\Yii::endProfile('block1')` o lo intercambiamos `\Yii::endProfile('block1')` con
`\Yii::endProfile('block2')`, el perfilado de rendimiento no funcionará.
Se registra un mensaje de registro con el nivel de severidad `profile` para cada bloque de código que se haya
perfilado. Se puede configurar el [destino del registro](#log-targets) para reunir todos los mensajes y exportarlos.
El [depurador de Yii](tool-debugger.md) incluye un panel de perfilado de rendimiento que muestra los resultados de
Se registra un mensaje de registro con el nivel de severidad `profile` para cada bloque de código que se haya
perfilado. Se puede configurar el [destino del registro](#log-targets) para reunir todos los mensajes y exportarlos.
El [depurador de Yii](tool-debugger.md) incluye un panel de perfilado de rendimiento que muestra los resultados de
perfilado.
\ No newline at end of file
Assets
======
Un asset en Yii es un archivo al que se puede hacer referencia en una página Web. Puede ser un archivo CSS, un archivo
JavaScript, una imagen o un archivo de vídeo, etc. Los assets se encuentran en los directorios públicos de la web y se
Un asset en Yii es un archivo al que se puede hacer referencia en una página Web. Puede ser un archivo CSS, un archivo
JavaScript, una imagen o un archivo de vídeo, etc. Los assets se encuentran en los directorios públicos de la web y se
sirven directamente por los servidores Web.
A menudo es preferible gestionar los assets mediante programación. Por ejemplo, cuando se usa el widget
[[yii\jui\DatePicker]] en una página, éste incluirá automáticamente los archivos CSS y JavaScript requeridos, en vez
de tener que buscar los archivos e incluirlos manualmente. Y cuando se actualice el widget a una nueva versión, ésta
A menudo es preferible gestionar los assets mediante programación. Por ejemplo, cuando se usa el widget
[[yii\jui\DatePicker]] en una página, éste incluirá automáticamente los archivos CSS y JavaScript requeridos, en vez
de tener que buscar los archivos e incluirlos manualmente. Y cuando se actualice el widget a una nueva versión, ésta
usará de forma automática la nueva versión de los archivos asset.
En este tutorial, se describirá la poderosa capacidad que proporciona la gestión de assets en Yii.
## Asset Bundles <a name="asset-bundles"></a>
Yii gestiona los assets en unidades de *asset bundle*. Un asset bundle es simplemente un conjunto de assets
localizados en un directorio. Cuando se registra un asset bundle en una [vista](structure-views.md), éste incluirá los
Yii gestiona los assets en unidades de *asset bundle*. Un asset bundle es simplemente un conjunto de assets
localizados en un directorio. Cuando se registra un asset bundle en una [vista](structure-views.md), éste incluirá los
archivos CSS y JavaScript del bundle en la página Web renderizada.
## Definición de Asset Bundles <a name="defining-asset-bundles"></a>
Los asset bundles son descritos como clases PHP que extienden a [[yii\web\AssetBundle]]. El nombre del bundle es
simplemente su correspondiente nombre de la classe PHP que debe ser [autocargable](concept-autoloading.md). En una
clase asset bundle, lo más habitual es especificar donde se encuentran los archivos asset, que archivos CSS y
Los asset bundles son descritos como clases PHP que extienden a [[yii\web\AssetBundle]]. El nombre del bundle es
simplemente su correspondiente nombre de la classe PHP que debe ser [autocargable](concept-autoloading.md). En una
clase asset bundle, lo más habitual es especificar donde se encuentran los archivos asset, que archivos CSS y
JavaScript contiene el bundle, y como depende éste bundle de otros bundles.
El siguiente código define el asset bundle principal que se usa en
El siguiente código define el asset bundle principal que se usa en
[la plantilla de aplicación básica](start-installation.md):
```php
......@@ -50,42 +50,42 @@ class AppAsset extends AssetBundle
}
```
La anterior clase `AppAsset` especifica que los archivos asset se encuentran en el directorio `@webroot` que
corresponde a la URL `@web`; el bundle contiene un único archivo CSS `css/site.css` y ningún archivo JavaScript;
el bundle depende de otros dos bundles: [[yii\web\YiiAsset]] y [[yii\bootstrap\BootstrapAsset]].
La anterior clase `AppAsset` especifica que los archivos asset se encuentran en el directorio `@webroot` que
corresponde a la URL `@web`; el bundle contiene un único archivo CSS `css/site.css` y ningún archivo JavaScript;
el bundle depende de otros dos bundles: [[yii\web\YiiAsset]] y [[yii\bootstrap\BootstrapAsset]].
A continuación se explicarán más detalladamente las propiedades del [[yii\web\AssetBundle]]:
* [[yii\web\AssetBundle::sourcePath|sourcePath]]: especifica el directorio raiz que contiene los archivos asset en el
bundle. Si no, se deben especificar las propiedades [[yii\web\AssetBundle::basePath|basePath]] y
* [[yii\web\AssetBundle::sourcePath|sourcePath]]: especifica el directorio raiz que contiene los archivos asset en el
bundle. Si no, se deben especificar las propiedades [[yii\web\AssetBundle::basePath|basePath]] y
[[yii\web\AssetBundle::baseUrl|baseUrl]], en su lugar. Se pueden usar [alias de ruta](concept-aliases.md).
* [[yii\web\AssetBundle::basePath|basePath]]: especifica el directorio Web público que contiene los archivos assets de
este bundle. Cuando se especifica la propiedad [[yii\web\AssetBundle::sourcePath|sourcePath]], el [gestor de
assets](#asset-manager) publicara los assets de este bundle en un directorio Web publico y sobrescribirá la
propiedad en consecuencia. Se debe establecer esta propiedad si los archivos asset ya se encuentran en un directorio
* [[yii\web\AssetBundle::basePath|basePath]]: especifica el directorio Web público que contiene los archivos assets de
este bundle. Cuando se especifica la propiedad [[yii\web\AssetBundle::sourcePath|sourcePath]], el [gestor de
assets](#asset-manager) publicara los assets de este bundle en un directorio Web publico y sobrescribirá la
propiedad en consecuencia. Se debe establecer esta propiedad si los archivos asset ya se encuentran en un directorio
Web publico y no necesitan ser publicados. Se pueden usar [alias de ruta](concept-aliases.md).
* [[yii\web\AssetBundle::baseUrl|baseUrl]]: especifica la URL correspondiente al directorio
[[yii\web\AssetBundle::basePath|basePath]]. Como en [yii\web\AssetBundle::basePath|basePath]], si se especifica la
propiedad [[yii\web\AssetBundle::sourcePath|sourcePath]], el [gestor de assets](#asset-manager) publicara los assets
[[yii\web\AssetBundle::basePath|basePath]]. Como en [yii\web\AssetBundle::basePath|basePath]], si se especifica la
propiedad [[yii\web\AssetBundle::sourcePath|sourcePath]], el [gestor de assets](#asset-manager) publicara los assets
y sobrescribirá esta propiedad en consecuencia. Se pueden usar [alias de ruta](concept-aliases.md).
* [[yii\web\AssetBundle::js|js]]: un array lista los archivos JavaScript que contiene este bundle. Tenga en cuenta que
solo deben usarse las barras invertidas "/" como separadores de directorios. Cada archivo Javascrpt se puede
* [[yii\web\AssetBundle::js|js]]: un array lista los archivos JavaScript que contiene este bundle. Tenga en cuenta que
solo deben usarse las barras invertidas "/" como separadores de directorios. Cada archivo Javascrpt se puede
especificar en uno de los siguientes formatos:
- una ruta relativa que represente un archivo local JavaScript (p. ej. `js/main.js`). La ruta actual del fichero
se puede determinar anteponiendo [[yii\web\AssetManager::basePath]] a la ruta relativa, y la URL actual de un
- una ruta relativa que represente un archivo local JavaScript (ej. `js/main.js`). La ruta actual del fichero
se puede determinar anteponiendo [[yii\web\AssetManager::basePath]] a la ruta relativa, y la URL actual de un
archivo puede ser determinada anteponiendo [[yii\web\AssetManager::baseUrl]] a la ruta relativa.
- un URL absoluta que represente un archivo JavaScript externo. Por ejemplo,
`http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js` o
- un URL absoluta que represente un archivo JavaScript externo. Por ejemplo,
`http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js` o
`//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js`.
* [[yii\web\AssetBundle::css|css]]: un array que lista los archivos CSS que contiene el este bundle. El formato de este
array es el mismo que el de [[yii\web\AssetBundle::js|js]].
* [[yii\web\AssetBundle::depends|depends]]: un array que lista los nombres de los asset bundles de los que depende este
asset bundle (para explicarlo brevemente).
* [[yii\web\AssetBundle::jsOptions|jsOptions]]: especifica las opciones que se enviaran al método
* [[yii\web\AssetBundle::jsOptions|jsOptions]]: especifica las opciones que se enviaran al método
[[yii\web\View::registerJsFile()]] cuando se le llame para registrar *todos* los archivos JavaScript de este bundle.
* [[yii\web\AssetBundle::cssOptions|cssOptions]]: especifica las opciones que se enviaran al método
* [[yii\web\AssetBundle::cssOptions|cssOptions]]: especifica las opciones que se enviaran al método
[[yii\web\View::registerCssFile()]] cuando se le llame para registrar *todos* los archivos CSS de este bundle.
* [[yii\web\AssetBundle::publishOptions|publishOptions]]: especifica las opciones que se enviaran al método
[[yii\web\AssetManager::publish()]] cuando se le llame para publicar los archivos de los assets fuente a un
* [[yii\web\AssetBundle::publishOptions|publishOptions]]: especifica las opciones que se enviaran al método
[[yii\web\AssetManager::publish()]] cuando se le llame para publicar los archivos de los assets fuente a un
directorio Web.
Solo se usa si se especifica la propiedad [[yii\web\AssetBundle::sourcePath|sourcePath]].
......@@ -93,56 +93,56 @@ Solo se usa si se especifica la propiedad [[yii\web\AssetBundle::sourcePath|sour
Según la localización de los assets, se pueden clasificar como:
* assets fuente (source assets): los assets se encuentran junto con el código fuente PHP, al que no se puede acceder
directamente a través de la Web. Para usar los assets fuente en una página, deben ser copiados en un directorio
publico y transformados en los llamados assets publicados. El proceso se llama *publicación de assets* que será
* assets fuente (source assets): los assets se encuentran junto con el código fuente PHP, al que no se puede acceder
directamente a través de la Web. Para usar los assets fuente en una página, deben ser copiados en un directorio
publico y transformados en los llamados assets publicados. El proceso se llama *publicación de assets* que será
descrito a continuación.
* assets publicados (published assets): los archivos assets se encuentran en el directorio Web y son accesibles via Web.
* assets externos (external assets): los archivos assets se encuentran en un servidor Web diferente al de la aplicación.
Cuando se define una clase asset bundle, si se especifica la propiedad [[yii\web\AssetBundle::sourcePath|sourcePath]],
significa que cualquier asset listado que use rutas relativas será considerado como un asset fuente. Si no se
especifica la propiedad, significa que los assets son assets publicados (se deben especificar
[[yii\web\AssetBundle::basePath|basePath]] y
Cuando se define una clase asset bundle, si se especifica la propiedad [[yii\web\AssetBundle::sourcePath|sourcePath]],
significa que cualquier asset listado que use rutas relativas será considerado como un asset fuente. Si no se
especifica la propiedad, significa que los assets son assets publicados (se deben especificar
[[yii\web\AssetBundle::basePath|basePath]] y
[[yii\web\AssetBundle::baseUrl|baseUrl]] para hacerle saber a Yii dónde se encuentran.)
Se recomienda ubicar los assets que correspondan a la aplicación en un directorio Web para evitar publicaciones de
assets innecesarias. Por esto en el anterior ejemplo `AppAsset` especifica [[yii\web\AssetBundle::basePath|basePath]]
Se recomienda ubicar los assets que correspondan a la aplicación en un directorio Web para evitar publicaciones de
assets innecesarias. Por esto en el anterior ejemplo `AppAsset` especifica [[yii\web\AssetBundle::basePath|basePath]]
en vez de [[yii\web\AssetBundle::sourcePath|sourcePath]].
Para las [extensiones](structure-extensions.md), por el hecho de que sus assets se encuentran junto con el código
fuente, en directorios que no son accesibles para la Web, se tiene que especificar la propiedad
Para las [extensiones](structure-extensions.md), por el hecho de que sus assets se encuentran junto con el código
fuente, en directorios que no son accesibles para la Web, se tiene que especificar la propiedad
[[yii\web\AssetBundle::sourcePath|sourcePath]] cuando se definan clases asset bundle para ellas.
> Nota: No se debe usar `@webroot/assets` como [yii\web\AssetBundle::sourcePath|source path]]. Este directorio se usa
por defecto por el [[yii\web\AssetManager|asset manager]] para guardar los archivos asset publicados temporalmente y
> Nota: No se debe usar `@webroot/assets` como [yii\web\AssetBundle::sourcePath|source path]]. Este directorio se usa
por defecto por el [[yii\web\AssetManager|asset manager]] para guardar los archivos asset publicados temporalmente y
pueden ser eliminados.
### Dependencias de los Asset <a name="asset-dependencies"></a>
Cuando se incluyen múltiples archivos CSS o JavaScript en una página Web, tienen que cumplir ciertas órdenes para
evitar problemas de sobrescritura. Por ejemplo, si se usa un widget jQuery UI en una página Web, tenemos que
asegurarnos de que el archivo JavaScript jQuery se incluya antes que el archivo JavaScript jQuery UI. A esto se le
Cuando se incluyen múltiples archivos CSS o JavaScript en una página Web, tienen que cumplir ciertas órdenes para
evitar problemas de sobrescritura. Por ejemplo, si se usa un widget jQuery UI en una página Web, tenemos que
asegurarnos de que el archivo JavaScript jQuery se incluya antes que el archivo JavaScript jQuery UI. A esto se le
llama ordenar las dependencias entre archivos.
Las dependencias de los assets se especifican principalmente a través de la propiedad [[yii\AssetBundle::depends]].
En el ejemplo `AppAsset`, el asset bundle depende de otros dos asset bundles [[yii\web\YiiAsset]] y
[[yii\bootstrap\BootstrapAsset]], que significa que los archivos CSS y JavaScript en `AppAsset` se incluirán *después*
Las dependencias de los assets se especifican principalmente a través de la propiedad [[yii\AssetBundle::depends]].
En el ejemplo `AppAsset`, el asset bundle depende de otros dos asset bundles [[yii\web\YiiAsset]] y
[[yii\bootstrap\BootstrapAsset]], que significa que los archivos CSS y JavaScript en `AppAsset` se incluirán *después*
que los archivos de los dos bundles dependientes.
Las dependencias son transitivas. Esto significa, que si un bundle A depende de un bundle B que depende de C, A
Las dependencias son transitivas. Esto significa, que si un bundle A depende de un bundle B que depende de C, A
dependerá de C, también.
### Opciones de los Assets <a name="asset-options"></a>
Se pueden especificar las propiedades [[yii\web\AssetBundle::cssOptions|cssOptions]] y
[[yii\web\AssetBundle::jsOptions|jsOptions]] para personalizar la forma en que los archivos CSS y JavaScript serán
incluidos en una página. Los valores de estas propiedades serán enviadas a los metodos
[[yii\web\View::registerCssFile()]] y [[yii\web\View::registerJsFile()]], respectivamente cuando las
Se pueden especificar las propiedades [[yii\web\AssetBundle::cssOptions|cssOptions]] y
[[yii\web\AssetBundle::jsOptions|jsOptions]] para personalizar la forma en que los archivos CSS y JavaScript serán
incluidos en una página. Los valores de estas propiedades serán enviadas a los metodos
[[yii\web\View::registerCssFile()]] y [[yii\web\View::registerJsFile()]], respectivamente cuando las
[vistas](structure-views.md) los llamen para incluir los archivos CSS y JavaScript.
> Nota: Las opciones que se especifican en una clase bundle se aplican a *todos* los archivos CSS/JavaScript de un
bundle. Si se quiere usar diferentes opciones para diferentes archivos, se deben crear assets bundles separados y
> Nota: Las opciones que se especifican en una clase bundle se aplican a *todos* los archivos CSS/JavaScript de un
bundle. Si se quiere usar diferentes opciones para diferentes archivos, se deben crear assets bundles separados y
usar un conjunto de opciones para cada bundle.
Por ejemplo, para incluir una archivo CSS condicionalmente para navegadores que como IE9 o anteriores, se puede usar la
......@@ -175,26 +175,26 @@ public $jsOptions = ['position' => \yii\web\View::POS_HEAD];
### Assets Bower y NPM <a name="bower-npm-assets"></a>
La mayoría de paquetes JavaScript/CSS se gestionan con [Bower](http://bower.io/) y/o [NPM](https://www.npmjs.org/).
La mayoría de paquetes JavaScript/CSS se gestionan con [Bower](http://bower.io/) y/o [NPM](https://www.npmjs.org/).
Si tu aplicación o extensión usa estos paquetes, se recomienda seguir los siguientes pasos para gestionar los assets en
la librería:
1. Modificar el archivo `composer.json` de tu aplicación o extensión e introducir el paquete en la lista `require`.
Se debe usar `bower-asset/PackageName` (para paquetes Bower) o `npm-asset/PackageName` (para paquetes NPM) para
1. Modificar el archivo `composer.json` de tu aplicación o extensión e introducir el paquete en la lista `require`.
Se debe usar `bower-asset/PackageName` (para paquetes Bower) o `npm-asset/PackageName` (para paquetes NPM) para
referenciar la librería.
2. Crear una clase asset bundle y listar los archivos JavaScript/CSS que se planea usar en la aplicación o extensión.
Se debe especificar la propiedad [[yii\web\AssetBundle::sourcePath|sourcePath]] como `@bower\PackageName` o
2. Crear una clase asset bundle y listar los archivos JavaScript/CSS que se planea usar en la aplicación o extensión.
Se debe especificar la propiedad [[yii\web\AssetBundle::sourcePath|sourcePath]] como `@bower\PackageName` o
`@npm\PackageName`. Esto se debe a que Composer instalará el paquete Bower o NPM en el correspondiente directorio de
este alias.
> Nota: Algunos paquetes pueden distribuir sus archivos en subdirectorios. Si es el caso, se debe especificar el
subdirectorio como valor del [[yii\web\AssetBundle::sourcePath|sourcePath]]. Por ejemplo, [[yii\web\JqueryAsset]]
> Nota: Algunos paquetes pueden distribuir sus archivos en subdirectorios. Si es el caso, se debe especificar el
subdirectorio como valor del [[yii\web\AssetBundle::sourcePath|sourcePath]]. Por ejemplo, [[yii\web\JqueryAsset]]
usa `@bower/jquery/dist` en vez de `@bower/jquery`.
## Uso de Asset Bundles <a name="using-asset-bundles"></a>
Para usar un asset bundle, debe registrarse con una [vista](structure-views.md) llamando al método
[[yii\web\AssetBundle::register()]]. Por ejemplo, en plantilla de vista se puede registrar un asset bundle como en el
Para usar un asset bundle, debe registrarse con una [vista](structure-views.md) llamando al método
[[yii\web\AssetBundle::register()]]. Por ejemplo, en plantilla de vista se puede registrar un asset bundle como en el
siguiente ejemplo:
```php
......@@ -202,28 +202,28 @@ use app\assets\AppAsset;
AppAsset::register($this); // $this representa el objeto vista
```
> Información: El método [[yii\web\AssetBundle::register()]] devuelve un objeto asset bundle que contiene la
información acerca de los assets publicados, tales como [[yii\web\AssetBundle::basePath|basePath]] o
> Información: El método [[yii\web\AssetBundle::register()]] devuelve un objeto asset bundle que contiene la
información acerca de los assets publicados, tales como [[yii\web\AssetBundle::basePath|basePath]] o
[[yii\web\AssetBundle::baseUrl|baseUrl]].
Si se registra un asset bundle en otro lugar, se debe proporcionar la vista necesaria al objeto. Por ejemplo, para
registrar un asset bundle en una clase [widget](structure-widgets.md), se puede obtener el objeto vista mediante
Si se registra un asset bundle en otro lugar, se debe proporcionar la vista necesaria al objeto. Por ejemplo, para
registrar un asset bundle en una clase [widget](structure-widgets.md), se puede obtener el objeto vista mediante
`$this->view`.
Cuando se registra un asset bundle con una vista, por detrás, Yii registrará todos sus asset bundles dependientes.
Y si un asset bundle se encuentra en un directorio inaccesible por la Web, éste será publicado a un directorio Web
publico. Después cuando la vista renderice una página, se generarán las etiquetas (tags) `<link>` y `<script>` para
los archivos CSS y JavaScript listados en los bundles registrados. El orden de estas etiquetas será determinado por
las dependencias entre los bundles registrados y los otros assets listados en las propiedades
Cuando se registra un asset bundle con una vista, por detrás, Yii registrará todos sus asset bundles dependientes.
Y si un asset bundle se encuentra en un directorio inaccesible por la Web, éste será publicado a un directorio Web
publico. Después cuando la vista renderice una página, se generarán las etiquetas (tags) `<link>` y `<script>` para
los archivos CSS y JavaScript listados en los bundles registrados. El orden de estas etiquetas será determinado por
las dependencias entre los bundles registrados y los otros assets listados en las propiedades
[[yii\web\AssetBundle::css]] y [[yii\web\AssetBundle::js]].
### Personalización de Asset Bundles <a name="customizing-asset-bundles"></a>
Yii gestiona los asset bundles a través de un componentes de aplicación llamado `assetManager` que está implementado
por [[yii\web\AssetManager]]. Configurando la propiedad [[yii\web\AssetManager::bundles]], se puede personalizar el
Yii gestiona los asset bundles a través de un componentes de aplicación llamado `assetManager` que está implementado
por [[yii\web\AssetManager]]. Configurando la propiedad [[yii\web\AssetManager::bundles]], se puede personalizar el
comportamiento (behavior) de un asset bundle. Por ejemplo, de forma predeterminada, el asset bundle [[yii\web\Jquery]]
, utiliza el archivo `jquery.js` desde el paquete Bower instalado. Para mejorar la disponibilidad y el rendimiento se
puede querer usar la versión alojada por Google. Ésta puede ser obtenida configurando `assetManager` en la
, utiliza el archivo `jquery.js` desde el paquete Bower instalado. Para mejorar la disponibilidad y el rendimiento se
puede querer usar la versión alojada por Google. Ésta puede ser obtenida configurando `assetManager` en la
configuración de la aplicación como en el siguiente ejemplo:
```php
......@@ -244,11 +244,11 @@ return [
];
```
Del mismo modo, se pueden configurar múltiples asset bundles a través de [[yii\web\AssetManager::bundles]]. Las claves
Del mismo modo, se pueden configurar múltiples asset bundles a través de [[yii\web\AssetManager::bundles]]. Las claves
del array deben ser los nombres de clase (sin la primera barra invertida) de los asset bundles, y los valores del array
deben ser las correspondientes [configuraciones de arrays](concept-configurations.md).
> Consejo: Se puede de elegir condicionalmente que assets se van a usar en un asset bundle. El siguiente ejemplo
> Consejo: Se puede de elegir condicionalmente que assets se van a usar en un asset bundle. El siguiente ejemplo
muestra como usar `jquery.js` en el entorno de desarrollo y `jquery.min.js` en los otros casos:
>
> ```php
......@@ -259,8 +259,8 @@ muestra como usar `jquery.js` en el entorno de desarrollo y `jquery.min.js` en l
> ],
> ```
Se puede deshabilitar uno o más asset bundles asociando `false` a los nombres de los asset bundles que se quieran
deshabilitar. Cuando se registra un asset bundle deshabilitado con una vista, ninguno de sus bundles dependientes será
Se puede deshabilitar uno o más asset bundles asociando `false` a los nombres de los asset bundles que se quieran
deshabilitar. Cuando se registra un asset bundle deshabilitado con una vista, ninguno de sus bundles dependientes será
registrado, y la vista tampoco incluirá ningún asset del bundle en la página que se renderice.
Por ejemplo, para deshabilitar [[yii\web\JqueryAsset]], se puede usar la siguiente configuración:
......@@ -281,10 +281,10 @@ Además se pueden deshabilitar *todos* los asset bundles asignando `false` a [[y
### Mapeo de Assets (Asset Mapping) <a name="asset-mapping"></a>
A veces se puede querer "arreglar" rutas de archivos incorrectos/incompatibles usadas en múltiples asset bundles.
Por ejemplo, el bundle A usa `jquery.min.js` con versión 1.11.1, y el bundle B usa `jquery.js` con versión 2.11.1.
Mientras que se puede solucionar el problema personalizando cada bundle, una forma más fácil, es usar la
característica *asset map* para mapear los assets incorrectos a los deseados. Para hacerlo, se tiene que configurar la
A veces se puede querer "arreglar" rutas de archivos incorrectos/incompatibles usadas en múltiples asset bundles.
Por ejemplo, el bundle A usa `jquery.min.js` con versión 1.11.1, y el bundle B usa `jquery.js` con versión 2.11.1.
Mientras que se puede solucionar el problema personalizando cada bundle, una forma más fácil, es usar la
característica *asset map* para mapear los assets incorrectos a los deseados. Para hacerlo, se tiene que configurar la
propiedad [[yii\web\AssetManager::assetMap]] como en el siguiente ejemplo:
```php
......@@ -300,29 +300,29 @@ return [
];
```
Las claves de [[yii\web\AssetManager::assetMap|assetmMap]] son los nombres de los assets que se quieren corregir,
y los valores son las rutas de los assets deseados. Cuando se registra un asset bundle con una vista, cada archivo de
Las claves de [[yii\web\AssetManager::assetMap|assetmMap]] son los nombres de los assets que se quieren corregir,
y los valores son las rutas de los assets deseados. Cuando se registra un asset bundle con una vista, cada archivo de
asset relativo de [[yii\web\AssetBundle::css|css]] y [[yii\web\AssetBundle::js|js]] serán contrastados con este mapa.
Si se detecta que alguna de estas claves es la última parte de un archivo asset (prefijado con
Si se detecta que alguna de estas claves es la última parte de un archivo asset (prefijado con
[[yii\web\AssetBundle::sourcePath]], si esta disponible), el correspondiente valor reemplazará el asset y será
registrado con la vista.
Por ejemplo, un archivo asset `mi/ruta/a/jquery.js` concuerda con la clave `jquery.js`.
> Nota: Sólo los assets especificados usando rutas relativas están sujetos al mapeo de assets. Y las rutas de los
> Nota: Sólo los assets especificados usando rutas relativas están sujetos al mapeo de assets. Y las rutas de los
assets destino deben ser tanto URLs absolutas o rutas relativas a [[yii\web\AssetManager::basePath]].
### Publicación de Asset <a name="asset-publishing"></a>
Como se ha comentado anteriormente, si un asset bundle se encuentra en un directorio que no es accesible por la Web,
este asset será copiado a un directorio Web cuando se registre el bundle con una vista. Este proceso se llama
Como se ha comentado anteriormente, si un asset bundle se encuentra en un directorio que no es accesible por la Web,
este asset será copiado a un directorio Web cuando se registre el bundle con una vista. Este proceso se llama
*publicación de assets*, y se efectúa automáticamente por el [[yii\web\AssetManager|asset manager]].
De forma predeterminada, los assets se publican en el directorio `@webrrot/assets` cuando corresponden a la URL
`@web\assets`. Se puede personalizar esta ubicación configurando las propiedades
De forma predeterminada, los assets se publican en el directorio `@webrrot/assets` cuando corresponden a la URL
`@web\assets`. Se puede personalizar esta ubicación configurando las propiedades
[[yii\web\AssetManager::basePath|basePath]] y [[yii\web\AssetManager::baseUrl|baseUrl]].
En lugar de publicar los assets copiando archivos, se puede considerar usar enlaces simbólicos, si tu
SO (sistema operativo) y servidor Web lo permite. Esta característica se puede habilitar estableciendo el valor de
En lugar de publicar los assets copiando archivos, se puede considerar usar enlaces simbólicos, si tu
SO (sistema operativo) y servidor Web lo permite. Esta característica se puede habilitar estableciendo el valor de
[[yii\web\AssetManager::linkAssets|linkAssets]] en `true`.
```php
......@@ -336,35 +336,35 @@ return [
];
```
Con la anterior configuración, el gestor de assets creará un enlace simbólico a la ruta de origen del asset bundle
Con la anterior configuración, el gestor de assets creará un enlace simbólico a la ruta de origen del asset bundle
cuando éste sea publicado. Esto es más rápido que copiar archivos y también asegura que siempre estén actualizados.
## Los Asset Bundles más Comunes <a name="common-asset-bundles"></a>
El código del núcleo de Yii tiene definidos varios asset bundles. Entre ellos, los siguientes bundles son los más
El código del núcleo de Yii tiene definidos varios asset bundles. Entre ellos, los siguientes bundles son los más
usados y pueden referenciarse en códigos de aplicaciones o extensiones.
- [[yii\web\YiiAsset]]: Principalmente incluye el archivo `yii.js` que implementa un mecanismo de organización de
código JavaScript en los módulos. También proporciona soporte especial para los atributos `data-method` y
- [[yii\web\YiiAsset]]: Principalmente incluye el archivo `yii.js` que implementa un mecanismo de organización de
código JavaScript en los módulos. También proporciona soporte especial para los atributos `data-method` y
`data-confirm` y otras característica útiles.
- [[yii\web\JqueryAsset]]: Incluye el archivo `jquery.js` desde el paquete Bower jQuery.
- [[yii\bootstrap\BootstrapAsset]]: Incluye el archivo CSS desde el framework Twitter Bootstrap.
- [[yii\bootstrap\BootstrapPluginAsset]]: Incluye el archivo JavaScript desde el framework Twitter Bootstrap para dar
- [[yii\bootstrap\BootstrapPluginAsset]]: Incluye el archivo JavaScript desde el framework Twitter Bootstrap para dar
soporte a los plugins JavaScript de Bootstrap.
- [[yii\jui\JuiAsset]]: Incluye los archivos CSS y JavaScript desde la librería jQuery UI.
Si el código depende de jQuery, jQuery UI o Bootstrap, se pueden usar estos asset bundles predefinidos en lugar de
crear versiones propias. Si la configuración predeterminada de estos bundles no satisface las necesidades, se puede
Si el código depende de jQuery, jQuery UI o Bootstrap, se pueden usar estos asset bundles predefinidos en lugar de
crear versiones propias. Si la configuración predeterminada de estos bundles no satisface las necesidades, se puede
personalizar como se describe en la subsección [Personalización de Asset Bundles](#customizing-asset-bundles).
## Conversión de Assets <a name="asset-conversion"></a>
En lugar de escribir código CSS y/o JavaScript directamente, los desarrolladores a menudo escriben código usando una
sintaxis extendida y usan herramientas especiales para convertirlos en CSS/JavaScript. Por ejemplo, para código CSS se
puede usar [LESS](http://lesscss.org) o [SCSS](http://sass-lang.com/); y para JavaScript se puede usar
En lugar de escribir código CSS y/o JavaScript directamente, los desarrolladores a menudo escriben código usando una
sintaxis extendida y usan herramientas especiales para convertirlos en CSS/JavaScript. Por ejemplo, para código CSS se
puede usar [LESS](http://lesscss.org) o [SCSS](http://sass-lang.com/); y para JavaScript se puede usar
[TypeScript](http://www.typescriptlang.org/).
Se pueden listar los archivos asset con sintaxis extendida (extended syntax) en [[yii\web\AssetBundle::css|css]] y
Se pueden listar los archivos asset con sintaxis extendida (extended syntax) en [[yii\web\AssetBundle::css|css]] y
[[yii\web\AssetBundle::js|js]] en un asset bundle. Por ejemplo:
```php
......@@ -385,12 +385,12 @@ class AppAsset extends AssetBundle
}
```
Cuando se registra uno de estos asset bundles en una vista, el [[yii\web\AssetManager|asset manager]] ejecutará
automáticamente las herramientas pre-procesadoras para convertir los assets de sintaxis extendidas reconocidas en
CSS/JavaScript. Cuando la vista renderice finalmente una página, se incluirán los archivos CSS/JavaScript
Cuando se registra uno de estos asset bundles en una vista, el [[yii\web\AssetManager|asset manager]] ejecutará
automáticamente las herramientas pre-procesadoras para convertir los assets de sintaxis extendidas reconocidas en
CSS/JavaScript. Cuando la vista renderice finalmente una página, se incluirán los archivos CSS/JavaScript
en la página, en lugar de los assets originales en sintaxis extendidas.
Yii usa las extensiones de archivo para identificar que sintaxis extendida se está usando. De forma predeterminada se
Yii usa las extensiones de archivo para identificar que sintaxis extendida se está usando. De forma predeterminada se
reconocen las siguientes sintaxis y extensiones de archivo.
- [LESS](http://lesscss.org/): `.less`
......@@ -399,10 +399,10 @@ reconocen las siguientes sintaxis y extensiones de archivo.
- [CoffeeScript](http://coffeescript.org/): `.coffee`
- [TypeScript](http://www.typescriptlang.org/): `.ts`
Yii se basa en las herramientas pre-procesadoras instalada para convertir los assets. Por ejemplo, para usar
Yii se basa en las herramientas pre-procesadoras instalada para convertir los assets. Por ejemplo, para usar
[LESS](http://lesscss.org/) se debe instalar el comando pre-procesador `lessc`.
Se pueden personalizar los comandos de los pre-procesadores y las sintaxis extendidas soportadas configurando
Se pueden personalizar los comandos de los pre-procesadores y las sintaxis extendidas soportadas configurando
[[yii\web\AssetManager::converter]] como en el siguiente ejemplo:
```php
......@@ -421,72 +421,72 @@ return [
];
```
En el anterior ejemplo se especifican las sintaxis extendidas soportadas a través de la propiedad
[[yii\web\AssetConverter::commands]]. Las claves del array son los nombres de extensión de archivo (sin el punto), y
los valores del array las extensiones de archivo resultantes y los comandos para realizar la conversión de assets.
Los tokens `{from}` y `{to}` en los comandos se reemplazarán por las rutas de origen de los archivos asset y las rutas
En el anterior ejemplo se especifican las sintaxis extendidas soportadas a través de la propiedad
[[yii\web\AssetConverter::commands]]. Las claves del array son los nombres de extensión de archivo (sin el punto), y
los valores del array las extensiones de archivo resultantes y los comandos para realizar la conversión de assets.
Los tokens `{from}` y `{to}` en los comandos se reemplazarán por las rutas de origen de los archivos asset y las rutas
de destino de los archivos asset.
> Información: Hay otras maneras de trabajar con las assets de sintaxis extendidas, además de la descrita
anteriormente. Por ejemplo, se pueden usar herramientas generadoras tales como [grunt](http://gruntjs.com/) para
monitorear y convertir automáticamente los assets de sintaxis extendidas. En este caso, se deben listar los archivos
> Información: Hay otras maneras de trabajar con las assets de sintaxis extendidas, además de la descrita
anteriormente. Por ejemplo, se pueden usar herramientas generadoras tales como [grunt](http://gruntjs.com/) para
monitorear y convertir automáticamente los assets de sintaxis extendidas. En este caso, se deben listar los archivos
CSS/JavaScript resultantes en lugar de los archivos de originales.
## Combinación y Compresión de Assets <a name="combining-compressing-assets"></a>
Una página web puede incluir muchos archivos CSS y/o JavaScript. Para reducir el numero de peticiones (requests)
HTTP y el tamaño total de descarga de estos archivos, una práctica común es combinar y comprimir uno o
Una página web puede incluir muchos archivos CSS y/o JavaScript. Para reducir el numero de peticiones (requests)
HTTP y el tamaño total de descarga de estos archivos, una práctica común es combinar y comprimir uno o
varios archivos, y después incluir los archivos comprimidos en las páginas Web.
>Información: La combinación y compresión de assets es habitualmente necesario cuando una aplicación se encuentra en
modo de producción. En modo de desarrollo, es más conveniente usar los archivos CSS/JavaScript originales por temas
>Información: La combinación y compresión de assets es habitualmente necesario cuando una aplicación se encuentra en
modo de producción. En modo de desarrollo, es más conveniente usar los archivos CSS/JavaScript originales por temas
relacionados con el debugging.
En el siguiente ejemplo, se muestra una propuesta para combinar y comprimir archivos asset sin necesidad de modificar
el código de la aplicación.
En el siguiente ejemplo, se muestra una propuesta para combinar y comprimir archivos asset sin necesidad de modificar
el código de la aplicación.
1. Buscar todos los asset bundles en la aplicación que se quieran combinar y comprimir.
2. Dividir estos bundles en uno o más grupos. Tenga en cuenta que cada bundle solo puede pertenecer a un único grupo.
3. Combina/Comprime los archivos CSS de cada grupo en un único archivo. Hace lo mismo para los archivos JavaScript.
4. Define un nuevo asset bundle para cada grupo:
* Establece las propiedades [[yii\web\AssetBundle::css|css]] y [[yii\web\AssetBundle::js|js]] para que sean los
* Establece las propiedades [[yii\web\AssetBundle::css|css]] y [[yii\web\AssetBundle::js|js]] para que sean los
archivos CSS y JavaScript combinados, respectivamente.
* Personaliza los asset bundles en cada grupo configurando sus propiedades [[yii\web\AssetBundle::css|css]] y
* Personaliza los asset bundles en cada grupo configurando sus propiedades [[yii\web\AssetBundle::css|css]] y
[[yii\web\AssetBundle::js|js]] para que sean el nuevo asset bundle creado para el grupo.
Usando este propuesta, cuando se registre un asset bundle en una vista, se genera un registro automático del nuevo
asset bundle para el grupo al que pertenece el bundle original. Y como resultado, los archivos combinados/comprimidos
Usando este propuesta, cuando se registre un asset bundle en una vista, se genera un registro automático del nuevo
asset bundle para el grupo al que pertenece el bundle original. Y como resultado, los archivos combinados/comprimidos
se incluyen en la página, en lugar de los originales.
### Un Example <a name="example"></a>
Vamos a usar un ejemplo para explicar la propuesta anterior.
Asumiendo que la aplicación tenga dos páginas X e Y. La página X utiliza el asset bundle A, B y C mientras que la
Asumiendo que la aplicación tenga dos páginas X e Y. La página X utiliza el asset bundle A, B y C mientras que la
página Y usa los asset bundles B, C y D.
Hay dos maneras de dividir estos asset bundles. Uno es usar un único grupo que incluye todos los asset bundles,
el otro es poner (A, B y C) en el Grupo X, y (B, C, D) en el grupo Y. Cuál es mejor? El primero tiene la ventaja
de que las dos páginas comparten los mismos archivos CSS y JavaScript combinados, que producen una caché HTTP más
efectiva. Por otra parte, por el hecho de que un único grupo contenga todos los bundles, los archivos JavaScript serán
más grandes y por tanto incrementan el tiempo de transmisión del archivo inicial. En este ejemplo, se usara la primera
Hay dos maneras de dividir estos asset bundles. Uno es usar un único grupo que incluye todos los asset bundles,
el otro es poner (A, B y C) en el Grupo X, y (B, C, D) en el grupo Y. Cuál es mejor? El primero tiene la ventaja
de que las dos páginas comparten los mismos archivos CSS y JavaScript combinados, que producen una caché HTTP más
efectiva. Por otra parte, por el hecho de que un único grupo contenga todos los bundles, los archivos JavaScript serán
más grandes y por tanto incrementan el tiempo de transmisión del archivo inicial. En este ejemplo, se usara la primera
opción, p.e., usar un único grupo que contenga todos los bundles.
> Información: Dividiendo los asset bundles en grupos no es una tarea trivial. Normalmente requiere un análisis de los
datos del trafico real de varios assets en diferentes páginas. Al principio, se puede empezar con un
> Información: Dividiendo los asset bundles en grupos no es una tarea trivial. Normalmente requiere un análisis de los
datos del trafico real de varios assets en diferentes páginas. Al principio, se puede empezar con un
único grupo para simplificar.
Se pueden usar herramientas existentes (ej. [Closure Compiler](https://developers.google.com/closure/compiler/),
[YUI Compressor](https://github.com/yui/yuicompressor/)) para combinar y comprimir todos los bundles. Hay que tener en
Se pueden usar herramientas existentes (ej. [Closure Compiler](https://developers.google.com/closure/compiler/),
[YUI Compressor](https://github.com/yui/yuicompressor/)) para combinar y comprimir todos los bundles. Hay que tener en
cuenta que los archivos deben ser combinados en el orden que satisfaga las dependencias entre los bundles.
Por ejemplo, si el Bundle A depende del B que depende a su vez de C y D, entonces, se deben listar los archivos asset
Por ejemplo, si el Bundle A depende del B que depende a su vez de C y D, entonces, se deben listar los archivos asset
empezando por C y D, seguidos por B y finalmente A.
Después de combinar y comprimir obtendremos un archivo CSS y un archivo JavaScript. Supongamos que se llaman
`all-xyz.css` y `all-xyz.js`, donde `xyz` representa un timestamp o un hash que se usa para generar un nombre de
Después de combinar y comprimir obtendremos un archivo CSS y un archivo JavaScript. Supongamos que se llaman
`all-xyz.css` y `all-xyz.js`, donde `xyz` representa un timestamp o un hash que se usa para generar un nombre de
archivo único para evitar problemas con la caché HTTP.
Ahora estamos en el último paso. Configurar el [[yii\web\AssetManager|asset manager]] como en el siguiente ejemplo en
Ahora estamos en el último paso. Configurar el [[yii\web\AssetManager|asset manager]] como en el siguiente ejemplo en
la configuración de la aplicación:
```php
......@@ -511,42 +511,42 @@ return [
];
```
Como se ha explicado en la subsección [Personalización de Asset Bundles](#customizing-asset-bundles), la anterior
configuración modifica el comportamiento predeterminado de cada bundle. En particular, el Bundle A, B, C y D ya no
tendrán ningún archivo asset. Ahora todos dependen del bundle `all` que contiene los archivos combinados `all-xyz.css`
y `all-xyz.js`. Por consiguiente, para la Página X, en lugar de incluir los archivos originales desde los bundles A, B
Como se ha explicado en la subsección [Personalización de Asset Bundles](#customizing-asset-bundles), la anterior
configuración modifica el comportamiento predeterminado de cada bundle. En particular, el Bundle A, B, C y D ya no
tendrán ningún archivo asset. Ahora todos dependen del bundle `all` que contiene los archivos combinados `all-xyz.css`
y `all-xyz.js`. Por consiguiente, para la Página X, en lugar de incluir los archivos originales desde los bundles A, B
y C, solo se incluirán los dos archivos combinados; pasa lo mismo con la Página Y.
Hay un último truco para hacer que el enfoque anterior se adapte mejor. En lugar de modificar directamente el archivo
de configuración de la aplicación, se puede poner el array del personalización del bundle en un archivo separado y que
Hay un último truco para hacer que el enfoque anterior se adapte mejor. En lugar de modificar directamente el archivo
de configuración de la aplicación, se puede poner el array del personalización del bundle en un archivo separado y que
se incluya condicionalmente este archivo en la configuración de la aplicación. Por ejemplo:
```php
return [
'components' => [
'assetManager' => [
'bundles' => require(__DIR__ . '/' . (YII_ENV_PROD ? 'assets-prod.php' : 'assets-dev.php')),
'bundles' => require(__DIR__ . '/' . (YII_ENV_PROD ? 'assets-prod.php' : 'assets-dev.php')),
],
],
];
```
Es decir, el array de configuración del asset bundle se guarda en `asset-prod.php` para el modo de producción, y
Es decir, el array de configuración del asset bundle se guarda en `asset-prod.php` para el modo de producción, y
`assets-del.php` para los otros modos.
### Uso del Comando `asset` <a name="using-asset-command"></a>
Yii proporciona un comando de consola llamado `asset` para automatizar el enfoque descrito.
Para usar este comando, primero se debe crear un archivo de configuración para describir que asset bundle se deben
combinar y cómo se deben agrupar. Se puede usar el sub-comando `asset/template` para generar una plantilla primero y
Para usar este comando, primero se debe crear un archivo de configuración para describir que asset bundle se deben
combinar y cómo se deben agrupar. Se puede usar el sub-comando `asset/template` para generar una plantilla primero y
después modificarla para que se adapte a nuestras necesidades.
```
yii asset/template assets.php
```
El comando genera un archivo llamado `assets.php` en el directorio actual. El contenido de este archivo es similar al
El comando genera un archivo llamado `assets.php` en el directorio actual. El contenido de este archivo es similar al
siguiente código:
```php
......@@ -582,32 +582,32 @@ return [
];
```
Se debe modificar este archivo para especificar que bundles plantea combinar en la opción `bundles`. En la opción
`targets` se debe especificar como se deben dividir entre los grupos. Se puede especificar uno o más grupos,
Se debe modificar este archivo para especificar que bundles plantea combinar en la opción `bundles`. En la opción
`targets` se debe especificar como se deben dividir entre los grupos. Se puede especificar uno o más grupos,
como se ha comentado.
> Nota: Debido a que los alias `@webroot` y `@web` no están disponibles en la aplicación de consola, se deben definir
> Nota: Debido a que los alias `@webroot` y `@web` no están disponibles en la aplicación de consola, se deben definir
explícitamente en la configuración.
Los archivos JavaScript se combinan, comprimen y guardan en `js/all-{hash}.js` donde {hash} se reemplaza con el hash
Los archivos JavaScript se combinan, comprimen y guardan en `js/all-{hash}.js` donde {hash} se reemplaza con el hash
del archivo resultante.
Las opciones `jsCompressor` y `cssCompressor` especifican los comandos de consola o llamadas PHP (PHP callbacks) para
realizar la combinación/compresión de JavaScript y CSS. De forma predeterminada Yii usa
[Closure Compiler](https://developers.google.com/closure/compiler/) para combinar los archivos JavaScript y
[YUI Compressor](https://github.com/yui/yuicompressor/) para combinar archivos CSS. Se deben instalar las herramientas
Las opciones `jsCompressor` y `cssCompressor` especifican los comandos de consola o llamadas PHP (PHP callbacks) para
realizar la combinación/compresión de JavaScript y CSS. De forma predeterminada Yii usa
[Closure Compiler](https://developers.google.com/closure/compiler/) para combinar los archivos JavaScript y
[YUI Compressor](https://github.com/yui/yuicompressor/) para combinar archivos CSS. Se deben instalar las herramientas
manualmente o ajustar sus configuraciones para usar nuestras favoritas.
Con el archivo de configuración, se puede ejecutar el comando `asset` para combinar y comprimir los archivos asset y
Con el archivo de configuración, se puede ejecutar el comando `asset` para combinar y comprimir los archivos asset y
después generar un nuevo archivo de configuración de asset bundles `asset-prod.php`:
```
yii asset assets.php config/assets-prod.php
```
El archivo de configuración generado se puede incluir en la configuración de la aplicación, como se ha descrito en la
El archivo de configuración generado se puede incluir en la configuración de la aplicación, como se ha descrito en la
anterior subsección.
> Información: Usar el comando `asset` no es la única opción de automatizar el proceso de combinación y compresión.
Se puede usar la excelente herramienta de ejecución de tareas [grunt](http://gruntjs.com/) para lograr el mismo
> Información: Usar el comando `asset` no es la única opción de automatizar el proceso de combinación y compresión.
Se puede usar la excelente herramienta de ejecución de tareas [grunt](http://gruntjs.com/) para lograr el mismo
objetivo.
\ No newline at end of file
Extensiones
===========
Las extensiones son paquetes de software redistribuibles diseñados especialmente para ser usados en aplicaciones Yii y
proporcionar características listas para ser usadas. Por ejemplo, la extensión [yiisoft/yii2-debug](tool-debugger.md)
añade una practica barra de herramientas de depuración (debug toolbar) al final de cada página de la aplicación para
ayudar a comprender más fácilmente como se han generado las páginas. Se pueden usar extensiones para acelerar el
Las extensiones son paquetes de software redistribuibles diseñados especialmente para ser usados en aplicaciones Yii y
proporcionar características listas para ser usadas. Por ejemplo, la extensión [yiisoft/yii2-debug](tool-debugger.md)
añade una practica barra de herramientas de depuración (debug toolbar) al final de cada página de la aplicación para
ayudar a comprender más fácilmente como se han generado las páginas. Se pueden usar extensiones para acelerar el
proceso de desarrollo. También se puede empaquetar código propio para compartir nuestro trabajo con otra gente.
> Información: Usamos el termino "extensión" para referirnos a los paquetes específicos de software Yii. Para
propósitos generales los paquetes de software pueden usarse sin Yii, nos referiremos a ellos usando los términos
"paquetes" (package) o "librerías" (library).
> Información: Usamos el termino "extensión" para referirnos a los paquetes específicos de software Yii. Para
propósitos generales los paquetes de software pueden usarse sin Yii, nos referiremos a ellos usando los términos
"paquetes" (package) o "librerías" (library).
## Uso de Extensiones <a name="using-extensions"></a>
Para usar una extension, primero tenemos que instalarla. La mayoría de extensiones se usan como paquetes
Para usar una extension, primero tenemos que instalarla. La mayoría de extensiones se usan como paquetes
[Composer](https://getcomposer.org/) que se pueden instalar mediante los dos simples siguientes pasos:
1. modificar el archivo `composer.json` de la aplicación y especificar que extensiones (paquetes Composer) se quieren
1. modificar el archivo `composer.json` de la aplicación y especificar que extensiones (paquetes Composer) se quieren
instalar.
2. ejecutar `composer install` para instalar las extensiones especificadas.
Hay que tener en cuenta que es necesaria la instalación de [Composer](https://getcomposer.org/) si no la tenemos
Hay que tener en cuenta que es necesaria la instalación de [Composer](https://getcomposer.org/) si no la tenemos
instalada.
De forma predeterminada, Composer instala los paquetes registrados en [Packagist](https://packagist.org/) que es el
repositorio más grande de paquetes Composer de código abierto (open source). Se pueden buscar extensiones en
Packagist. También se puede crear un [repositorio propio](https://getcomposer.org/doc/05-repositories.md#repository) y
configurar Composer para que lo use. Esto es práctico cuando se desarrollan extensiones privadas que se quieran
De forma predeterminada, Composer instala los paquetes registrados en [Packagist](https://packagist.org/) que es el
repositorio más grande de paquetes Composer de código abierto (open source). Se pueden buscar extensiones en
Packagist. También se puede crear un [repositorio propio](https://getcomposer.org/doc/05-repositories.md#repository) y
configurar Composer para que lo use. Esto es práctico cuando se desarrollan extensiones privadas que se quieran
compartir a través de otros proyectos.
Las extensiones instaladas por Composer se almacenan en el directorio `BasePath/vendor`, donde `BasePath` hace
referencia a la [ruta base (base path)](structure-applications.md#basePath) de la aplicación. Ya que Composer es un
Las extensiones instaladas por Composer se almacenan en el directorio `BasePath/vendor`, donde `BasePath` hace
referencia a la [ruta base (base path)](structure-applications.md#basePath) de la aplicación. Ya que Composer es un
gestor de dependencias, cuando se instala un paquete, también se instalarán todos los paquetes de los que dependa.
Por ejemplo, para instalar la extensión `yiisoft/yii2-imagine`, modificamos el archivo `composer.json` como se muestra
Por ejemplo, para instalar la extensión `yiisoft/yii2-imagine`, modificamos el archivo `composer.json` como se muestra
a continuación:
```json
......@@ -48,15 +48,15 @@ a continuación:
}
```
Después de la instalación, debemos encontrar el directorio `yiisoft/yii2-imagine` dentro del directorio
`BasePath/vendor`. También debemos encontrar el directorio `imagine/imagine` que contiene sus paquetes dependientes
Después de la instalación, debemos encontrar el directorio `yiisoft/yii2-imagine` dentro del directorio
`BasePath/vendor`. También debemos encontrar el directorio `imagine/imagine` que contiene sus paquetes dependientes
instalados.
> Información: La extensión `yiisoft/yii2-imagine` es una extensión del núcleo (core) desarrollada y mantenida por el
equipo de desarrollo de Yii. Todas las extensiones del núcleo se hospedan en [Packagist](https://packagist.org/) y
> Información: La extensión `yiisoft/yii2-imagine` es una extensión del núcleo (core) desarrollada y mantenida por el
equipo de desarrollo de Yii. Todas las extensiones del núcleo se hospedan en [Packagist](https://packagist.org/) y
son nombradas como `yiisoft/yii2-xyz`, donde `zyz` varia según la extensión.
Ahora ya podemos usar las extensiones instaladas como si fueran parte de nuestra aplicación. El siguiente ejemplo
Ahora ya podemos usar las extensiones instaladas como si fueran parte de nuestra aplicación. El siguiente ejemplo
muestra como se puede usar la clase `yii\imagine\Image` proporcionada por la extensión `yiisoft/yii2-imagine`:
```php
......@@ -68,7 +68,7 @@ Image::thumbnail('@webroot/img/test-image.jpg', 120, 120)
->save(Yii::getAlias('@runtime/thumb-test-image.jpg'), ['quality' => 50]);
```
> Información: Las clases de extensiones se cargan automáticamente gracias a
> Información: Las clases de extensiones se cargan automáticamente gracias a
[autocarga de clases de Yii](concept-autoloading.md).
### Instalación Manual de Extensiones <a name="installing-extensions-manually"></a>
......@@ -80,12 +80,12 @@ En algunas ocasiones excepcionales es posible que tengamos que instalar alguna o
2. instalar la clase de autocarga proporcionada por las extensiones, si existe.
3. descargar e instalar todas las extensiones dependientes como siguiendo estas mismas instrucciones.
Si una extensión no proporciona clase de autocarga pero sigue el estándar
[PSR-4](http://www.php-fig.org/psr/psr-4/), se puede usar la clase de autocarga proporcionada por Yii para cargar
automáticamente las clases de las extensiones. Todo lo que se tiene que hacer es declarar un
[alias de raíz (root)](concept-aliases.md#defining-aliases) para las extensiones del directorio raíz. Por ejemplo,
asumiendo que tenemos instalada una extensión en el directorio `vendor/mycompany/myext`, y las clases de extensión se
encuentran en el namespace `myext`, entonces podemos incluir el siguiente código en nuestra configuración de
Si una extensión no proporciona clase de autocarga pero sigue el estándar
[PSR-4](http://www.php-fig.org/psr/psr-4/), se puede usar la clase de autocarga proporcionada por Yii para cargar
automáticamente las clases de las extensiones. Todo lo que se tiene que hacer es declarar un
[alias de raíz (root)](concept-aliases.md#defining-aliases) para las extensiones del directorio raíz. Por ejemplo,
asumiendo que tenemos instalada una extensión en el directorio `vendor/mycompany/myext`, y las clases de extensión se
encuentran en el namespace `myext`, entonces podemos incluir el siguiente código en nuestra configuración de
aplicación:
```php
......@@ -98,28 +98,28 @@ aplicación:
## Creación de Extensiones <a name="creating-extensions"></a>
Podemos considerar la creación de una extensión cuando tengamos la necesidad de compartir nuestro código. Cada
extensión puede contener el código que se desee, puede ser una clase de ayuda (helper class), un widget, un módulo,
Podemos considerar la creación de una extensión cuando tengamos la necesidad de compartir nuestro código. Cada
extensión puede contener el código que se desee, puede ser una clase de ayuda (helper class), un widget, un módulo,
etc.
Se recomienda crear una extensión como [paquetes de Composer](https://getcomposer.org/) para que sea se pueda
Se recomienda crear una extensión como [paquetes de Composer](https://getcomposer.org/) para que sea se pueda
instalarse más fácilmente por los otros usuarios, como se ha descrito en la anterior subsección.
Más adelante se encuentran los pasos básicos que deben seguirse para crear una extensión como paquete Composer.
1. Crear un proyecto para la extensión y alojarlo en un repositorio con VCS (Sistema de Control de Versiones), como
puede ser [github.com](https://github.com). El trabajo de desarrollo y el mantenimiento debe efectuarse en este
1. Crear un proyecto para la extensión y alojarlo en un repositorio con VCS (Sistema de Control de Versiones), como
puede ser [github.com](https://github.com). El trabajo de desarrollo y el mantenimiento debe efectuarse en este
repositorio.
2. En el directorio raíz del repositorio debe encontrarse el archivo `composer.json` que es requerido por Composer. Se
2. En el directorio raíz del repositorio debe encontrarse el archivo `composer.json` que es requerido por Composer. Se
pueden encontrar más detalles en la siguiente subsección.
3. Registrar la extensión en un repositorio de Composer como puede ser [Packagist](https://packagist.org/), para que
3. Registrar la extensión en un repositorio de Composer como puede ser [Packagist](https://packagist.org/), para que
los otros usuarios puedan encontrarlo e instalarla mediante Composer.
### `composer.json` <a name="composer-json"></a>
Cada paquete de Composer tiene que tener un archivo `composer.json` en su directorio raíz. El archivo contiene los
metadatos relacionados con el paquete. Se pueden encontrar especificaciones completas acerca de este fichero en el
[Manual de Composer](https://getcomposer.org/doc/01-basic-usage.md#composer-json-project-setup). El siguiente ejemplo
Cada paquete de Composer tiene que tener un archivo `composer.json` en su directorio raíz. El archivo contiene los
metadatos relacionados con el paquete. Se pueden encontrar especificaciones completas acerca de este fichero en el
[Manual de Composer](https://getcomposer.org/doc/01-basic-usage.md#composer-json-project-setup). El siguiente ejemplo
muestra el archivo `composer.json` para la extensión `yiisoft/yii2-imagine`:
```json
......@@ -164,38 +164,38 @@ muestra el archivo `composer.json` para la extensión `yiisoft/yii2-imagine`:
#### Nombre del Paquete<a name="package-name"></a>
Cada paquete Composer debe tener un nombre de paquete que identifique de entre todos los otros paquetes. El formato
del nombre del paquete es `nombreProveedor/nombreProyecto`. Por ejemplo, el nombre de paquete `yiisoft/yii2-imagine`,
Cada paquete Composer debe tener un nombre de paquete que identifique de entre todos los otros paquetes. El formato
del nombre del paquete es `nombreProveedor/nombreProyecto`. Por ejemplo, el nombre de paquete `yiisoft/yii2-imagine`,
el nombre del proveedor es `yiisoft` y el nombre del proyecto es `yii2-imagine`.
NO se puede usar el nombre de proveedor `yiisoft` ya que está reservado para el usarse para el código del núcleo
NO se puede usar el nombre de proveedor `yiisoft` ya que está reservado para el usarse para el código del núcleo
(core) de Yii.
Recomendamos usar el prefijo `yii2-` al nombre del proyecto para paquetes que representen extensiones de Yii 2, por
ejemplo, `minombre/yii2-miwidget`. Esto permite ver a los usuarios más fácilmente si un paquete es una extensión de
Recomendamos usar el prefijo `yii2-` al nombre del proyecto para paquetes que representen extensiones de Yii 2, por
ejemplo, `minombre/yii2-miwidget`. Esto permite ver a los usuarios más fácilmente si un paquete es una extensión de
Yii 2.
#### Tipo de Paquete <a name="package-type"></a>
Es importante que se especifique el tipo del paquete de la extensión como `yii2-extension` para que el paquete pueda
Es importante que se especifique el tipo del paquete de la extensión como `yii2-extension` para que el paquete pueda
ser reconocido como una extensión de Yii cuando se esté instalando.
Cuando un usuario ejecuta `composer install` para instalar una extensión, el archivo `vendor/yiisoft/extensions.php`
se actualizará automáticamente para incluir la información acerca de la nueva extensión. Desde este archivo, las
aplicaciones Yii pueden saber que extensiones están instaladas. (se puede acceder a esta información mediante
Cuando un usuario ejecuta `composer install` para instalar una extensión, el archivo `vendor/yiisoft/extensions.php`
se actualizará automáticamente para incluir la información acerca de la nueva extensión. Desde este archivo, las
aplicaciones Yii pueden saber que extensiones están instaladas. (se puede acceder a esta información mediante
[[yii\base\Application::extensions]]).
#### Dependencias <a name="dependencies"></a>
La extensión depende de Yii (por supuesto). Por ello se debe añadir (`yiisoft/yii2`) a la lista en la entrada
`required` del archivo `composer.json`. Si la extensión también depende de otras extensiones o de terceras
(third-party) librerías, también se deberán listar. Debemos asegurarnos de anotar las restricciones de versión
apropiadas (p. ej. `1.*`, `@stable`) para cada paquete dependiente. Se deben usar dependencias estables en versiones
La extensión depende de Yii (por supuesto). Por ello se debe añadir (`yiisoft/yii2`) a la lista en la entrada
`required` del archivo `composer.json`. Si la extensión también depende de otras extensiones o de terceras
(third-party) librerías, también se deberán listar. Debemos asegurarnos de anotar las restricciones de versión
apropiadas (ej. `1.*`, `@stable`) para cada paquete dependiente. Se deben usar dependencias estables en versiones
estables de nuestras extensiones.
La mayoría de paquetes JavaScript/CSS se gestionan usando [Bower](http://bower.io/) y/o [NPM](https://www.npmjs.org/),
La mayoría de paquetes JavaScript/CSS se gestionan usando [Bower](http://bower.io/) y/o [NPM](https://www.npmjs.org/),
en lugar de Composer. Yii utiliza el [Composer asset plugin](https://github.com/francoispluchino/composer-asset-plugin)
para habilitar la gestión de estos tipos de paquetes a través de Composer. Si la extensión depende de un paquete
para habilitar la gestión de estos tipos de paquetes a través de Composer. Si la extensión depende de un paquete
Bower, se puede, simplemente, añadir la dependencia de el archivo `composer.json` como se muestra a continuación:
```json
......@@ -207,18 +207,18 @@ en lugar de Composer. Yii utiliza el [Composer asset plugin](https://github.com/
}
```
El código anterior declara que tela extensión depende del paquete Bower `jquery`. En general, se puede usar
`bower-asset/NombrePaquete` para referirse al paquete en `composer.json`, y usar `npm-asset/NombrePaquete` para
referirse a paquetes NPM. Cuando Composer instala un paquete Bower o NPM, de forma predeterminada los contenidos de
los paquetes se instalarán en `@vendor/bower/NombrePaquete` y `@vendor/npm/Packages` respectivamente. Podemos hacer
El código anterior declara que tela extensión depende del paquete Bower `jquery`. En general, se puede usar
`bower-asset/NombrePaquete` para referirse al paquete en `composer.json`, y usar `npm-asset/NombrePaquete` para
referirse a paquetes NPM. Cuando Composer instala un paquete Bower o NPM, de forma predeterminada los contenidos de
los paquetes se instalarán en `@vendor/bower/NombrePaquete` y `@vendor/npm/Packages` respectivamente. Podemos hacer
referencia a estos dos directorios usando los alias `@bower/NombrePaquete` and `@npm/NombrePaquete`.
Para obtener más detalles acerca de la gestión de assets, puede hacerse referencia a la sección
Para obtener más detalles acerca de la gestión de assets, puede hacerse referencia a la sección
[Assets](structure-assets.md#bower-npm-assets).
#### Autocarga de Clases <a name="class-autoloading"></a>
Para que se aplique la autocarga a clases propias mediante la autocarga de clases de Yii o la autocarga de clases de
Para que se aplique la autocarga a clases propias mediante la autocarga de clases de Yii o la autocarga de clases de
Composer, debemos especificar la entrada `autoload` en el archivo `composer.json` como se puede ver a continuación:
```json
......@@ -235,38 +235,38 @@ Composer, debemos especificar la entrada `autoload` en el archivo `composer.json
Se pueden añadir una o más namespaces raíz y sus correspondientes rutas de archivo.
Cuando se instala la extensión en una aplicación, Yii creara un [alias](concept-aliases.md#extension-aliases) para
todos los namespaces raíz, que harán referencia al directorio correspondiente del namespace. Por ejemplo, la anterior
Cuando se instala la extensión en una aplicación, Yii creara un [alias](concept-aliases.md#extension-aliases) para
todos los namespaces raíz, que harán referencia al directorio correspondiente del namespace. Por ejemplo, la anterior
declaración `autoload` corresponderá a un alias llamado `@yii/imagine`.
### Prácticas Recomendadas <a name="recommended-practices"></a>
Dado que las extensiones están destinadas a ser utilizadas por otras personas, a menudo es necesario hacer un esfuerzo
extra durante el desarrollo. A continuación presentaremos algunas practicas comunes y recomendadas para la creación de
Dado que las extensiones están destinadas a ser utilizadas por otras personas, a menudo es necesario hacer un esfuerzo
extra durante el desarrollo. A continuación presentaremos algunas practicas comunes y recomendadas para la creación de
extensiones de alta calidad.
#### Namespaces <a name="namespaces"></a>
Para evitar colisiones de nombres y permitir que las clases usen la autocarga en extensiones propias, se deben usar
namespaces y nombres de clase siguiendo el [estándar PSR-4](http://www.php-fig.org/psr/psr-4/) o el
Para evitar colisiones de nombres y permitir que las clases usen la autocarga en extensiones propias, se deben usar
namespaces y nombres de clase siguiendo el [estándar PSR-4](http://www.php-fig.org/psr/psr-4/) o el
[estándar PSR-0](http://www.php-fig.org/psr/psr-0/).
Los namespaces de clases propias deben empezar por `NombreProveedor\NombreExtension` donde `NombreExtension` es
similar al nombre del paquete pero este no debe contener el prefijo `yii2-`. Por ejemplo, para la extensión
Los namespaces de clases propias deben empezar por `NombreProveedor\NombreExtension` donde `NombreExtension` es
similar al nombre del paquete pero este no debe contener el prefijo `yii2-`. Por ejemplo, para la extensión
`yiisoft/yii2-imagine`, usamos `yii\imagine` como namespace para sus clases.
No se puede usar `yii`, `yii2` o `yiisoft` como nombre de proveedor. Estos nombres están reservados para usarse en el
No se puede usar `yii`, `yii2` o `yiisoft` como nombre de proveedor. Estos nombres están reservados para usarse en el
código del núcleo de Yii.
#### Clases de Bootstrapping <a name="bootstrapping-classes"></a>
A veces, se puede querer que nuestras extensiones ejecuten algo de código durante el
[proceso de bootstrapping](runtime-bootstrapping.md) de una aplicación. Por ejemplo, queremos que nuestra extensión
responda a un evento `beginRequest` de la aplicación para ajustar alguna configuración de entorno. Aunque podemos
indicar a los usuarios de la extensión que añadan nuestro gestor de eventos para que capture `beginRequest`, es mejor
A veces, se puede querer que nuestras extensiones ejecuten algo de código durante el
[proceso de bootstrapping](runtime-bootstrapping.md) de una aplicación. Por ejemplo, queremos que nuestra extensión
responda a un evento `beginRequest` de la aplicación para ajustar alguna configuración de entorno. Aunque podemos
indicar a los usuarios de la extensión que añadan nuestro gestor de eventos para que capture `beginRequest`, es mejor
hacerlo automáticamente.
Para llevarlo a cabo, podemos crear una *clase de bootstrpping* para implementar [[yii\base\BootstrapInterface]]. Por
Para llevarlo a cabo, podemos crear una *clase de bootstrpping* para implementar [[yii\base\BootstrapInterface]]. Por
ejemplo,
```php
......@@ -286,7 +286,7 @@ class MyBootstrapClass implements BootstrapInterface
}
```
Entonces se tiene que añadir esta clase en la lista del archivo `composer.json` de la extensión propia como se muestra
Entonces se tiene que añadir esta clase en la lista del archivo `composer.json` de la extensión propia como se muestra
a continuación,
```json
......@@ -299,142 +299,142 @@ a continuación,
}
```
Cuando se instala la extensión en la aplicación, Yii automáticamente instancia la clase de bootstrapping y llama a su
Cuando se instala la extensión en la aplicación, Yii automáticamente instancia la clase de bootstrapping y llama a su
método [[yii\base\BootstrapInterface::bootstrap()|bootstrap()]] durante el proceso de bootstrapping para cada petición.
#### Trabajar con Bases de Datos<a name="working-with-databases"></a>
Puede darse el caso en que la extensión necesite acceso a bases de datos. No se debe asumir que las aplicaciones que
usen la extensión siempre usarán `Yii::$db` como conexión de BBDD. Se debe crear una propiedad `db` para las clases
que requieran acceso a BBDD. La propiedad permitirá a los usuarios de nuestra extensión elegir que conexión quieren
que use nuestra extensión. Como ejemplo, se puede hacer referencia a la clase [[yii\caching\DbCache]] y observar como
Puede darse el caso en que la extensión necesite acceso a bases de datos. No se debe asumir que las aplicaciones que
usen la extensión siempre usarán `Yii::$db` como conexión de BBDD. Se debe crear una propiedad `db` para las clases
que requieran acceso a BBDD. La propiedad permitirá a los usuarios de nuestra extensión elegir que conexión quieren
que use nuestra extensión. Como ejemplo, se puede hacer referencia a la clase [[yii\caching\DbCache]] y observar como
declara y utiliza la propiedad `db`.
Si nuestra extensión necesita crear tablas especificas en la BBDD o hacer cambios en el esquema de la BBDD, debemos:
- proporcionar [migraciones](db-migrations.md) para manipular el esquema de la BBDD, en lugar de utilizar archivos con
- proporcionar [migraciones](db-migrations.md) para manipular el esquema de la BBDD, en lugar de utilizar archivos con
sentencias SQL;
- intentar hacer las migraciones aplicables a varios Sistemas de Gestión de BBDD;
- evitar usar [Active Record](db-active-record.md) en las migraciones.
#### Uso de Assets <a name="using-assets"></a>
Si nuestra aplicación es un widget o un módulo, hay posibilidades de que requiera [assets](structure-assets.md) para
poder funcionar. Por ejemplo, un modulo puede mostrar algunas páginas de que contengan archivos JavaScript y/o CSS.
Debido a que los archivos de las extensiones se encuentran en la misma ubicación y no son accesibles por la Web cuando
Si nuestra aplicación es un widget o un módulo, hay posibilidades de que requiera [assets](structure-assets.md) para
poder funcionar. Por ejemplo, un modulo puede mostrar algunas páginas de que contengan archivos JavaScript y/o CSS.
Debido a que los archivos de las extensiones se encuentran en la misma ubicación y no son accesibles por la Web cuando
se instalan en una aplicación, hay dos maneras de hacer los assets accesibles vía Web:
- pedir a los usuarios que copien manualmente los archivos assets en un directorio público de la Web.
- declarar un [asset bundle](structure-assets.md) dejar que el mecanismo de publicación se encargue automáticamente de
- declarar un [asset bundle](structure-assets.md) dejar que el mecanismo de publicación se encargue automáticamente de
copiar los archivos que se encuentren en el asset bundle a un directorio Web público.
Recomendamos el uso de la segunda propuesta para que la extensión sea más fácil de usar para usuarios. Se puede hacer
Recomendamos el uso de la segunda propuesta para que la extensión sea más fácil de usar para usuarios. Se puede hacer
referencia a la sección [Assets](structure-assets.md) para encontrar más detalles acerca de como trabajar con ellos.
#### Internacionalización y Localización <a name="i18n-l10n"></a>
Puede que las extensiones propias se usen en aplicaciones que den soporte a diferentes idiomas! Por ello, si nuestra
extensión muestra contenido a los usuarios finales, se debe intentar [internacionalizar y localizar](tutorial-i18n.md)
Puede que las extensiones propias se usen en aplicaciones que den soporte a diferentes idiomas! Por ello, si nuestra
extensión muestra contenido a los usuarios finales, se debe intentar [internacionalizar y localizar](tutorial-i18n.md)
la extensión. En particular,
- Si la extensión muestra mensajes destinados a usuarios finales, los mensajes deben mostrarse usando `Yii::t()` para
que puedan ser traducidos. Los mensajes dirigidos a desarrolladores (como mensajes de excepciones internas) no
- Si la extensión muestra mensajes destinados a usuarios finales, los mensajes deben mostrarse usando `Yii::t()` para
que puedan ser traducidos. Los mensajes dirigidos a desarrolladores (como mensajes de excepciones internas) no
necesitan ser traducidos.
- Si la extensión muestra números, fechas, etc., deben ser formateados usando [[yii\i18n\Formatter]] siguiendo las
- Si la extensión muestra números, fechas, etc., deben ser formateados usando [[yii\i18n\Formatter]] siguiendo las
reglas de formato adecuadas.
Se pueden encontrar más detalles en la sección [internacionalización](tutorial-i18n.md).
#### Testing <a name="testing"></a>
Para conseguir que las aplicaciones propias se ejecuten sin problemas y no causen problemas a otros usuarios, deben
Para conseguir que las aplicaciones propias se ejecuten sin problemas y no causen problemas a otros usuarios, deben
ejecutarse test a las extensiones antes de ser publicadas al público.
Se recomienda crear varios casos de prueba (test cases) para probar el código de nuestra extensión en lugar de
ejecutar pruebas manuales. Cada vez que se vaya a lanzar una nueva versión, simplemente podemos ejecutar estos casos
de prueba para asegurarnos de que todo está correcto. Yii proporciona soporte para testing que puede ayudar a escribir
pruebas unitarias (unit tests), pruebas de aceptación (acceptance tests) y pruebas de funcionalidad
Se recomienda crear varios casos de prueba (test cases) para probar el código de nuestra extensión en lugar de
ejecutar pruebas manuales. Cada vez que se vaya a lanzar una nueva versión, simplemente podemos ejecutar estos casos
de prueba para asegurarnos de que todo está correcto. Yii proporciona soporte para testing que puede ayudar a escribir
pruebas unitarias (unit tests), pruebas de aceptación (acceptance tests) y pruebas de funcionalidad
(functionality tests), más fácilmente. Se pueden encontrar más detalles en la sección [Testing](test-overview.md).
#### Versiones <a name="versioning"></a>
Se debe asignar un número de versión cada vez que se lance una nueva distribución. (p. ej. `1.0.1`). Recomendamos
Se debe asignar un número de versión cada vez que se lance una nueva distribución. (ej. `1.0.1`). Recomendamos
seguir la práctica [Versionamiento Semántico](http://semver.org/lang/es/) para determinar que números se deben usar.
#### Lanzamientos <a name="releasing"></a>
Para dar a conocer nuestra extensión a terceras personas, debemos lanzara al público.
Si es la primera vez que se realiza un lanzamiento de una extensión, debemos registrarla en un repositorio Composer
como puede ser [Packagist](https://packagist.org/). Después de estos, todo lo que tenemos que hacer es crear una
etiqueta (tag) (p. ej. `v1.0.1`) en un repositorio con VCS (Sistema de Control de Versiones) y notificarle al
repositorio Composer el nuevo lanzamiento. Entonces la gente podrá encontrar el nuevo lanzamiento y instalar o
Si es la primera vez que se realiza un lanzamiento de una extensión, debemos registrarla en un repositorio Composer
como puede ser [Packagist](https://packagist.org/). Después de estos, todo lo que tenemos que hacer es crear una
etiqueta (tag) (ej. `v1.0.1`) en un repositorio con VCS (Sistema de Control de Versiones) y notificarle al
repositorio Composer el nuevo lanzamiento. Entonces la gente podrá encontrar el nuevo lanzamiento y instalar o
actualizar la extensión a mediante el repositorio Composer.
En los lanzamientos de una extensión, además de archivos de código, también se debe considerar la inclusión los puntos
En los lanzamientos de una extensión, además de archivos de código, también se debe considerar la inclusión los puntos
mencionados a continuación para facilitar a otra gente el uso de nuestra extensión:
* Un archivo léame (readme) en el directorio raíz: describe que hace la extensión y como instalarla y utilizarla.
Recomendamos que se escriba en formato [Markdown](http://daringfireball.net/projects/markdown/) y llamarlo
* Un archivo léame (readme) en el directorio raíz: describe que hace la extensión y como instalarla y utilizarla.
Recomendamos que se escriba en formato [Markdown](http://daringfireball.net/projects/markdown/) y llamarlo
`readme.md`.
* Un archivo de registro de cambios (changelog) en el directorio raíz: enumera que cambios se realizan en cada
* Un archivo de registro de cambios (changelog) en el directorio raíz: enumera que cambios se realizan en cada
lanzamiento. El archivo puede escribirse en formato Markdown y llamarlo `changelog.md`.
* Un archivo de actualización (upgrade) en el directorio raíz: da instrucciones de como actualizar desde lanzamientos
* Un archivo de actualización (upgrade) en el directorio raíz: da instrucciones de como actualizar desde lanzamientos
antiguos de la extensión. El archivo puede escribirse en formato Markdown y llamarlo `upgrade.md`.
* Tutoriales, demostraciones, capturas de pantalla, etc: son necesarios si nuestra extensión proporciona muchas
* Tutoriales, demostraciones, capturas de pantalla, etc: son necesarios si nuestra extensión proporciona muchas
características que no pueden ser detalladas completamente en el archivo `readme`.
* Documentación de API: el código debe documentarse debidamente para que otras personas puedan leerlo y entenderlo
fácilmente. Más información acerca de documentación de código en
[archivo de Objetos de clase](https://github.com/yiisoft/yii2/blob/master/framework/base/Object.php)
* Documentación de API: el código debe documentarse debidamente para que otras personas puedan leerlo y entenderlo
fácilmente. Más información acerca de documentación de código en
[archivo de Objetos de clase](https://github.com/yiisoft/yii2/blob/master/framework/base/Object.php)
> Información: Los comentarios de código pueden ser escritos en formato Markdown. La extensión `yiisoft/yii2-apidoc`
> Información: Los comentarios de código pueden ser escritos en formato Markdown. La extensión `yiisoft/yii2-apidoc`
proporciona una herramienta para generar buena documentación de API basándose en los comentarios del código.
> Información: Aunque no es un requerimiento, se recomienda que la extensión se adhiera a ciertos estilos de
codificación. Se puede hacer referencia a
[estilo de código del núcleo del framework](https://github.com/yiisoft/yii2/wiki/Core-framework-code-style) para
> Información: Aunque no es un requerimiento, se recomienda que la extensión se adhiera a ciertos estilos de
codificación. Se puede hacer referencia a
[estilo de código del núcleo del framework](https://github.com/yiisoft/yii2/wiki/Core-framework-code-style) para
obtener más detalles.
## Extensiones del Núcleo <a name="core-extensions"></a>
Yii proporciona las siguientes extensiones del núcleo que son desarrolladas y mantenidas por el equipo de desarrollo
de Yii. Todas ellas están registradas en [Packagist](https://packagist.org/) y pueden ser instaladas fácilmente como
se describe en la subsección [Uso de Extensiones](#using-extensions)
Yii proporciona las siguientes extensiones del núcleo que son desarrolladas y mantenidas por el equipo de desarrollo
de Yii. Todas ellas están registradas en [Packagist](https://packagist.org/) y pueden ser instaladas fácilmente como
se describe en la subsección [Uso de Extensiones](#using-extensions)
- [yiisoft/yii2-apidoc](https://github.com/yiisoft/yii2-apidoc):proporciona un generador de documentación de APIs
- [yiisoft/yii2-apidoc](https://github.com/yiisoft/yii2-apidoc):proporciona un generador de documentación de APIs
extensible y de de alto rendimiento.
- [yiisoft/yii2-authclient](https://github.com/yiisoft/yii2-authclient):proporciona un conjunto de clientes de
- [yiisoft/yii2-authclient](https://github.com/yiisoft/yii2-authclient):proporciona un conjunto de clientes de
autorización tales como el cliente OAuth2 de Facebook, el cliente GitHub OAuth2.
- [yiisoft/yii2-bootstrap](https://github.com/yiisoft/yii2-bootstrap): proporciona un conjunto de widgets que
- [yiisoft/yii2-bootstrap](https://github.com/yiisoft/yii2-bootstrap): proporciona un conjunto de widgets que
encapsulan los componentes y plugins de [Bootstrap](http://getbootstrap.com/).
- [yiisoft/yii2-codeception](https://github.com/yiisoft/yii2-codeception): proporciona soporte de testing basado en
- [yiisoft/yii2-codeception](https://github.com/yiisoft/yii2-codeception): proporciona soporte de testing basado en
[Codeception](http://codeception.com/).
- [yiisoft/yii2-debug](https://github.com/yiisoft/yii2-debug): proporciona soporte de depuración para aplicaciones
Yii. Cuando se usa esta extensión, aparece una barra de herramientas de depuración en la parte inferior de cada
- [yiisoft/yii2-debug](https://github.com/yiisoft/yii2-debug): proporciona soporte de depuración para aplicaciones
Yii. Cuando se usa esta extensión, aparece una barra de herramientas de depuración en la parte inferior de cada
página. La extensión también proporciona un conjunto de páginas para mostrar información detallada de depuración.
- [yiisoft/yii2-elasticsearch](https://github.com/yiisoft/yii2-elasticsearch): proporciona soporte para usar
[Elasticsearch](http://www.elasticsearch.org/). Incluye soporte básico para realizar consultas/búsquedas y también
implementa patrones de [Active Record](db-active-record.md) que permiten y permite guardar los `active records` en
- [yiisoft/yii2-elasticsearch](https://github.com/yiisoft/yii2-elasticsearch): proporciona soporte para usar
[Elasticsearch](http://www.elasticsearch.org/). Incluye soporte básico para realizar consultas/búsquedas y también
implementa patrones de [Active Record](db-active-record.md) que permiten y permite guardar los `active records` en
Elasticsearch.
- [yiisoft/yii2-faker](https://github.com/yiisoft/yii2-faker): proporciona soporte para usar
- [yiisoft/yii2-faker](https://github.com/yiisoft/yii2-faker): proporciona soporte para usar
[Faker](https://github.com/fzaninotto/Faker) y generar datos automáticamente.
- [yiisoft/yii2-gii](https://github.com/yiisoft/yii2-gii): proporciona un generador de código basado den Web altamente
- [yiisoft/yii2-gii](https://github.com/yiisoft/yii2-gii): proporciona un generador de código basado den Web altamente
extensible y que puede usarse para generar modelos, formularios, módulos, CRUD, etc. rápidamente.
- [yiisoft/yii2-imagine](https://github.com/yiisoft/yii2-imagine): proporciona funciones comunes de manipulación de
- [yiisoft/yii2-imagine](https://github.com/yiisoft/yii2-imagine): proporciona funciones comunes de manipulación de
imágenes basadas en [Imagine](http://imagine.readthedocs.org/).
- [yiisoft/yii2-jui](https://github.com/yiisoft/yii2-jui): proporciona un conjunto de widgets que encapsulan las
- [yiisoft/yii2-jui](https://github.com/yiisoft/yii2-jui): proporciona un conjunto de widgets que encapsulan las
iteraciones y widgets de [JQuery UI](http://jqueryui.com/).
- [yiisoft/yii2-mongodb](https://github.com/yiisoft/yii2-mongodb): proporciona soporte para utilizar
[MongoDB](http://www.mongodb.org/). incluye características como consultas básicas, Active Record, migraciones,
- [yiisoft/yii2-mongodb](https://github.com/yiisoft/yii2-mongodb): proporciona soporte para utilizar
[MongoDB](http://www.mongodb.org/). incluye características como consultas básicas, Active Record, migraciones,
caching, generación de código, etc.
- [yiisoft/yii2-redis](https://github.com/yiisoft/yii2-redis): proporciona soporte para utilizar
- [yiisoft/yii2-redis](https://github.com/yiisoft/yii2-redis): proporciona soporte para utilizar
[redis](http://redis.io/). incluye características como consultas básicas, Active Record, caching, etc.
- [yiisoft/yii2-smarty](https://github.com/yiisoft/yii2-smarty): proporciona un motor de plantillas basado en
- [yiisoft/yii2-smarty](https://github.com/yiisoft/yii2-smarty): proporciona un motor de plantillas basado en
[Smarty](http://www.smarty.net/).
- [yiisoft/yii2-sphinx](https://github.com/yiisoft/yii2-sphinx): proporciona soporte para utilizar
[Sphinx](http://sphinxsearch.com). incluye características como consultas básicas, Active Record, code generation,
- [yiisoft/yii2-sphinx](https://github.com/yiisoft/yii2-sphinx): proporciona soporte para utilizar
[Sphinx](http://sphinxsearch.com). incluye características como consultas básicas, Active Record, code generation,
etc.
- [yiisoft/yii2-swiftmailer](https://github.com/yiisoft/yii2-swiftmailer): proporciona características de envío de
- [yiisoft/yii2-swiftmailer](https://github.com/yiisoft/yii2-swiftmailer): proporciona características de envío de
correos electrónicos basadas en [swiftmailer](http://swiftmailer.org/).
- [yiisoft/yii2-twig](https://github.com/yiisoft/yii2-twig): proporciona un motor de plantillas basado en
- [yiisoft/yii2-twig](https://github.com/yiisoft/yii2-twig): proporciona un motor de plantillas basado en
[Twig](http://twig.sensiolabs.org/).
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment