HTTP-ответы
- Создание ответов
- Добавление заголовков к ответам
- Добавление файлов Cookies к ответам
- Файлы Cookies и шифрование
- Перенаправления
- Перенаправление на именованные маршруты
- Перенаправление к действиям контроллера
- Перенаправление на внешние домены
- Перенаправление с кратковременным сохранением данных в сессии
- Другие типы ответов
- Ответы с HTML-шаблонами
- Ответы JSON
- Ответы для загрузки файлов
- Ответы на файлы
- Потоковые ответы
- Макрокоманды ответа
Создание ответов
Строки и массивы
Все маршруты и контроллеры должны возвращать ответ, который будет отправлен обратно в браузер пользователя. Laravel предлагает несколько разных способов вернуть ответы. Самый простой ответ – это возврат строки из маршрута или контроллера. Фреймворк автоматически преобразует строку в полный HTTP-ответ:
Route::get('/', function () {
return 'Hello World';
});
Помимо возврата строк из ваших маршрутов и контроллеров, вы также можете возвращать массивы. Фреймворк автоматически преобразует массив в ответ JSON:
Route::get('/', function () {
return [1, 2, 3];
});
Знаете ли вы, что можете возвращать коллекции Eloquent из ваших маршрутов или контроллеров? Они будут автоматически преобразованы в JSON.
Объекты ответа
Как правило, вы не просто будете возвращать строки или массивы из действий маршрута. Вместо этого вы вернете полные экземпляры Illuminate\Http\Response
или шаблоны.
Возврат полного экземпляра Response
позволяет вам настроить код состояния и заголовки HTTP ответа. Экземпляр Response
наследуется от класса Symfony\Component\HttpFoundation\Response
, который содержит множество методов для построения ответов HTTP:
Route::get('/home', function () {
return response('Hello World', 200)
->header('Content-Type', 'text/plain');
});
Модели и коллекции Eloquent
По желанию можно вернуть модели и коллекции Eloquent ORM прямо из ваших маршрутов и контроллеров. Когда вы это сделаете, Laravel автоматически преобразует модели и коллекции в ответы JSON, учитывая скрытие атрибутов модели:
use App\Models\User;
Route::get('/user/{user}', function (User $user) {
return $user;
});
Добавление заголовков к ответам
Имейте в виду, что большинство методов ответа можно объединять в цепочку вызовов для гибкого создания экземпляров ответа. Например, вы можете использовать метод header
для добавления серии заголовков к ответу перед его отправкой обратно пользователю:
return response($content)
->header('Content-Type', $type)
->header('X-Header-One', 'Header Value')
->header('X-Header-Two', 'Header Value');
Или вы можете использовать метод withHeaders
, чтобы указать массив заголовков, которые будут добавлены к ответу:
return response($content)
->withHeaders([
'Content-Type' => $type,
'X-Header-One' => 'Header Value',
'X-Header-Two' => 'Header Value',
]);
Посредник управления кешем
Laravel содержит посредник cache.headers
, используемый для быстрой установки заголовка Cache-Control
для группы маршрутов. Директивы должны быть предоставлены с использованием эквивалента “snake case” соответствующей директивы управления кешем и должны быть разделены точкой с запятой. Если в списке директив указан etag
, то MD5-хеш содержимого ответа будет автоматически установлен как идентификатор ETag:
Route::middleware('cache.headers:public;max_age=2628000;etag')->group(function () {
Route::get('/privacy', function () {
// ...
});
Route::get('/terms', function () {
// ...
});
});
Добавление файлов Cookies к ответам
Вы можете добавить Cookies к исходящему экземпляру Illuminate\Http\Response
, используя метод cookie
. Вы должны передать этому методу имя, значение и количество минут, в течение которых куки должен считаться действительным:
return response('Hello World')->cookie(
'name', 'value', $minutes
);
Метод cookie
также принимает еще несколько аргументов, которые используются реже. Как правило, эти аргументы имеют то же назначение и значение, что и аргументы, передаваемые встроенному в PHP методу setcookie
method:
return response('Hello World')->cookie(
'name', 'value', $minutes, $path, $domain, $secure, $httpOnly
);
Если вы хотите, чтобы куки отправлялся вместе с исходящим ответом, но у вас еще нет экземпляра этого ответа, вы можете использовать фасад Cookie
, чтобы «поставить в очередь» файлы Cookies для добавления их к ответу при его отправке. Метод queue
принимает аргументы, необходимые для создания экземпляра Cookie
. Эти файлы Cookies будут добавлены к исходящему ответу перед его отправкой в браузер:
use Illuminate\Support\Facades\Cookie;
Cookie::queue('name', 'value', $minutes);
Создание экземпляров Cookie
Если вы хотите сгенерировать экземпляр Symfony\Component\HttpFoundation\Cookie
, который может быть добавлен к экземпляру ответа позже, вы можете использовать глобальный помощник cookie
. Этот файл Cookies не будет отправлен обратно клиенту, если он не прикреплен к экземпляру ответа:
$cookie = cookie('name', 'value', $minutes);
return response('Hello World')->cookie($cookie);
Досрочное окончание срока действия файлов Cookies
Вы можете удалить куки, обнулив срок его действия с помощью метода withoutCookie
исходящего ответа:
return response('Hello World')->withoutCookie('name');
Если у вас еще нет экземпляра исходящего ответа, вы можете использовать метод expire
фасада Cookie
для обнуления срока действия кук:
Cookie::expire('name');
Файлы Cookies и шифрование
По умолчанию, благодаря middleware Illuminate\Cookie\Middleware\EncryptCookies
все файлы Cookies, генерируемые Laravel, зашифрованы и подписаны, поэтому клиент не может их изменить или прочитать. Если вы хотите отключить шифрование для подмножества куки, созданных вашим приложением, вы можете использовать метод encryptCookies
в файле bootstrap/app.php
вашего приложения:
->withMiddleware(function (Middleware $middleware) {
$middleware->encryptCookies(except: [
'cookie_name',
]);
})
Перенаправления
Ответы с перенаправлением являются экземплярами класса Illuminate\Http\RedirectResponse
и содержат корректные заголовки, необходимые для перенаправления пользователя на другой URL. Есть несколько способов сгенерировать экземпляр RedirectResponse
. Самый простой способ – использовать глобальный помощник redirect
:
Route::get('/dashboard', function () {
return redirect('/home/dashboard');
});
По желанию можно перенаправить пользователя в его предыдущее местоположение, например, когда отправленная форма является недействительной. Вы можете сделать это с помощью глобального помощника back
. Поскольку эта функция использует сессии, убедитесь, что маршрут, вызывающий функцию back
, использует группу посредников web
:
Route::post('/user/profile', function () {
// Валидация запроса ...
return back()->withInput();
});
Перенаправление на именованные маршруты
Когда вы вызываете помощник redirect
без параметров, возвращается экземпляр Illuminate\Routing\Redirector
, что позволяет вам вызывать любой метод экземпляра Redirector
. Например, чтобы сгенерировать RedirectResponse
на именованный маршрут, вы можете использовать метод route
:
return redirect()->route('login');
Если ваш маршрут имеет параметры, вы можете передать их в качестве второго аргумента методу route
:
// Для маршрута со следующим URI: /profile/{id}
return redirect()->route('profile', ['id' => 1]);
Заполнение параметров с моделей Eloquent
Если вы перенаправляете на маршрут с параметром ID
, который извлекается из модели Eloquent, то вы можете просто передать саму модель. ID будет извлечен автоматически:
// Для маршрута со следующим URI: /profile/{id}
return redirect()->route('profile', [$user]);
Если вы хотите настроить значение, которое соответствует параметру маршрута, то вы можете указать столбец при определении параметра маршрута (/profile/{id:slug}
) или переопределить метод getRouteKey
в вашей модели Eloquent:
/**
* Получить значение ключа маршрута модели.
*/
public function getRouteKey(): mixed
{
return $this->slug;
}
Перенаправление к действиям контроллера
Вы также можете генерировать перенаправления на действия контроллера. Для этого передайте имя контроллера и действия методу action
:
use App\Http\Controllers\UserController;
return redirect()->action([UserController::class, 'index']);
Если ваш маршрут контроллера требует параметров, вы можете передать их в качестве второго аргумента методу action
:
return redirect()->action(
[UserController::class, 'profile'], ['id' => 1]
);
Перенаправление на внешние домены
Иногда может потребоваться перенаправление на домен за пределами вашего приложения. Вы можете сделать это, вызвав метод away
, который создает RedirectResponse
без какой-либо дополнительной кодировки URL, валидации или проверки:
return redirect()->away('https://www.google.com');
Перенаправление с кратковременным сохранением данных в сессии
Перенаправление на новый URL-адрес и краткосрочная запись данных в сессию обычно выполняются одновременно. Обычно это делается после успешного выполнения действия, когда вы отправляете сообщение об успешном завершении в сессию. Для удобства вы можете создать экземпляр RedirectResponse
и передать данные в сессию в единой текучей цепочке методов:
Route::post('/user/profile', function () {
// ...
return redirect('/dashboard')->with('status', 'Profile updated!');
});
После перенаправления пользователя, вы можете отобразить сохраненное из сессии сообщение. Например, используя синтаксис Blade:
@if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
@endif
Перенаправление с кратковременным сохранением входных данных
Вы можете использовать метод withInput
экземпляра RedirectResponse
, для передачи входных данных текущего запроса в сессию перед перенаправлением пользователя в новое место. Обычно это делается, если пользователь спровоцировал ошибку валидации. После того как входные данные были переданы в сессию, вы можете легко получить их во время следующего запроса для повторного автозаполнения формы:
return back()->withInput();
Другие типы ответов
Помощник response
используется для генерации других типов экземпляров ответа. Когда помощник response
вызывается без аргументов, возвращается реализация контракта Illuminate\Contracts\Routing\ResponseFactory
. Этот контракт содержит несколько полезных методов для генерации ответов.
Ответы с HTML-шаблонами
Если вам нужен контроль над статусом и заголовками ответа, но также необходимо вернуть HTML-шаблон в качестве содержимого ответа, то вы должны использовать метод view
:
return response()
->view('hello', $data, 200)
->header('Content-Type', $type);
Конечно, вы можете использовать глобальный помощник view
, даже если вам не нужно передавать собственные код состояния или заголовки HTTP.
Ответы JSON
Метод json
автоматически установит заголовок Content-Type
в application/json
, а также преобразует переданный массив в JSON с помощью функции json_encode
PHP:
return response()->json([
'name' => 'Abigail',
'state' => 'CA',
]);
Если вы хотите создать ответ JSONP, вы можете использовать метод json
в сочетании с методом withCallback
:
return response()
->json(['name' => 'Abigail', 'state' => 'CA'])
->withCallback($request->input('callback'));
Ответы для загрузки файлов
Метод download
используется для генерации ответа, который заставляет браузер пользователя загружать файл по указанному пути. Метод download
принимает имя файла в качестве второго аргумента метода, определяющий имя файла, которое видит пользователь, загружающий файл. Наконец, вы можете передать массив заголовков HTTP в качестве третьего аргумента метода:
return response()->download($pathToFile);
return response()->download($pathToFile, $name, $headers);
Symfony HttpFoundation, управляющий загрузкой файлов, требует, чтобы имя загружаемого файла было в кодировке ASCII.
Ответы на файлы
Метод file
может использоваться для отображения файла, например изображения или PDF-файла, непосредственно в браузере пользователя вместо запуска загрузки. Этот метод принимает абсолютный путь к файлу в качестве первого аргумента и массив заголовков в качестве второго аргумента:
return response()->file($pathToFile);
return response()->file($pathToFile, $headers);
Потоковые ответы
Передавая данные клиенту по мере их создания, вы можете значительно сократить использование памяти и повысить производительность, особенно для очень больших ответов. Потоковые ответы позволяют клиенту начать обработку данных до того, как сервер завершит их отправку:
function streamedContent(): Generator {
yield 'Hello, ';
yield 'World!';
}
Route::get('/stream', function () {
return response()->stream(function (): void {
foreach (streamedContent() as $chunk) {
echo $chunk;
ob_flush();
flush();
sleep(2); // Simulate delay between chunks...
}
}, 200, ['X-Accel-Buffering' => 'no']);
});
Внутри Laravel использует функцию буферизации вывода PHP. Как вы можете видеть в приведенном выше примере, вам следует использовать функции
ob_flush
иflush
для отправки буферизованного содержимого клиенту.
Потоковые ответы JSON
Если вам нужно поэтапно передавать данные JSON, вы можете использовать метод streamJson
. Этот метод особенно полезен для больших наборов данных, которые необходимо постепенно отправлять в браузер в формате, который можно легко проанализировать с помощью JavaScript:
use App\Models\User;
Route::get('/users.json', function () {
return response()->streamJson([
'users' => User::cursor(),
]);
});
Потоковые загрузки
По желанию можно превратить строковый ответ переданной функции в загружаемый ответ без необходимости записывать результирующее содержимое на диск. В этом сценарии вы можете использовать метод streamDownload
. Этот метод принимает в качестве аргументов замыкание, имя файла и необязательный массив заголовков:
use App\Services\GitHub;
return response()->streamDownload(function () {
echo GitHub::api('repo')
->contents()
->readme('laravel', 'laravel')['contents'];
}, 'laravel-readme');
Макрокоманды ответа
Если вы хотите определить собственный ответ, который вы можете повторно использовать в различных маршрутах и контроллерах, то вы можете использовать метод macro
фасада Response
. Как правило, этот метод следует вызывать в методе boot
одного из поставщиков служб вашего приложения, например, App\Providers\AppServiceProvider
:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Загрузка любых служб приложения.
*/
public function boot(): void
{
Response::macro('caps', function (string $value) {
return Response::make(strtoupper($value));
});
}
}
Метод macro
принимает имя как свой первый аргумент и замыкание – как второй аргумент. Замыкание макрокоманды будет выполнено при вызове имени макрокоманды из реализации ResponseFactory
или глобального помощника response
:
return response()->caps('foo');