Respostas

Flight ajuda a gerar parte dos cabeçalhos de resposta para você, mas você possui a maior parte do controle sobre o que envia de volta ao usuário. Às vezes, você pode acessar o objeto Response diretamente, mas na maioria das vezes você usará a instância Flight para enviar uma resposta.

Enviando uma Resposta Básica

Flight usa ob_start() para armazenar em buffer a saída. Isso significa que você pode usar echo ou print para enviar uma resposta ao usuário e o Flight irá capturá-la e enviá-la de volta ao usuário com os cabeçalhos apropriados.


// Isso enviará "Olá, Mundo!" para o navegador do usuário
Flight::route('/', function() {
    echo "Olá, Mundo!";
});

// HTTP/1.1 200 OK
// Content-Type: text/html
//
// Olá, Mundo!

Como alternativa, você pode chamar o método write() para adicionar ao corpo também.


// Isso enviará "Olá, Mundo!" para o navegador do usuário
Flight::route('/', function() {
    // detalhado, mas muitas vezes faz o trabalho quando você precisa
    Flight::response()->write("Olá, Mundo!");

    // se você quiser recuperar o corpo que definiu até este ponto
    // você pode fazer isso assim
    $body = Flight::response()->getBody();
});

Códigos de Status

Você pode definir o código de status da resposta usando o método status:

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

Se você quiser obter o código de status atual, pode usar o método status sem argumentos:

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

Definindo um Corpo de Resposta

Você pode definir o corpo da resposta usando o método write, no entanto, se você echo ou print qualquer coisa, isso será capturado e enviado como o corpo da resposta através do buffering de saída.

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

// mesmo que

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

Limpando um Corpo de Resposta

Se você quiser limpar o corpo da resposta, pode usar o método clearBody:

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

Executando um Callback no Corpo da Resposta

Você pode executar um callback no corpo da resposta usando o método addResponseBodyCallback:

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

// Isso irá gzip todas as respostas para qualquer rota
Flight::response()->addResponseBodyCallback(function($body) {
    return gzencode($body, 9);
});

Você pode adicionar múltiplos callbacks e eles serão executados na ordem em que foram adicionados. Como isso pode aceitar qualquer callable, pode aceitar um array de classe [ $class, 'method' ], uma closure $strReplace = function($body) { str_replace('hi', 'there', $body); };, ou um nome de função 'minify' se você tiver uma função para minificar seu código html, por exemplo.

Nota: Callbacks de rota não funcionarão se você estiver usando a opção de configuração flight.v2.output_buffering.

Callback de Rota Específica

Se você quiser que isso se aplique apenas a uma rota específica, pode adicionar o callback na própria rota:

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

    // Isso irá gzip somente a resposta para esta rota
    Flight::response()->addResponseBodyCallback(function($body) {
        return gzencode($body, 9);
    });
});

Opção de Middleware

Você também pode usar middleware para aplicar o callback a todas as rotas via middleware:

// MinifyMiddleware.php
class MinifyMiddleware {
    public function before() {
        // Aplique o callback aqui no objeto response().
        Flight::response()->addResponseBodyCallback(function($body) {
            return $this->minify($body);
        });
    }

    protected function minify(string $body): string {
        // minifique o corpo de alguma forma
        return $body;
    }
}

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

Definindo um Cabeçalho de Resposta

Você pode definir um cabeçalho como tipo de conteúdo da resposta usando o método header:


// Isso enviará "Olá, Mundo!" para o navegador do usuário em texto simples
Flight::route('/', function() {
    Flight::response()->header('Content-Type', 'text/plain');
    // ou
    Flight::response()->setHeader('Content-Type', 'text/plain');
    echo "Olá, Mundo!";
});

JSON

Flight fornece suporte para o envio de respostas JSON e JSONP. Para enviar uma resposta JSON você passa alguns dados para serem codificados em JSON:

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

Nota: Por padrão, o Flight enviará um cabeçalho Content-Type: application/json com a resposta. Ele também usará as constantes JSON_THROW_ON_ERROR e JSON_UNESCAPED_SLASHES ao codificar o JSON.

JSON com Código de Status

Você também pode passar um código de status como segundo argumento:

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

JSON com Impressão Bonita

Você também pode passar um argumento para a última posição para habilitar a impressão bonita:

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

Se você estiver mudando as opções passadas para Flight::json() e quiser uma sintaxe mais simples, você pode apenas reconfigurar o método JSON:

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

