Respuestas

Flight ayuda a generar parte de los encabezados de respuesta por ti, pero tú mantienes la mayor parte del control sobre lo que envías de vuelta al usuario. A veces puedes acceder al objeto Response directamente, pero la mayor parte del tiempo usarás la instancia de Flight para enviar una respuesta.

Enviando una Respuesta Básica

Flight utiliza ob_start() para almacenar en búfer la salida. Esto significa que puedes usar echo o print para enviar una respuesta al usuario y Flight la capturará y la enviará de vuelta al usuario con los encabezados apropiados.


// Esto enviará "¡Hola, Mundo!" al navegador del usuario
Flight::route('/', function() {
    echo "¡Hola, Mundo!";
});

// HTTP/1.1 200 OK
// Content-Type: text/html
//
// ¡Hola, Mundo!

Como alternativa, puedes llamar al método write() para agregar al cuerpo también.


// Esto enviará "¡Hola, Mundo!" al navegador del usuario
Flight::route('/', function() {
    // Verboso, pero a veces hace el trabajo cuando lo necesitas
    Flight::response()->write("¡Hola, Mundo!");

    // Si deseas recuperar el cuerpo que has establecido en este punto
    // puedes hacerlo de esta manera
    $body = Flight::response()->getBody();
});

Códigos de Estado

Puedes establecer el código de estado de la respuesta utilizando el método status:

Flight::route('/@id', function($id) {
    if($id == 123) {
        Flight::response()->status(200);
        echo "¡Hola, Mundo!";
    } else {
        Flight::response()->status(403);
        echo "Prohibido";
    }
});

Si deseas obtener el código de estado actual, puedes utilizar el método status sin ningún argumento:

Flight::response()->status(); // 200

Estableciendo un Cuerpo de Respuesta

Puedes establecer el cuerpo de la respuesta utilizando el método write, sin embargo, si haces echo o print de algo, será capturado y enviado como el cuerpo de respuesta a través del almacenamiento en búfer.

Flight::route('/', function() {
    Flight::response()->write("¡Hola, Mundo!");
});

// igual que

Flight::route('/', function() {
    echo "¡Hola, Mundo!";
});

Limpiando un Cuerpo de Respuesta

Si deseas limpiar el cuerpo de la respuesta, puedes usar el método clearBody:

Flight::route('/', function() {
    if($someCondition) {
        Flight::response()->write("¡Hola, Mundo!");
    } else {
        Flight::response()->clearBody();
    }
});

Ejecutando un Callback en el Cuerpo de Respuesta

Puedes ejecutar un callback en el cuerpo de la respuesta utilizando el método addResponseBodyCallback:

Flight::route('/users', function() {
    $db = Flight::db();
    $users = $db->fetchAll("SELECT * FROM users");
    Flight::render('users_table', ['users' => $users]);
});

// Esto comprimirá todas las respuestas para cualquier ruta
Flight::response()->addResponseBodyCallback(function($body) {
    return gzencode($body, 9);
});

Puedes agregar múltiples callbacks y se ejecutarán en el orden en que fueron agregados. Debido a que esto puede aceptar cualquier callable, puede aceptar un array de clase [ $class, 'method' ], un closure $strReplace = function($body) { str_replace('hi', 'there', $body); };, o un nombre de función 'minify' si tuvieras una función para minificar tu código html, por ejemplo.

Nota: Los callbacks de ruta no funcionarán si estás utilizando la opción de configuración flight.v2.output_buffering.

Callback de Ruta Específica

Si quieres que esto aplique solo a una ruta específica, podrías agregar el callback en la ruta misma:

Flight::route('/users', function() {
    $db = Flight::db();
    $users = $db->fetchAll("SELECT * FROM users");
    Flight::render('users_table', ['users' => $users]);

    // Esto comprimirá solo la respuesta para esta ruta
    Flight::response()->addResponseBodyCallback(function($body) {
        return gzencode($body, 9);
    });
});

Opción de Middleware

También puedes usar middleware para aplicar el callback a todas las rutas a través de middleware:

// MinifyMiddleware.php
class MinifyMiddleware {
    public function before() {
        // Aplica el callback aquí en el objeto response().
        Flight::response()->addResponseBodyCallback(function($body) {
            return $this->minify($body);
        });
    }

    protected function minify(string $body): string {
        // minificar el cuerpo de alguna manera
        return $body;
    }
}

// index.php
Flight::group('/users', function() {
    Flight::route('', function() { /* ... */ });
    Flight::route('/@id', function($id) { /* ... */ });
}, [ new MinifyMiddleware() ]);

Estableciendo un Encabezado de Respuesta

Puedes establecer un encabezado como el tipo de contenido de la respuesta utilizando el método header:


// Esto enviará "¡Hola, Mundo!" al navegador del usuario en texto plano
Flight::route('/', function() {
    Flight::response()->header('Content-Type', 'text/plain');
    // o
    Flight::response()->setHeader('Content-Type', 'text/plain');
    echo "¡Hola, Mundo!";
});

JSON

Flight proporciona soporte para enviar respuestas JSON y JSONP. Para enviar una respuesta JSON pasas algunos datos para que sean codificados en JSON:

Flight::json(['id' => 123]);

Nota: Por defecto, Flight enviará un encabezado Content-Type: application/json con la respuesta. También utilizará las constantes JSON_THROW_ON_ERROR y JSON_UNESCAPED_SLASHES al codificar el JSON.

