Cuando una aplicación finaliza la gestión de una petición (request), genera un objeto response y lo envía al usuario final. El objeto response contiene información tal como el código de estado (status code) HTTP, las cabeceras (headers) HTTP y el cuerpo (body). El objetivo final del desarrollo de una aplicación Web es esencialmente construir objetos response para varias peticiones.
En la mayoría de casos principalmente se debe tratar con
componentes de aplicación de tipo response
que, por defecto, son una
instancia de yii\web\Response. Sin embargo, Yii permite crear sus propios objetos response
y enviarlos al
usuario final tal y como se explica a continuación.
En esta sección, se describirá como generar y enviar respuestas a usuarios finales.
Una de las primeras cosas que debería hacerse cuando se genera una respuesta es indicar si la petición se ha gestionado correctamente. Esto se indica asignando la propiedad yii\web\Response::$statusCode a la que se le puede asignar cualquier valor válido dentro de los códigos de estado HTTP. Por ejemplo, para indicar que la petición se ha gestionado correctamente, se puede asignar el código de estado a 200, como en el siguiente ejemplo:
Yii::$app->response->statusCode = 200;
Sin embargo, en la mayoría de casos nos es necesario asignar explícitamente el código de estado. Esto se debe a que el valor por defecto de yii\web\Response::$statusCode es 200. Y si se quiere indicar que la petición ha fallado, se puede lanzar una excepción HTTP apropiada como en el siguiente ejemplo:
throw new \yii\web\NotFoundHttpException;
Cuando el error handler captura una excepción, obtendrá el código de estado de la excepción y lo asignará a la respuesta. En el caso anterior, la excepción yii\web\NotFoundHttpException está asociada al estado HTTP 404. En Yii existen las siguientes excepciones predefinidas.
Si la excepción que se quiere lanzar no se encuentra en la lista anterior, se puede crear una extendiendo yii\web\HttpException, o directamente lanzando un código de estado, por ejemplo:
throw new \yii\web\HttpException(402);
Se puede enviar cabeceras HTTP modificando el header collection en el componente
response
. Por ejemplo:
$headers = Yii::$app->response->headers;
// añade una cabecera Pragma. Las cabeceras Pragma existentes NO se sobrescribirán.
$headers->add('Pragma', 'no-cache');
// asigna una cabecera Pragma. Cualquier cabecera Pragma existente será descartada.
$headers->set('Pragma', 'no-cache');
// Elimina las cabeceras Pragma y devuelve los valores de las eliminadas en un array
$values = $headers->remove('Pragma');
Información: Los nombres de las cabeceras case insensitive, es decir, no discriminan entre mayúsculas y minúsculas. Además, las nuevas cabeceras registradas no se enviarán al usuario hasta que se llame al método yii\web\Response::send().
La mayoría de las respuestas deben tener un cuerpo que contenga el contenido que se quiere mostrar a los usuarios finales.
Si ya se tiene un texto de cuerpo con formato, se puede asignar a la propiedad yii\web\Response::$content del response. Por ejemplo:
Yii::$app->response->content = 'hello world!';
Si se tiene que dar formato a los datos antes de enviarlo al usuario final, se deben asignar las propiedades format y data. La propiedad format especifica que formato debe tener data. Por ejemplo:
$response = Yii::$app->response;
$response->format = \yii\web\Response::FORMAT_JSON;
$response->data = ['message' => 'hello world'];
Yii soporta a los siguientes formatos de forma predeterminada, cada uno de ellos implementado por una clase formatter. Se pueden personalizar los formatos o añadir nuevos sobrescribiendo la propiedad yii\web\Response::$formatters.
Mientras el cuerpo de la respuesta puede ser mostrado de forma explicita como se muestra a en el anterior ejemplo, en la mayoría de casos se puede asignar implícitamente por el valor de retorno de los métodos de acción. El siguiente, es un ejemplo de uso común:
public function actionIndex()
{
return $this->render('index');
}
La acción index
anterior, devuelve el resultado renderizado de la vista index
. El valor devuelto será recogido por
el componente response
, se le aplicará formato y se enviará al usuario final.
Por defecto, el formato de respuesta es HTML, sólo se debe devolver un string en un método de acción. Si se quiere usar un formato de respuesta diferente, se debe asignar antes de devolver los datos. Por ejemplo:
public function actionInfo()
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return [
'message' => 'hello world',
'code' => 100,
];
}
Como se ha mencionado, además de usar el componente de aplicación response
predeterminado, también se pueden crear
objetos response propios y enviarlos a los usuarios finales. Se puede hacer retornando un objeto en el método de
acción, como en el siguiente ejemplo:
public function actionInfo()
{
return \Yii::createObject([
'class' => 'yii\web\Response',
'format' => \yii\web\Response::FORMAT_JSON,
'data' => [
'message' => 'hello world',
'code' => 100,
],
]);
}
Nota: Si se crea un objeto response propio, no se podrán aprovechar las configuraciones asignadas para el componente
response
en la configuración de la aplicación. Sin embargo, se puede usar la inyección de dependencias para aplicar la configuración común al nuevo objeto response.
La redirección del navegador se basa en el envío de la cabecera HTTP Location
. Debido a que esta característica se
usa comúnmente, Yii proporciona soporte especial para ello.
Se puede redirigir el navegador a una URL llamando al método yii\web\Response::redirect(). El método asigna la
cabecera de Location
apropiada con la URL proporcionada y devuelve el objeto response él mismo. En un método de
acción, se puede acceder a él mediante el acceso directo yii\web\Controller::redirect() como en el siguiente
ejemplo:
public function actionOld()
{
return $this->redirect('https://example.com/new', 301);
}
En el ejemplo anterior, el método de acción devuelve el resultado del método redirect()
. Como se ha explicado antes,
el objeto response devuelto por el método de acción se usará como respuesta enviándola al usuario final.
En otros sitios que no sean los métodos de acción, se puede llamar a yii\web\Response::redirect() directamente seguido por una llamada al método yii\web\Response::send() para asegurar que no habrá contenido extra en la respuesta.
\Yii::$app->response->redirect('https://example.com/new', 301)->send();
Información: De forma predeterminada, el método yii\web\Response::redirect() asigna el estado de respuesta al código de estado 302 que indica al navegador que recurso solicitado está temporalmente alojado en una URI diferente. Se puede enviar un código de estado 301 para expresar que el recurso se ha movido de forma permanente.
Cuando la petición actual es de una petición AJAX, el hecho de enviar una cabecera Location
no causará una
redirección del navegador automática. Para resolver este problema, el método yii\web\Response::redirect() asigna
una cabecera X-Redirect
con el valor de la URL de redirección. En el lado del cliente se puede escribir código
JavaScript para leer la esta cabecera y redireccionar el navegador como corresponda.
Información: Yii contiene el archivo JavaScript
yii.js
que proporciona un conjunto de utilidades comunes de JavaScript, incluyendo la redirección de navegador basada en la cabeceraX-Redirect
. Por tanto, si se usa este fichero JavaScript (registrándolo asset bundle yii\web\YiiAsset), no se necesitará escribir nada más para tener soporte en redirecciones AJAX.
Igual que con la redirección, el envío de archivos es otra característica que se basa en cabeceras HTTP especificas. Yii proporciona un conjunto de métodos para dar soporte a varias necesidades del envío de ficheros. Todos ellos incorporan soporte para el rango de cabeceras HTTP.
Estos métodos tienen la misma firma de método con el objeto response como valor de retorno. Si el archivo que se envía es muy grande, se debe considerar usar yii\web\Response::sendStreamAsFile() porque es más efectivo en términos de memoria. El siguiente ejemplo muestra como enviar un archivo en una acción de controlador.
public function actionDownload()
{
return \Yii::$app->response->sendFile('ruta/del/fichero.txt');
}
Si se llama al método de envío de ficheros fuera de un método de acción, también se debe llamar al método yii\web\Response::send() después para asegurar que no se añada contenido extra a la respuesta.
\Yii::$app->response->sendFile('ruta/del/fichero.txt')->send();
Algunos servidores Web tienen un soporte especial para enviar ficheros llamado X-Sendfile. La idea es redireccionar
la petición para un fichero a un servidor Web que servirá el fichero directamente. Como resultado, la aplicación Web
puede terminar antes mientras el servidor Web envía el fichero. Para usar esta funcionalidad, se puede llamar a
yii\web\Response::xSendFile(). La siguiente lista resume como habilitar la característica X-Sendfile
para
algunos servidores Web populares.
El contenido en una respuesta no se envía al usuario hasta que se llama al método yii\web\Response::send(). De forma predeterminada, se llama a este método automáticamente al final de yii\base\Application::run(). Sin embargo, se puede llamar explícitamente a este método forzando el envío de la respuesta inmediatamente.
El método yii\web\Response::send() sigue los siguientes pasos para enviar una respuesta:
Después de llamar a yii\web\Response::send() por primera vez, cualquier llamada a este método será ignorada. Esto significa que una vez se envíe una respuesta, no se le podrá añadir más contenido.
Como se puede observar, el método yii\web\Response::send() lanza varios eventos útiles. Al responder a estos eventos, es posible ajustar o decorar la respuesta.
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.