git 58b5d7776b6ea1b04bfbe1f54c4800bc053f83aa
Все маршруты и контроллеры должны возвращать ответ, который будет отправлен обратно в браузер пользователя. Laravel предлагает несколько разных способов вернуть ответы. Самый простой ответ – это возврат строки из маршрута или контроллера. Фреймворк автоматически преобразует строку в полный HTTP-ответ:
Route::get('/', function () {
return 'Hello World';
});
Помимо возврата строк из ваших маршрутов и контроллеров, вы также можете возвращать массивы. Фреймворк автоматически преобразует массив в ответ JSON:
Route::get('/', function () {
return [1, 2, 3];
});
{tip} Знаете ли вы, что можете возвращать коллекции 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 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 к исходящему экземпляру 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);
Если вы хотите сгенерировать экземпляр Symfony\Component\HttpFoundation\Cookie
, который может быть добавлен к экземпляру ответа позже, вы можете использовать глобальный помощник cookie
. Этот файл Cookies не будет отправлен обратно клиенту, если он не прикреплен к экземпляру ответа:
$cookie = cookie('name', 'value', $minutes);
return response('Hello World')->cookie($cookie);
Вы можете удалить куки, обнулив срок его действия с помощью метода withoutCookie
исходящего ответа:
return response('Hello World')->withoutCookie('name');
Если у вас еще нет экземпляра исходящего ответа, вы можете использовать метод expire
фасада Cookie
для обнуления срока действия кук:
Cookie::expire('name');
По умолчанию все файлы Cookies, генерируемые Laravel, зашифрованы и подписаны, поэтому клиент не может их изменить или прочитать. Если вы хотите отключить шифрование для некоторого подмножества файлов Cookies, создаваемых вашим приложением, вы можете использовать свойство $except
посредника App\Http\Middleware\EncryptCookies
, находящегося в каталоге app/Http/Middleware
:
/**
* Имена файлов Cookies, которые не должны быть зашифрованы.
*
* @var array
*/
protected $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]);
Если вы перенаправляете на маршрут с параметром ID
, который извлекается из модели Eloquent, то вы можете просто передать саму модель. ID будет извлечен автоматически:
// Для маршрута со следующим URI: /profile/{id}
return redirect()->route('profile', [$user]);
Если вы хотите настроить значение, которое соответствует параметру маршрута, то вы можете указать столбец при определении параметра маршрута (/profile/{id:slug}
) или переопределить метод getRouteKey
в вашей модели Eloquent:
/**
* Получить значение ключа маршрута модели.
*
* @return mixed
*/
public function getRouteKey()
{
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-шаблон в качестве содержимого ответа, то вы должны использовать метод view
:
return response()
->view('hello', $data, 200)
->header('Content-Type', $type);
Конечно, вы можете использовать глобальный помощник view
, даже если вам не нужно передавать собственные код состояния или заголовки HTTP.
Метод 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);
{note} Symfony HttpFoundation, управляющий загрузкой файлов, требует, чтобы имя загружаемого файла было в кодировке ASCII.
По желанию можно превратить строковый ответ переданной функции в загружаемый ответ без необходимости записывать результирующее содержимое на диск. В этом сценарии вы можете использовать метод streamDownload
. Этот метод принимает в качестве аргументов замыкание, имя файла и необязательный массив заголовков:
use App\Services\GitHub;
return response()->streamDownload(function () {
echo GitHub::api('repo')
->contents()
->readme('laravel', 'laravel')['contents'];
}, 'laravel-readme');
Метод file
используется для отображения файла, такого как изображение или PDF, непосредственно в браузере пользователя вместо того, чтобы инициировать загрузку. Этот метод принимает путь к файлу в качестве первого аргумента и массив заголовков в качестве второго аргумента:
return response()->file($pathToFile);
return response()->file($pathToFile, $headers);
Если вы хотите определить собственный ответ, который вы можете повторно использовать в различных маршрутах и контроллерах, то вы можете использовать метод macro
фасада Response
. Как правило, этот метод следует вызывать в методе boot
одного из поставщиков служб вашего приложения, например, App\Providers\AppServiceProvider
:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Загрузка любых служб приложения.
*
* @return void
*/
public function boot()
{
Response::macro('caps', function ($value) {
return Response::make(strtoupper($value));
});
}
}
Метод macro
принимает имя как свой первый аргумент и замыкание – как второй аргумент. Замыкание макрокоманды будет выполнено при вызове имени макрокоманды из реализации ResponseFactory
или глобального помощника response
:
return response()->caps('foo');