// E agora pode ser usado assim
Flight::json(['id' => 123], 200, JSON_PRETTY_PRINT);

JSON e Parar Execução (v3.10.0)

Se você quiser enviar uma resposta JSON e parar a execução, pode usar o método jsonHalt. Isso é útil para casos em que você está verificando talvez algum tipo de autorização e se o usuário não estiver autorizado, você pode enviar uma resposta JSON imediatamente, limpar o corpo existente e parar a execução.

Flight::route('/users', function() {
    $authorized = someAuthorizationCheck();
    // Verifique se o usuário está autorizado
    if($authorized === false) {
        Flight::jsonHalt(['error' => 'Não Autorizado'], 401);
    }

    // Continue com o restante da rota
});

Antes da v3.10.0, você teria que fazer algo assim:

Flight::route('/users', function() {
    $authorized = someAuthorizationCheck();
    // Verifique se o usuário está autorizado
    if($authorized === false) {
        Flight::halt(401, json_encode(['error' => 'Não Autorizado']));
    }

    // Continue com o restante da rota
});

JSONP

Para solicitações JSONP você pode, opcionalmente, passar o nome do parâmetro de consulta que você está usando para definir sua função de callback:

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

Assim, ao fazer uma solicitação GET usando ?q=my_func, você deverá receber a saída:

my_func({"id":123});

Se você não passar um nome de parâmetro de consulta, ele será definido como jsonp.

Redirecionar para outra URL

Você pode redirecionar a solicitação atual usando o método redirect() e passar uma nova URL:

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

Por padrão, o Flight envia um código de status HTTP 303 ("Veja Outro"). Você pode opcionalmente definir um código personalizado:

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

Parando

Você pode parar o framework a qualquer momento chamando o método halt:

Flight::halt();

Você também pode especificar um código e mensagem de status HTTP opcionais:

Flight::halt(200, 'Be right back...');

Chamar halt descartará qualquer conteúdo de resposta até aquele ponto. Se você quiser parar o framework e exibir a resposta atual, use o método stop:

Flight::stop();

Limpando Dados da Resposta

Você pode limpar o corpo da resposta e os cabeçalhos usando o método clear(). Isso limpará quaisquer cabeçalhos atribuídos à resposta, limpará o corpo da resposta e definirá o código de status como 200.

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

Limpando Apenas o Corpo da Resposta

Se você apenas deseja limpar o corpo da resposta, pode usar o método clearBody():

// Isso ainda manterá quaisquer cabeçalhos definidos no objeto response().
Flight::response()->clearBody();

Cache HTTP

Flight fornece suporte embutido para caching a nível HTTP. Se a condição de cache for atendida, o Flight retornará uma resposta HTTP 304 Not Modified. Na próxima vez que o cliente solicitar o mesmo recurso, ele será solicitado a usar sua versão armazenada em cache localmente.

Cache a Nível de Rota

Se você quiser armazenar em cache toda a sua resposta, pode usar o método cache() e passar o tempo para cache.


// Isso armazenará em cache a resposta por 5 minutos
Flight::route('/news', function () {
  Flight::response()->cache(time() + 300);
  echo 'Este conteúdo será armazenado em cache.';
});

// Alternativamente, você pode usar uma string que você passaria
// para o método strtotime()
Flight::route('/news', function () {
  Flight::response()->cache('+5 minutes');
  echo 'Este conteúdo será armazenado em cache.';
});

Last-Modified

Você pode usar o método lastModified e passar um timestamp UNIX para definir a data e a hora em que uma página foi modificada pela última vez. O cliente continuará a usar seu cache até que o valor da última modificação seja alterado.

Flight::route('/news', function () {
  Flight::lastModified(1234567890);
  echo 'Este conteúdo será armazenado em cache.';
});

ETag

O cache ETag é semelhante ao Last-Modified, exceto que você pode especificar qualquer id que quiser para o recurso:

Flight::route('/news', function () {
  Flight::etag('my-unique-id');
  echo 'Este conteúdo será armazenado em cache.';
});

Lembre-se de que chamar lastModified ou etag definirá e verificará ambos os valores de cache. Se o valor de cache for o mesmo entre as solicitações, o Flight enviará imediatamente uma resposta HTTP 304 e parará o processamento.

Fazer o Download de um Arquivo (v3.12.0)

Há um método auxiliar para fazer o download de um arquivo. Você pode usar o método download e passar o caminho.

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