Ответы

Flight помогает генерировать часть заголовков ответа для вас, но большую часть управления тем, что вы отправляете пользователю, вы удерживаете. Иногда вы можете получить доступ к объекту Responseнепосредственно, но большую часть времени вы будете использовать экземпляр Flight для отправки ответа.

Отправка основного ответа

Flight использует ob_start() для буферизации вывода. Это означает, что вы можете использовать echo или print для отправки ответа пользователю, и Flight захватит его и отправит обратно пользователю с соответствующими заголовками.


// Это отправит "Привет, Мир!" в браузер пользователя
Flight::route('/', function() {
    echo "Привет, Мир!";
});

// HTTP/1.1 200 OK
// Content-Type: text/html
//
// Привет, Мир!

В качестве альтернативы вы можете вызвать метод write() для добавления к телу также.


// Это отправит "Привет, Мир!" в браузер пользователя
Flight::route('/', function() {
    // многословно, но удобно, когда вам это нужно
    Flight::response()->write("Привет, Мир!");

    // если вы хотите извлечь тело, которое вы установили на этом этапе
    // вы можете сделать это так
    $body = Flight::response()->getBody();
});

Коды статусов

Вы можете установить код статуса ответа, используя метод status:

Flight::route('/@id', function($id) {
    if($id == 123) {
        Flight::response()->status(200);
        echo "Привет, Мир!";
    } else {
        Flight::response()->status(403);
        echo "Forbidden";
    }
});

Если вы хотите получить текущий код статуса, вы можете использовать метод status без аргументов:

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

Установка тела ответа

Вы можете установить тело ответа, используя метод write, однако, если вы используете echo или print что-либо, это будет захвачено и отправлено как тело ответа через буферизацию вывода.

Flight::route('/', function() {
    Flight::response()->write("Привет, Мир!");
});

// то же самое, что и

Flight::route('/', function() {
    echo "Привет, Мир!";
});

Очистка тела ответа

Если вы хотите очистить тело ответа, вы можете использовать метод clearBody:

Flight::route('/', function() {
    if($someCondition) {
        Flight::response()->write("Привет, Мир!");
    } else {
        Flight::response()->clearBody();
    }
});

Запуск обратного вызова на теле ответа

Вы можете запустить обратный вызов на теле ответа, используя метод addResponseBodyCallback:

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

// Это сжимает все ответы для любого маршрута
Flight::response()->addResponseBodyCallback(function($body) {
    return gzencode($body, 9);
});

Вы можете добавлять несколько обратных вызовов, и они будут запускаться в том порядке, в котором они были добавлены. Поскольку это может принимать любой вызываемый объект, он может принимать массив класса [ $class, 'method' ], замыкание $strReplace = function($body) { str_replace('hi', 'there', $body); };, или имя функции 'minify', если у вас есть функция для минификации вашего html-кода, например.

Примечание: Обратные вызовы маршрута не будут работать, если вы используете параметр конфигурации flight.v2.output_buffering.

Специфический обратный вызов маршрута

Если вы хотите, чтобы это применялось только к определенному маршруту, вы можете добавить обратный вызов в сам маршрут:

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

    // Это сжимает только ответ для этого маршрута
    Flight::response()->addResponseBodyCallback(function($body) {
        return gzencode($body, 9);
    });
});

Опция Middleware

Вы также можете использовать промежуточное программное обеспечение для применения обратного вызова ко всем маршрутам через промежуточное программное обеспечение:

// MinifyMiddleware.php
class MinifyMiddleware {
    public function before() {
        // Применить обратный вызов здесь на объект response().
        Flight::response()->addResponseBodyCallback(function($body) {
            return $this->minify($body);
        });
    }

    protected function minify(string $body): string {
        // минифицировать тело как-то
        return $body;
    }
}

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

Установка заголовка ответа

Вы можете установить заголовок, такой как тип содержимого ответа, с помощью метода header:


// Это отправит "Привет, Мир!" в браузер пользователя в виде простого текста
Flight::route('/', function() {
    Flight::response()->header('Content-Type', 'text/plain');
    // или
    Flight::response()->setHeader('Content-Type', 'text/plain');
    echo "Привет, Мир!";
});

JSON

Flight предоставляет поддержку для отправки JSON и JSONP ответов. Чтобы отправить JSON-ответ, вы передаете некоторые данные для кодирования JSON:

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

JSON с кодом статуса

Вы также можете передать код статуса в качестве второго аргумента:

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

JSON с Pretty Print

