Respostas
Visão Geral
Flight ajuda a gerar parte dos cabeçalhos de resposta para você, mas você mantém a maior parte do controle sobre o que envia de volta ao usuário. Na maioria das vezes, você acessará o objeto response() diretamente, mas Flight tem alguns métodos auxiliares para definir alguns dos cabeçalhos de resposta para você.
Entendendo
Após o usuário enviar sua request para sua aplicação, você precisa gerar uma resposta apropriada para eles. Eles enviaram informações como a linguagem que preferem, se podem lidar com certos tipos de compressão, seu agente de usuário, etc., e após processar tudo, é hora de enviar de volta uma resposta apropriada. Isso pode ser definir cabeçalhos, produzir um corpo de HTML ou JSON para eles, ou redirecioná-los para uma página.
Uso Básico
Enviando um Corpo de Resposta
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 Flight a capturará e a enviará de volta ao usuário com os cabeçalhos apropriados.
// Isso enviará "Hello, World!" para o navegador do usuário
Flight::route('/', function() {
echo "Hello, World!";
});
// HTTP/1.1 200 OK
// Content-Type: text/html
//
// Hello, World!Como alternativa, você pode chamar o método write() para adicionar ao corpo também.
// Isso enviará "Hello, World!" para o navegador do usuário
Flight::route('/', function() {
// verboso, mas faz o trabalho às vezes quando você precisa
Flight::response()->write("Hello, World!");
// se você quiser recuperar o corpo que definiu neste ponto
// você pode fazer assim
$body = Flight::response()->getBody();
});JSON
Flight fornece suporte para enviar respostas JSON e JSONP. Para enviar uma resposta JSON, você passa alguns dados para serem codificados em JSON:
Flight::route('/@companyId/users', function(int $companyId) {
// de alguma forma, extraia seus usuários de um banco de dados, por exemplo
$users = Flight::db()->fetchAll("SELECT id, first_name, last_name FROM users WHERE company_id = ?", [ $companyId ]);
Flight::json($users);
});
// [{"id":1,"first_name":"Bob","last_name":"Jones"}, /* more users */ ]Nota: Por padrão, Flight enviará um cabeçalho
Content-Type: application/jsoncom a resposta. Ele também usará as flagsJSON_THROW_ON_ERROReJSON_UNESCAPED_SLASHESao codificar o JSON.
JSON com Código de Status
Você também pode passar um código de status como o segundo argumento:
Flight::json(['id' => 123], 201);JSON com Impressão Bonita
Você também pode passar um argumento na última posição para ativar a impressão bonita:
Flight::json(['id' => 123], 200, true, 'utf-8', JSON_PRETTY_PRINT);Alterando a Ordem dos Argumentos JSON
Flight::json() é um método muito antigo, mas o objetivo do Flight é manter a compatibilidade retroativa
para projetos. Na verdade, é muito simples se você quiser refazer a ordem dos argumentos para usar uma sintaxe mais simples,
você pode apenas remapear o método JSON como qualquer outro método do Flight:
Flight::map('json', function($data, $code = 200, $options = 0) {
// agora você não precisa de `true, 'utf-8'` ao usar o método json()!
Flight::_json($data, $code, true, 'utf-8', $options);
}
// E agora pode ser usado assim
Flight::json(['id' => 123], 200, JSON_PRETTY_PRINT);JSON e Parando a Execução
v3.10.0
Se você quiser enviar uma resposta JSON e parar a execução, você 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 conteúdo do corpo existente
e parar a execução.
Flight::route('/users', function() {
$authorized = someAuthorizationCheck();
// Verifica se o usuário está autorizado
if($authorized === false) {
Flight::jsonHalt(['error' => 'Unauthorized'], 401);
// sem exit; necessário aqui.
}
// Continua com o resto da rota
});Antes da v3.10.0, você teria que fazer algo assim:
Flight::route('/users', function() {
$authorized = someAuthorizationCheck();
// Verifica se o usuário está autorizado
if($authorized === false) {
Flight::halt(401, json_encode(['error' => 'Unauthorized']));
}
// Continua com o resto da rota
});Limpando um Corpo de Resposta
Se você quiser limpar o corpo da resposta, você pode usar o método clearBody:
Flight::route('/', function() {
if($someCondition) {
Flight::response()->write("Hello, World!");
} else {
Flight::response()->clearBody();
}
});O caso de uso acima provavelmente não é comum, no entanto, poderia ser mais comum se isso fosse usado em um middleware.
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 fará gzip em 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ê tivesse 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ê quisesse que isso se aplicasse apenas a uma rota específica, poderia 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 fará gzip apenas na resposta desta 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() ]);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 "Hello, World!";
} else {
Flight::response()->status(403);
echo "Forbidden";
}
});Se você quiser obter o código de status atual, pode usar o método status sem argumentos:
Flight::response()->status(); // 200Definindo um Cabeçalho de Resposta
Você pode definir um cabeçalho, como o tipo de conteúdo da resposta, usando o método header:
// Isso enviará "Hello, World!" para o navegador do usuário em texto plano
Flight::route('/', function() {
Flight::response()->header('Content-Type', 'text/plain');
// ou
Flight::response()->setHeader('Content-Type', 'text/plain');
echo "Hello, World!";
});Redirecionamento
Você pode redirecionar a solicitação atual usando o método redirect() e passando
uma nova URL:
Flight::route('/login', function() {
$username = Flight::request()->data->username;
$password = Flight::request()->data->password;
$passwordConfirm = Flight::request()->data->password_confirm;
if($password !== $passwordConfirm) {
Flight::redirect('/new/location');
return; // isso é necessário para que a funcionalidade abaixo não execute
}
// adicione o novo usuário...
Flight::db()->runQuery("INSERT INTO users ....");
Flight::redirect('/admin/dashboard');
});Nota: Por padrão, Flight envia um código de status HTTP 303 ("See Other"). Você pode opcionalmente definir um código personalizado:
Flight::redirect('/new/location', 301); // permanenteParando a Execução da Rota
Você pode parar o framework e sair imediatamente em qualquer ponto chamando o método halt:
Flight::halt();Você também pode especificar um código de status HTTP opcional e mensagem:
Flight::halt(200, 'Be right back...');Chamar halt descartará qualquer conteúdo de resposta até aquele ponto e parará toda a execução.
Se você quiser parar o framework e produzir a resposta atual, use o método stop:
Flight::stop($httpStatusCode = null);Nota:
Flight::stop()tem algum comportamento estranho, como produzir a resposta, mas continuar executando seu script, o que pode não ser o que você deseja. Você pode usarexitoureturnapós chamarFlight::stop()para prevenir execução adicional, mas geralmente é recomendado usarFlight::halt().
Isso salvará a chave e o valor do cabeçalho no objeto de resposta. No final do ciclo de vida da solicitação, ele construirá os cabeçalhos e enviará uma resposta.
Uso Avançado
Enviando um Cabeçalho Imediatamente
Pode haver momentos em que você precisa fazer algo personalizado com o cabeçalho e precisa enviar o cabeçalho
na própria linha de código com a qual está trabalhando. Se você estiver definindo uma rota transmitida,
isso é o que você precisaria. Isso é alcançável através de response()->setRealHeader().
Flight::route('/', function() {
Flight::response()->setRealHeader('Content-Type: text/plain');
echo 'Streaming response...';
sleep(5);
echo 'Done!';
})->stream();JSONP
Para solicitações JSONP, você pode opcionalmente passar o nome do parâmetro de consulta que está usando para definir sua função de callback:
Flight::jsonp(['id' => 123], 'q');Então, ao fazer uma solicitação GET usando ?q=my_func, você deve receber a saída:
my_func({"id":123});Se você não passar um nome de parâmetro de consulta, ele usará jsonp por padrão.
Nota: Se você ainda estiver usando solicitações JSONP em 2025 e além, entre no chat e nos diga por quê! Adoramos ouvir algumas boas histórias de batalha/horror!
Limpando Dados de Resposta
Você pode limpar o corpo da resposta e 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 para 200.
Flight::response()->clear();Limpando Apenas o Corpo da Resposta
Se você quiser limpar apenas o corpo da resposta, pode usar o método clearBody():
// Isso ainda manterá quaisquer cabeçalhos definidos no objeto response().
// Isso ainda manterá quaisquer cabeçalhos definidos no objeto response().
Flight::response()->clearBody();Cache HTTP
Flight fornece suporte integrado para cache no nível HTTP. Se a condição de cache
for atendida, Flight retornará uma resposta HTTP 304 Not Modified. Na próxima vez que o
cliente solicitar o mesmo recurso, eles serão solicitados a usar sua versão em cache local.
Cache no 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 'This content will be cached.';
});
// Alternativamente, você pode usar uma string que passaria
// para o método strtotime()
Flight::route('/news', function () {
Flight::response()->cache('+5 minutes');
echo 'This content will be cached.';
});Last-Modified
Você pode usar o método lastModified e passar um timestamp UNIX para definir a data
e hora em que uma página foi modificada pela última vez. O cliente continuará usando seu cache até
que o valor da última modificação seja alterado.
Flight::route('/news', function () {
Flight::lastModified(1234567890);
echo 'This content will be cached.';
});ETag
O cache ETag é semelhante ao Last-Modified, exceto que você pode especificar qualquer ID que
desejar para o recurso:
Flight::route('/news', function () {
Flight::etag('my-unique-id');
echo 'This content will be cached.';
});Tenha em mente que chamar lastModified ou etag definirá e verificará o
valor do cache. Se o valor do cache for o mesmo entre as solicitações, Flight enviará imediatamente
uma resposta HTTP 304 e parará o processamento.
Baixar um Arquivo
v3.12.0
Há um método auxiliar para transmitir um arquivo ao usuário final. Você pode usar o método download e passar o caminho.
Flight::route('/download', function () {
Flight::download('/path/to/file.txt');
// A partir da v3.17.1, você pode especificar um nome de arquivo personalizado para o download
Flight::download('/path/to/file.txt', 'custom_name.txt');
});Veja Também
- Routing - Como mapear rotas para controladores e renderizar visualizações.
- Requests - Entendendo como lidar com solicitações de entrada.
- Middleware - Usando middleware com rotas para autenticação, logging, etc.
- Por que um Framework? - Entendendo os benefícios de usar um framework como Flight.
- Extending - Como estender Flight com sua própria funcionalidade.
Solução de Problemas
- Se você estiver tendo problemas com redirecionamentos não funcionando, certifique-se de adicionar um
return;ao método. stop()ehalt()não são a mesma coisa.halt()parará a execução imediatamente, enquantostop()permitirá que a execução continue.
Changelog
- v3.17.1 - Adicionado
$fileNameao métododownloadFile(). - v3.12.0 - Adicionado método auxiliar downloadFile.
- v3.10.0 - Adicionado
jsonHalt. - v1.0 - Lançamento inicial.