Las acciones independientes son acciones definidas en términos de clases de acción que extienden de [[yii\base\Action]] o cualquiera de sus clases hijas.
Por ejemplo, en Yii se encuentran las clases [[yii\web\ViewAction]] y [[yii\web\ErrorAction]], de las cuales ambas son acciones independientes.
Para utilizar una acción independiente, debes declararla en el *action map* (mapeo de acciones) sobrescribiendo el método
[[yii\base\Controller::actions()]] en tu controlador de la siguiente manera:
```php
publicfunctionactions()
{
return[
// declara la acción "error" utilizando un nombre de clase
'error'=>'yii\web\ErrorAction',
// declara la acción "view" utilizando un array de configuración
'view'=>[
'class'=>'yii\web\ViewAction',
'viewPrefix'=>'',
],
];
}
```
Como puedes ver, el método `actions()` debe devolver un array cuyas claves son los IDs de acciones y sus valores los nombres
de clases de acciones o [configuraciones](concept-configurations.md). Al contrario de acciones en línea, los IDs de acciones independientes
pueden contener caracteres arbitrarios, mientras sean declarados en el método `actions()`.
Para crear una acción independiente, debes extender de [[yii\base\Action]] o una clase hija, e implementar un
método `public` llamado `run()`. El rol del método `run()` es similar al de un método de acción. Por ejemplo:
```php
<?php
namespaceapp\components;
useyii\base\Action;
classHelloWorldActionextendsAction
{
publicfunctionrun()
{
return"Hola Mundo!";
}
}
```
### Resultados de Acción <a name="action-results"></a>
El valor de retorno de una método de acción o del método `run()` de una acción independiente son significativos. Este se refiere
al resultado de la acción correspondiente.
El valor devuelto puede ser un objeto [response](runtime-responses.md) que será enviado como respuesta a
los usuarios.
* Para [[yii\web\Application|aplicaciones Web]], el valor de retorno pueden ser también datos arbitrarios que serán
asignados a [[yii\web\Response::data]] y más adelante convertidos a una cadena representando el cuerpo de la respuesta.
* Para [[yii\console\Application|aplicaciones de consola], el valor de retorno puede ser también un entero representando
el [[yii\console\Response::exitStatus|status de salida]] de la ejecución del comando.
En los ejemplos mostrados arriba, los resultados de las acciones son todas cadenas que serán tratadas como el cuerpo de la respuesta
a ser enviado a los usuarios. El siguiente ejemplo demuestra cómo una acción puede redirigir el navegador del usuario a una nueva URL
devolviendo un objeto `response` (debido a que el método [[yii\web\Controller::redirect()|redirect()]] devuelve
un objeto `response`):
```php
publicfunctionactionForward()
{
// redirige el navegador del usuario a http://example.com
return$this->redirect('http://example.com');
}
```
### Parámetros de Acción <a name="action-parameters"></a>
Los métodos de acción para acciones en línea y el método `run()` de acciones independientes pueden tomar parámetros,
llamados *parámetros de acción*. Sus valores son obtenidos del `request`. Para [[yii\web\Application|aplicaciones Web]],
el valor de cada parámetro de acción es tomado desde `$_GET` usando el nombre del parámetro como su clave;
para [[yii\console\Application|aplicaciones de consola]], estos corresponden a los argumentos de la línea de comandos.
En el siguiente ejemplo, la acción `view` (una acción en línea) declara dos parámetros: `$id` y `$version`.
```php
namespaceapp\controllers;
useyii\web\Controller;
classPostControllerextendsController
{
publicfunctionactionView($id,$version=null)
{
// ...
}
}
```
Los parámetros de acción serán poblados como se muestra a continuación para distintos `requests`:
*`http://hostname/index.php?r=post/view&id=123`: el parámetro `$id` tomará el valor
`'123'`, mientras que `$version` queda como `null` debido a que no hay un parámetro `version` en la URL.
*`http://hostname/index.php?r=post/view&id=123&version=2`: los parámetros `$id` y `$version` serán llenados con
`'123'` y `'2'`, respectivamente.
*`http://hostname/index.php?r=post/view`: se lanzará una excepción [[yii\web\BadRequestHttpException]]
dado que el parámetro `$id` es requerido pero no es provisto en el `request`.
*`http://hostname/index.php?r=post/view&id[]=123`: una excepción [[yii\web\BadRequestHttpException]] será lanzada
porque el parámetro `$id` está recibiendo un valor inesperado, el array `['123']`.
Si quieres que un parámetro de acción acepte un array como valor, deberías utilizar el `type-hinting` (especificación de tipo) `array`,
como a continuación:
```php
publicfunctionactionView(array$id,$version=null)
{
// ...
}
```
Ahora si el `request` es `http://hostname/index.php?r=post/view&id[]=123`, el parámetro `$id` tomará el valor
de `['123']`. Si el `request` es `http://hostname/index.php?r=post/view&id=123`, el parámetro `$id` recibirá aún
el mismo array como valor ya que el valor escalar `'123'` será convertido automáticamente en array.
Los ejemplos de arriba muestran principalmente como funcionan los parámetros de acción de una aplicación Web. Para aplicaciones de consola,
por favor consulta la sección [Comandos de Consola](tutorial-console.md) para más detalles.
### Acción por Defecto <a name="default-action"></a>
Cada controlador tiene una acción por defecto especificada a través de la propiedad [[yii\base\Controller::defaultAction]].
Cuando una [ruta](#ids-routes) contiene sólo el ID del controlador, implica que se está solicitando la acción por defecto
del controlador especificado.
Por defecto, la acción por defecto (valga la redundancia) definida es `index`. Si quieres cambiar dicho valor, simplemente sobrescribe
esta propiedad en la clase del controlador, como se muestra a continuación:
```php
namespaceapp\controllers;
useyii\web\Controller;
classSiteControllerextendsController
{
public$defaultAction='home';
publicfunctionactionHome()
{
return$this->render('home');
}
}
```
## Ciclo de Vida del Controlador <a name="controller-lifecycle"></a>
Cuando se procesa un `request`, la [aplicación](structure-applications.md) creará un controlador
basada en la [ruta](#routes) solicitada. El controlador entonces irá a través del siguiente ciclo de vida
para completar el `request`:
1. El método [[yii\base\Controller::init()]] es llamado después de que el controlador es creado y configurado.
2. El controlador crea un objecto `action` basado en el ID de acción solicitado:
* Si el ID de la acción no es especificado, el [[yii\base\Controller::defaultAction|ID de la acción por defecto]] será utilizado.
* Si el ID de la acción es encontrado en el [[yii\base\Controller::actions()|mapeo de acciones]], una acción independiente
será creada;
* Si el ID de la acción es coincide con un método de acción, una acción en línea será creada;
* De otra manera, se lanzará una excepción [[yii\base\InvalidRouteException]].
3. El controlador llama secuencialmente al método `beforeAction()` de la aplicación, al del módulo (si el controlador
pertenece a uno) y al del controlador.
* Si alguna de las llamadas devuelve `false`, el resto de los llamados subsiguientes a `beforeAction()` serán saltados y
la ejecución de la acción será cancelada.
* Por defecto, cada llamada al método `beforeAction()` lanzará un evento `beforeAction` al cual le puedes conectar un manejador.
4. El controlador ejecuta la acción:
* Los parámetros de la acción serán analizados y poblados con los datos del `request`;
5. El controlador llama secuencialmente al método `afterAction()` del controlador, del módulo (si el controlador
pertenece a uno) y de la aplicación.
* Por defecto, cada llamada al método `afterAction()` lanzará un evento `afterAction` al cual le puedes conectar un manejador.
6. La aplicación tomará el resultado de la acción y lo asignará al [response](runtime-responses.md).
## Buenas Prácticas <a name="best-practices"></a>
En una aplicación bien diseñada, los controladores son a menudo muy pequeños con cada acción conteniendo unas pocas líneas de código.
Si tu controlador se torna muy complejo, es usualmente un indicador de que deberías realizar una refactorización y mover algo de
código a otras clases.
En resumen, los controladores
* pueden acceder a los datos del [request](runtime-requests.md);
* puede llamar a métodos del [modelo](structure-models.md) y otros componentes con data del `request`;
* pueden utilizar [vistas](structure-views.md) para componer `responses`;
* NO debe procesar datos del `request - esto debe ser realizado en los [modelos](structure-models.md);
* deberían evitar insertar HTML o cualquier código de presentación - para esto están las [vistas](structure-views.md).