JSON con Código de Estado

También puedes pasar un código de estado como el segundo argumento:

Flight::json(['id' => 123], 201);

JSON con Formato Bonito

También puedes pasar un argumento en la última posición para habilitar el formato bonito:

Flight::json(['id' => 123], 200, true, 'utf-8', JSON_PRETTY_PRINT);

Si estás cambiando las opciones pasadas a Flight::json() y deseas una sintaxis más simple, simplemente puedes volver a mapear el método JSON:

Flight::map('json', function($data, $code = 200, $options = 0) {
    Flight::_json($data, $code, true, 'utf-8', $options);
}

// Y ahora se puede usar así
Flight::json(['id' => 123], 200, JSON_PRETTY_PRINT);

JSON y Detener la Ejecución (v3.10.0)

Si deseas enviar una respuesta JSON y detener la ejecución, puedes usar el método jsonHalt. Esto es útil en casos donde estás verificando tal vez algún tipo de autorización y si el usuario no está autorizado, puedes enviar una respuesta JSON de inmediato, limpiar el contenido del cuerpo existente y detener la ejecución.

Flight::route('/users', function() {
    $authorized = someAuthorizationCheck();
    // Verifica si el usuario está autorizado
    if($authorized === false) {
        Flight::jsonHalt(['error' => 'No autorizado'], 401);
    }

    // Continúa con el resto de la ruta
});

Antes de v3.10.0, tendrías que hacer algo como esto:

Flight::route('/users', function() {
    $authorized = someAuthorizationCheck();
    // Verifica si el usuario está autorizado
    if($authorized === false) {
        Flight::halt(401, json_encode(['error' => 'No autorizado']));
    }

    // Continúa con el resto de la ruta
});

JSONP

Para las solicitudes JSONP, puedes opcionalmente pasar el nombre del parámetro de consulta que estás utilizando para definir tu función de callback:

Flight::jsonp(['id' => 123], 'q');

Entonces, al hacer una solicitud GET usando ?q=my_func, deberías recibir la salida:

my_func({"id":123});

Si no pasas un nombre de parámetro de consulta, predeterminará a jsonp.

Redirigir a otra URL

Puedes redirigir la solicitud actual utilizando el método redirect() y pasando una nueva URL:

Flight::redirect('/new/location');

Por defecto, Flight envía un código de estado HTTP 303 ("Ver Otro"). Puedes opcionalmente establecer un código personalizado:

Flight::redirect('/new/location', 401);

Deteniendo

Puedes detener el framework en cualquier momento llamando al método halt:

Flight::halt();

También puedes especificar un código de estado HTTP y un mensaje opcional:

Flight::halt(200, 'Regresaré pronto...');

Llamar a halt descartará cualquier contenido de respuesta hasta ese punto. Si deseas detener el framework y outputar la respuesta actual, usa el método stop:

Flight::stop();

Limpiando Datos de Respuesta

Puedes limpiar el cuerpo y los encabezados de la respuesta utilizando el método clear(). Esto limpiará cualquier encabezado asignado a la respuesta, limpiará el cuerpo de la respuesta y establecerá el código de estado en 200.

Flight::response()->clear();

Limpiando Solo el Cuerpo de Respuesta

Si solo deseas limpiar el cuerpo de la respuesta, puedes usar el método clearBody():

// Esto aún mantendrá cualquier encabezado establecido en el objeto response().
Flight::response()->clearBody();

Caché HTTP

Flight proporciona soporte integrado para caché a nivel HTTP. Si se cumple la condición de caché, Flight devolverá una respuesta HTTP 304 No Modificado. La próxima vez que el cliente solicite el mismo recurso, se le recomendará utilizar su versión en caché local.

Caché a Nivel de Ruta

Si deseas caché tu respuesta completa, puedes utilizar el método cache() y pasar el tiempo para caché.


// Esto almacenará en caché la respuesta durante 5 minutos
Flight::route('/news', function () {
  Flight::response()->cache(time() + 300);
  echo 'Este contenido será almacenado en caché.';
});

// Alternativamente, puedes utilizar una cadena que pasarías
// al método strtotime()
Flight::route('/news', function () {
  Flight::response()->cache('+5 minutes');
  echo 'Este contenido será almacenado en caché.';
});

Última Modificación

Puedes usar el método lastModified y pasar un timestamp UNIX para establecer la fecha y hora en que se modificó por última vez una página. El cliente seguirá utilizando su caché hasta que el valor de última modificación cambie.

Flight::route('/news', function () {
  Flight::lastModified(1234567890);
  echo 'Este contenido será almacenado en caché.';
});

ETag

El almacenamiento en caché de ETag es similar a Última Modificación, excepto que puedes especificar cualquier id que quieras para el recurso:

Flight::route('/news', function () {
  Flight::etag('mi-id-único');
  echo 'Este contenido será almacenado en caché.';
});

Ten en cuenta que llamar a lastModified o etag establecerá y comprobará el valor de la caché. Si el valor de la caché es el mismo entre solicitudes, Flight enviará inmediatamente una respuesta HTTP 304 y detendrá el procesamiento.

Descargar un Archivo (v3.12.0)

Hay un método auxiliar para descargar un archivo. Puedes usar el método download y pasar la ruta.

Flight::route('/download', function () {
  Flight::download('/path/to/file.txt');
});