Los controladores son parte del patrón o arquitectura MVC.
Son objetos que extienden de yii\base\Controller y se encargan de procesar los requests
(consultas)
generando responses
(respuestas). Particularmente, después de tomar el control desde las aplicaciones,
los controladores analizarán los datos que entran en el request
, los pasan a los modelos, inyectan los
modelos resultantes a las vistas, y finalmente generan los responses
(respuestas) de salida.
Los Controladores están compuestos por acciones que son las unidades más básicas a las que los usuarios pueden dirigirse y solicitar ejecución. Un controlador puede tener una o múltiples acciones.
El siguiente ejemplo muestra un controlador post
con dos acciones: view
y create
:
namespace app\controllers;
use Yii;
use app\models\Post;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
class PostController extends Controller
{
public function actionView($id)
{
$model = Post::findOne($id);
if ($model === null) {
throw new NotFoundHttpException;
}
return $this->render('view', [
'model' => $model,
]);
}
public function actionCreate()
{
$model = new Post;
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
}
En la acción view
(definida en el método actionView()
), el código primero carga el modelo
de acuerdo el ID del modelo solicitado; Si el modelo es cargado satisfactoriamente, lo mostrará usando una vista
llamada view
. Si no, arrojará una excepción.
En la acción create
(definida por el método actionCreate()
), el código es similar. Primero intenta poblar
el modelo usando datos del request
y guardarlo. Si ambas cosas suceden correctamente, se redireccionará
el navegador a la acción view
con el ID del modelo recientemente creado. De otro modo mostrará
la vista create
a través de la cual el usuario puede completar los campos necesarios.
Los usuarios ejecutan las acciones a través de las llamadas routes (rutas). una ruta es una cadena que consiste en las siguientes partes:
Las rutas pueden usar el siguiente formato:
ControllerID/ActionID
o el siguiente formato si el controlador pertenece a un módulo:
ModuleID/ControllerID/ActionID
Entonces si un usuario solicita la URL https://hostname/index.php?r=site/index
, la acción index
del controlador site
será ejecutado. Para más detalles acerca de cómo las son resueltas en acciones, por favor consulta
la sección Routing.
En aplicaciones Web, los controladores deben extender de yii\web\Controller o cualquier
clase hija. De forma similar los controladores de aplicaciones de consola, deben extender
de yii\console\Controller o cualquier clase hija de esta. El siguiente código define un controlador site
:
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
}
Normalmente, un controlador está diseñado para manejar los requests
de acuerdo a un tipo de recurso.
Por esta razón, los IDs de controladores son a menudo sustantivos de los tipos de recurso que están manejando.
Por ejemplo, podrías utilizar article
como el ID de un controlador que maneja datos de artículos.
Por defecto, los IDs de controladores deberían contener sólo estos caracteres: letras del Inglés en minúscula, dígitos,
guiones bajos y medios, y barras. Por ejemplo, article
, post-comment
, admin/post-comment
son todos
IDs de controladores válidos, mientras que article?
, PostComment
, admin\post
no lo son.
Los guiones en un ID de controlador son utilizados para separar palabras, mientras que las barras diagonales lo son para organizar los controladores en sub-directorios.
Los nombres de clases de controladores pueden ser derivados de los IDs de acuerdo a las siguientes reglas:
Controller
.A continuación mostramos algunos ejemplos, asumiendo que el controller namespace
toma el valor por defecto: app\controllers
:
article
deriva en app\controllers\ArticleController
;post-comment
deriva en app\controllers\PostCommentController
;admin/post-comment
deriva en app\controllers\admin\PostCommentController
.Las clases de controladores deben ser autocargables. Por esta razón, en los ejemplos anteriores,
la clase del controlador article
debe ser guardada en un archivo cuyo alias alias
es @app/controllers/ArticleController.php
; mientras que el controlador admin/post-comment
debería estar
en @app/controllers/admin/PostCommentController.php
.
Información: En el último ejemplo,
admin/post-comment
, demuestra cómo puedes poner un controlador bajo un sub-directorio del controller namespace. Esto es útil cuando quieres organizar tus controladores en varias categorías pero sin utilizar módulos.
Puedes configurar controller map (mapeo de controladores) para superar las restricciones de los IDs de controladores y sus nombres de clase descritos arriba. Esto es principalmente útil cuando estás utilizando un controlador de terceros del cual no tienes control alguno sobre sus nombres de clase.
Puedes configurar controller map en la configuración de la aplicación de la siguiente manera:
[
'controllerMap' => [
[
// declara el controlador "account" usando un nombre de clase
'account' => 'app\controllers\UserController',
// declara el controlador "article" utilizando un array de configuración
'article' => [
'class' => 'app\controllers\PostController',
'enableCsrfValidation' => false,
],
],
],
]
Cada aplicación tiene un controlador por defecto especificado a través de la propiedad yii\base\Application::$defaultRoute.
Cuando un request
no especifica una ruta, se utilizará la ruta especificada en esta propiedad.
Para aplicaciones Web, el valor es 'site'
, mientras que para aplicaciones de consola
es help
. Por lo tanto, si la URL es https://hostname/index.php
, significa que el request
será manejado por el controlador site
.
Puedes cambiar el controlador por defecto con la siguiente configuración de la aplicación:
[
'defaultRoute' => 'main',
]
Crear acciones puede ser tan simple como definir un llamado método de acción en una clase controlador. Un método de acción es
un método public cuyo nombre comienza con la palabra action
. El valor de retorno de uno de estos métodos representa
los datos de respuesta (response) a ser enviado a los usuarios. El siguiente código define dos acciones: index
y hello-world
:
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
public function actionIndex()
{
return $this->render('index');
}
public function actionHelloWorld()
{
return 'Hola Mundo!';
}
}
Una acción está a menudo diseñada para realizar una manipulación particular de un recurso. Por esta razón,
los IDs de acciones son usualmente verbos, como view
(ver), update
(actualizar), etc.
Por defecto, los IDs de acciones deberían contener estos caracteres solamente: letras en Inglés en minúsculas, dígitos,
guiones bajos y barras. Los guiones en un ID de acción son utilizados para separar palabras. Por ejemplo,
view
, update2
, comment-post
son todos IDs válidos, mientras que view?
y Update
no lo son.
Puedes crear acciones de dos maneras: acciones en línea (inline) o acciones independientes (standalone). Una acción en línea es definida como un método en la clase del controlador, mientras que una acción independiente es una clase que extiende yii\base\Action o sus clases hijas. Las acciones en línea son más fáciles de crear y por lo tanto preferidas si no tienes intenciones de volver a utilizarlas. Las acciones independientes, por otro lado, son principalmente creadas para ser reutilizadas en otros controladores o para ser redistribuidas como extensiones.
Como acciones en línea nos referimos a acciones que son definidas en términos de métodos como acabamos de describir.
Los nombre de métodos de acciones derivan de los IDs de acuerdo al siguiente criterio:
action
.Por ejemplo, index
se vuelve actionIndex
, y hello-world
se vuelve actionHelloWorld
.
Nota: Los nombres de los métodos de acción son case-sensitive (distinguen entre minúsculas y mayúsculas). Si tienes un método llamado
ActionIndex
, no será considerado como un método de acción, y como resultado, solicitar la acciónindex
resultará en una excepción. También ten en cuenta que los métodos de acción deben serpublic
. Un métodoprivate
oprotected
NO define un método de acción.
Las acciones en línea son las más comúnmente definidas ya que requieren muy poco esfuerzo de creación. De todos modos, si planeas reutilizar la misma acción en diferentes lugares, o quieres redistribuir una acción, deberías considerar definirla como un acción independiente.
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:
public function actions()
{
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. 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
namespace app\components;
use yii\base\Action;
class HelloWorldAction extends Action
{
public function run()
{
return "Hola Mundo!";
}
}
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 que será enviado como respuesta a los usuarios.
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 redirect() devuelve
un objeto response
):
public function actionForward()
{
// redirige el navegador del usuario a https://example.com
return $this->redirect('https://example.com');
}
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 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 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
.
namespace app\controllers;
use yii\web\Controller;
class PostController extends Controller
{
public function actionView($id, $version = null)
{
// ...
}
}
Los parámetros de acción serán poblados como se muestra a continuación para distintos requests
:
https://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.https://hostname/index.php?r=post/view&id=123&version=2
: los parámetros $id
y $version
serán llenados con
'123'
y '2'
, respectivamente.https://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
.https://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:
public function actionView(array $id, $version = null)
{
// ...
}
Ahora si el request
es https://hostname/index.php?r=post/view&id[]=123
, el parámetro $id
tomará el valor
de ['123']
. Si el request
es https://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 para más detalles.
Cada controlador tiene una acción por defecto especificada a través de la propiedad yii\base\Controller::$defaultAction. Cuando una ruta 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:
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
public $defaultAction = 'home';
public function actionHome()
{
return $this->render('home');
}
}
Cuando se procesa un request
, la aplicación creará un controlador
basado en la ruta solicitada. El controlador entonces irá a través del siguiente ciclo de vida
para completar el request
:
action
basado en el ID de acción solicitado:beforeAction()
de la aplicación, al del módulo (si el controlador
pertenece a uno) y al del controlador.false
, el resto de los llamados subsiguientes a beforeAction()
serán saltados y
la ejecución de la acción será cancelada.beforeAction()
lanzará un evento beforeAction
al cual le puedes conectar un manejador.request
;afterAction()
del controlador, del módulo (si el controlador
pertenece a uno) y de la aplicación.afterAction()
lanzará un evento afterAction
al cual le puedes conectar un manejador.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
request
;responses
;
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.