Вы также можете передать аргумент в последнюю позицию для включения красивой печати:

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

Если вы изменяете передаваемые в Flight::json() параметры и хотите более простый синтаксис, вы можете просто переопределить метод JSON:

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

// И теперь его можно использовать так
Flight::json(['id' => 123], 200, JSON_PRETTY_PRINT);

JSON и остановка выполнения (v3.10.0)

Если вы хотите отправить JSON-ответ и остановить выполнение, вы можете использовать метод jsonHalt. Это полезно для случаев, когда вы проверяете, возможно, какой-то тип авторизации и если пользователь не авторизован, вы можете немедленно отправить JSON-ответ, очистить текущее тело содержимого и остановить выполнение.

Flight::route('/users', function() {
    $authorized = someAuthorizationCheck();
    // Проверьте, авторизован ли пользователь
    if($authorized === false) {
        Flight::jsonHalt(['error' => 'Unauthorized'], 401);
    }

    // Продолжайте с оставшейся частью маршрута
});

До v3.10.0 вам пришлось бы сделать что-то вроде этого:

Flight::route('/users', function() {
    $authorized = someAuthorizationCheck();
    // Проверьте, авторизован ли пользователь
    if($authorized === false) {
        Flight::halt(401, json_encode(['error' => 'Unauthorized']));
    }

    // Продолжайте с оставшейся частью маршрута
});

JSONP

Для запросов JSONP вы можете необязательно передать имя параметра запроса, которое вы используете для определения вашей функции обратного вызова:

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

Таким образом, при выполнении GET-запроса с использованием ?q=my_func, вы должны получить вывод:

my_func({"id":123});

Если вы не передадите имя параметра запроса, он по умолчанию будет jsonp.

Перенаправление на другой URL

Вы можете перенаправить текущий запрос, используя метод redirect() и передавая новый URL:

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

По умолчанию Flight отправляет код состояния HTTP 303 ("Смотри другой"). Вы можете указать пользовательский код:

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

Остановка

Вы можете остановить фреймворк в любой момент, вызвав метод halt:

Flight::halt();

Также вы можете указать необязательный HTTP код состояния и сообщение:

Flight::halt(200, 'Скоро вернусь...');

Вызов halt будет отбрасывать любое содержимое ответа до этого момента. Если вы хотите остановить фреймворк и вывести текущий ответ, используйте метод stop:

Flight::stop();

Очистка данных ответа

Вы можете очистить тело ответа и заголовки, используя метод clear(). Это очистит любые заголовки, присвоенные ответу, очистит тело ответа и установит код статуса на 200.

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

Очистка только тела ответа

Если вы хотите очистить только тело ответа, вы можете использовать метод clearBody():

// Это все еще сохранит все заголовки установленные на объекте response().
Flight::response()->clearBody();

HTTP-кэширование

Flight предоставляет встроенную поддержку кэширования на уровне HTTP. Если условие кэширования соблюдается, Flight вернет HTTP 304 Not Modified ответ. При следующем запросе клиента к тому же ресурсу, их попросят использовать локально кэшированную версию.

Кэширование на уровне маршрута

Если вы хотите кешировать весь ваш ответ, вы можете использовать метод cache() и передать время кэширования.


// Это закеширует ответ на 5 минут
Flight::route('/news', function () {
  Flight::response()->cache(time() + 300);
  echo 'Этот контент будет закеширован.';
});

// Кроме того, вы можете использовать строку, которую вы передадите
// в метод strtotime()
Flight::route('/news', function () {
  Flight::response()->cache('+5 minutes');
  echo 'Этот контент будет закеширован.';
});

Последнее изменение

Вы можете использовать метод lastModified и передать временную метку UNIX для установки даты и времени последнего изменения страницы. Клиент продолжит использовать свой кэш до тех пор, пока значение последнего изменения не изменится.

Flight::route('/news', function () {
  Flight::lastModified(1234567890);
  echo 'Этот контент будет закеширован.';
});

ETag

Кэширование ETag аналогично кэшированию Last-Modified, за исключением того, что вы можете указать любой идентификатор, который вы хотите для ресурса:

Flight::route('/news', function () {
  Flight::etag('my-unique-id');
  echo 'Этот контент будет закеширован.';
});

Имейте в виду, что вызов lastModified или etag установит и проверит значение кеша. Если значение кеша одинаково между запросами, Flight немедленно отправит ответ HTTP 304 и прекратит обработку.

Скачать файл

Есть вспомогательный метод для загрузки файла. Вы можете использовать метод download и передать путь.

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