HTTP-запросы
- Введение
- Взаимодействие с запросом
- Ввод
- Файлы
- Настройка доверенных прокси
- Настройка доверенных хостов
Введение
Класс Laravel Illuminate\Http\Request
обеспечивает объектно-ориентированный способ взаимодействия с текущим HTTP-запросом, обрабатываемым вашим приложением, а также для получения входных данных, файлов cookie и файлов, которые были отправлены с запросом.
Взаимодействие с запросом
Доступ к запросу
Чтобы получить экземпляр текущего HTTP-запроса через внедрение зависимостей, Вы должны ввести класс Illuminate\Http\Request
с помощью метода замыкания маршрута или метода контроллера. Экземпляр входящего запроса будет автоматически внедрен Laravel контейнер службы:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class UserController extends Controller{ /** * Сохранить нового пользователя. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { $name = $request->input('name'); // }}
Как уже упоминалось, Вы также можете указать класс Illuminate\Http\Request
при замыкании маршрута. Сервисный контейнер автоматически вставит входящий запрос в замыкание при его выполнении:
use Illuminate\Http\Request; Route::get('/', function (Request $request) { //});
Внедрение зависимостей и параметры маршрута
Если Ваш метод контроллера также ожидает ввода от параметра маршрута, Вы должны указать параметры маршрута после других зависимостей. Например, если Ваш маршрут определен так:
use App\Http\Controllers\UserController; Route::put('/user/{id}', [UserController::class, 'update']);
Вы все еще можете ввести Illuminate\Http\Request
и получить доступ к параметру маршрута id
, определив свой метод контроллера следующим образом:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class UserController extends Controller{ /** * Обновить указанного пользователя. * * @param \Illuminate\Http\Request $request * @param string $id * @return \Illuminate\Http\Response */ public function update(Request $request, $id) { // }}
Путь и метод запроса
Экземпляр Illuminate\Http\Request
предоставляет множество методов для проверки входящего HTTP-запроса и расширяет класс Symfony\Component\HttpFoundation\Request
. Ниже мы обсудим несколько наиболее важных методов.
Получение пути запроса
Метод path
возвращает информацию о пути запроса. Итак, если входящий запрос нацелен на http://example.com/foo/bar
метод path
вернет foo/bar
:
$uri = $request->path();
Проверка пути / маршрута запроса
Метод is
позволяет проверить, соответствует ли путь входящего запроса заданному шаблону. При использовании этого метода Вы можете использовать символ *
в качестве подстановочного знака:
if ($request->is('admin/*')) { //}
Используя метод routeIs
, Вы можете определить, соответствует ли входящий запрос именованному маршруту:
if ($request->routeIs('admin.*')) { //}
Получение URL-адреса запроса
Чтобы получить полный URL для входящего запроса, Вы можете использовать методы url
или fullUrl
. Метод url
вернет URL без строки запроса, а метод fullUrl
включает строку запроса:
$url = $request->url(); $urlWithQueryString = $request->fullUrl();
Если вы хотите добавить данные строки запроса к текущему URL-адресу, вы можете вызвать метод fullUrlWithQuery
. Этот метод объединяет данный массив переменных строки запроса с текущей строкой запроса:
$request->fullUrlWithQuery(['type' => 'phone']);
Получение метода запроса
Метод method
вернет HTTP-команду для запроса. Вы можете использовать метод isMethod
для проверки соответствия HTTP-команды заданной строке:
$method = $request->method(); if ($request->isMethod('post')) { //}
Заголовки запроса
Вы можете получить заголовок запроса из экземпляра Illuminate\Http\Request
с помощью метода header
. Если заголовок отсутствует в запросе, будет возвращено значение null
. Однако метод header
принимает необязательный второй аргумент, который будет возвращен, если заголовок отсутствует в запросе:
$value = $request->header('X-Header-Name'); $value = $request->header('X-Header-Name', 'default');
Метод hasHeader
может использоваться, чтобы определить, содержит ли запрос заданный заголовок:
if ($request->hasHeader('X-Header-Name')) { //}
Для удобства метод bearerToken
может использоваться для извлечения токена носителя из заголовка Authorization
. Если такого заголовка нет, будет возвращена пустая строка:
$token = $request->bearerToken();
IP-адрес запроса
Метод ip
может использоваться для получения IP-адреса клиента, который сделал запрос Вашему приложению:
$ipAddress = $request->ip();
Согласование содержимого
Laravel предоставляет несколько методов для проверки типов запрошенного содержимого входящего запроса через заголовок Accept
. Во-первых, метод getAcceptableContentTypes
вернет массив, содержащий все типы контента, принятые запросом:
$contentTypes = $request->getAcceptableContentTypes();
Метод accepts
принимает массив типов контента и возвращает true
, если какой-либо из типов контента принят запросом. В противном случае будет возвращено false
:
if ($request->accepts(['text/html', 'application/json'])) { // ...}
Вы можете использовать метод prefers
, чтобы определить, какой тип контента из данного массива типов контента является наиболее предпочтительным для запроса. Если ни один из предоставленных типов контента не будет принят запросом, будет возвращено значение null
:
$preferred = $request->prefers(['text/html', 'application/json']);
Поскольку многие приложения обслуживают только HTML или JSON, Вы можете использовать метод expectsJson
, чтобы быстро определить, ожидает ли входящий запрос ответа JSON:
if ($request->expectsJson()) { // ...}
Запросы PSR-7
Стандарт PSR-7 определяет интерфейсы для сообщений HTTP, включая запросы и ответы. Если Вы хотите получить экземпляр запроса PSR-7 вместо запроса Laravel, Вам сначала необходимо установить несколько библиотек. Laravel использует компонент Symfony HTTP Message Bridge для преобразования типичных запросов и ответов Laravel в реализации, совместимые с PSR-7:
composer require symfony/psr-http-message-bridgecomposer require nyholm/psr7
После того, как Вы установили эти библиотеки, Вы можете получить запрос PSR-7, указав тип интерфейса запроса для Вашего метода замыкания маршрута или контроллера:
use Psr\Http\Message\ServerRequestInterface; Route::get('/', function (ServerRequestInterface $request) { //});
{tip} Если Вы вернете экземпляр ответа PSR-7 из маршрута или контроллера, он будет автоматически преобразован обратно в экземпляр ответа Laravel и отобразится фреймворком.
Ввод
Получение ввода
Получение всех входных данных
Вы можете получить все входные данные входящего запроса в виде массива array
, используя метод all
. Этот метод можно использовать независимо от того, поступает ли входящий запрос из HTML-формы или является запросом XHR:
$input = $request->all();
Используя метод collect
, вы можете получить все входные данные входящего запроса в виде коллекции:
$input = $request->collect();
Метод collect
также позволяет вам получить подмножество входных данных входящего запроса в виде коллекции:
$request->collect('users')->each(function ($user) { // ...});
Получение входного значения
Используя несколько простых методов, Вы можете получить доступ ко всему пользовательскому вводу из Вашего экземпляра Illuminate\Http\Request
, не беспокоясь о том, какой HTTP-глагол использовался для запроса. Независимо от HTTP-глагола, для получения пользовательского ввода может использоваться метод input
:
$name = $request->input('name');
Вы можете передать значение по умолчанию в качестве второго аргумента метода input
. Это значение будет возвращено, если запрошенное входное значение отсутствует в запросе:
$name = $request->input('name', 'Sally');
При работе с формами, которые содержат входные данные массива, используйте "точечную" нотацию для доступа к массивам:
$name = $request->input('products.0.name'); $names = $request->input('products.*.name');
Вы можете вызвать метод input
без аргументов, чтобы получить все входные значения в виде ассоциативного массива:
$input = $request->input();
Получение ввода из строки запроса
В то время как метод input
извлекает значения из всей полезной нагрузки запроса (включая строку запроса), метод query
будет извлекать значения только из строки запроса:
$name = $request->query('name');
Если данные значения запрошенной строки запроса отсутствуют, будет возвращен второй аргумент этого метода:
$name = $request->query('name', 'Helen');
Вы можете вызвать метод query
без аргументов, чтобы получить все значения строки запроса в виде ассоциативного массива:
$query = $request->query();
Получение входных значений JSON
При отправке запросов JSON в Ваше приложение Вы можете получить доступ к данным JSON с помощью метода input
, если заголовок запроса Content-Type
правильно установлен на application/json
. Вы даже можете использовать синтаксис с точкой для извлечения значений, вложенных в массивы JSON:
$name = $request->input('user.name');
Получение логических входных значений
При работе с элементами HTML, такими как флажки, Ваше приложение может получать «правдивые» значения, которые на самом деле являются строками. Например, «верно» или «включено». Для удобства Вы можете использовать метод boolean
, чтобы получить эти значения как логические. Метод boolean
возвращает true
для 1, "1", true, "true", "on" и "yes". Все остальные значения вернут false
:
$archived = $request->boolean('archived');
Получение входных значений даты
Для удобства входные значения, содержащие дату/время, могут быть получены как экземпляры Carbon с использованием метода date
. Если запрос не содержит входного значения с заданным именем, будет возвращен null
:
$birthday = $request->date('birthday');
Второй и третий аргументы, принимаемые методом date
, могут использоваться для указания формата даты и часового пояса соответственно:
$elapsed = $request->date('elapsed', '!H:i', 'Europe/Madrid');
Если входное значение присутствует, но имеет недопустимый формат, будет выдано исключение InvalidArgumentException
; поэтому рекомендуется проверять ввод перед вызовом метода date
.
Получение ввода через динамические свойства
Вы также можете получить доступ к вводу пользователя, используя динамические свойства экземпляра Illuminate\Http\Request
. Например, если одна из форм Вашего приложения содержит поле name
, Вы можете получить доступ к значению поля следующим образом:
$name = $request->name;
При использовании динамических свойств Laravel сначала будет искать значение параметра в полезной нагрузке запроса. Если его нет, Laravel будет искать поле в параметрах согласованного маршрута.
Получение части входных данных
Если Вам нужно получить подмножество входных данных, Вы можете использовать методы only
и except
. Оба эти метода принимают один массив array
или динамический список аргументов:
$input = $request->only(['username', 'password']); $input = $request->only('username', 'password'); $input = $request->except(['credit_card']); $input = $request->except('credit_card');
{note} Метод
only
возвращает все пары ключ / значение, которые Вы запрашиваете; однако он не вернет пары ключ / значение, которых нет в запросе.
Определение наличия ввода
Вы можете использовать метод has
, чтобы определить, присутствует ли значение в запросе. Метод has
возвращает true
, если значение присутствует в запросе:
if ($request->has('name')) { //}
При задании массива метод has
определяет, присутствуют ли все указанные значения:
if ($request->has(['name', 'email'])) { //}
Метод whenHas
выполнит данное замыкание, если в запросе присутствует значение:
$request->whenHas('name', function ($input) { //});
Второе замыкание может быть передано в метод whenHas
, который будет выполняться, если указанное значение не присутствует в запросе:
$request->whenHas('name', function ($input) { // The "name" value is present...}, function () { // The "name" value is not present...});
The hasAny
method returns true
if any of the specified values are present:
if ($request->hasAny(['name', 'email'])) { //}
Если Вы хотите определить, присутствует ли значение в запросе и не является ли оно пустым, Вы можете использовать метод filled
:
if ($request->filled('name')) { //}
Метод whenFilled
выполнит указанное замыкание, если значение присутствует в запросе и не является пустым:
$request->whenFilled('name', function ($input) { //});
Второе замыкание может быть передано в метод whenFilled
, который будет выполняться, если указанное значение не "заполнено":
$request->whenFilled('name', function ($input) { // The "name" value is filled...}, function () { // The "name" value is not filled...});
Чтобы определить, отсутствует ли данный ключ в запросе, вы можете использовать метод missing
:
if ($request->missing('name')) { //}
Объединение дополнительного ввода
Иногда может потребоваться вручную объединить дополнительные входные данные с существующими входными данными запроса. Для этого вы можете использовать метод merge
:
$request->merge(['votes' => 0]);
Метод mergeIfMissing
может использоваться для объединения ввода с запросом, если соответствующие ключи еще не существуют во входных данных запроса:
$request->mergeIfMissing(['votes' => 0]);
Старый ввод
Laravel позволяет Вам сохранить ввод из одного запроса во время следующего запроса. Эта функция особенно полезна для повторного заполнения форм после обнаружения ошибок проверки. Однако, если Вы используете Laravel включенные функции проверки, возможно, Вам не нужно будет вручную использовать эти методы ввода данных сеанса напрямую, как некоторые из встроенных в Laravel средства проверки будут вызывать их автоматически.
Проброс ввода для сессии
Метод flash
в классе Illuminate\Http\Request
будет пробрасывать текущий ввод в сессию, чтобы он был доступен во время следующего запроса пользователя к приложению:
$request->flash();
Вы также можете использовать методы flashOnly
и flashExcept
для передачи подмножества данных запроса в сеанс. Эти методы полезны для хранения конфиденциальной информации, такой как пароли, вне сессии:
$request->flashOnly(['username', 'email']); $request->flashExcept('password');
Проброс ввода, затем редирект
Так как Вы часто захотите выполнить проброс ввода в сессию, а затем перенаправить его на предыдущую страницу, Вы можете легко связать проброс ввода с перенаправлением, используя метод withInput
:
return redirect('form')->withInput(); return redirect()->route('user.create')->withInput(); return redirect('form')->withInput( $request->except('password'));
Получение старого ввода
Чтобы получить флэш-ввод из предыдущего запроса, вызовите метод old
для экземпляра Illuminate\Http\Request
. Метод old
извлечет ранее записанные входные данные из сессии:
$username = $request->old('username');
Laravel также предоставляет глобального помощника old
. Если Вы показываете старый ввод в шаблоне Blade, удобнее использовать помощник old
для повторного заполнения формы. Если для данного поля нет старого ввода, будет возвращен null
:
<input type="text" name="username" value="{{ old('username') }}">
Файлы cookie
Получение файлов cookie из запросов
Все файлы cookie, созданные фреймворком Laravel, зашифрованы и подписаны кодом аутентификации, что означает, что они будут считаться недействительными, если они были изменены клиентом. Чтобы получить значение cookie из запроса, используйте метод cookie
в экземпляре Illuminate\Http\Request
:
$value = $request->cookie('name');
Обрезка и нормализация ввода
По умолчанию Laravel включает мидлвар App\Http\Middleware\TrimStrings
и App\Http\Middleware\ConvertEmptyStringsToNull
в глобальный стек мидлвара Вашего приложения. Этот мидлвар перечислен в глобальном стеке мидлвара классом App\Http\Kernel
. Этот мидлвар будет автоматически обрезать все входящие строковые поля в запросе, а также конвертировать любые пустые строковые поля в null
. Это позволяет Вам не беспокоиться об этих проблемах нормализации в Ваших маршрутах и контроллерах.
Если Вы хотите отключить это поведение, Вы можете удалить два мидлвара из стека мидлвара Вашего приложения, удалив их из свойства $middleware
Вашего класса App\Http\Kernel
.
Файлы
Получение загруженных файлов
Вы можете получить загруженные файлы из экземпляра Illuminate\Http\Request
, используя метод file
или динамические свойства. Метод file
возвращает экземпляр класса Illuminate\Http\UploadedFile
, который расширяет класс PHP SplFileInfo
и предоставляет различные методы для взаимодействия с файлом:
$file = $request->file('photo'); $file = $request->photo;
Вы можете определить, присутствует ли файл в запросе, используя метод hasFile
:
if ($request->hasFile('photo')) { //}
Проверка успешных загрузок
Помимо проверки наличия файла, Вы можете убедиться, что не было проблем с загрузкой файла с помощью метода isValid
:
if ($request->file('photo')->isValid()) { //}
Пути к файлам и расширения
Класс UploadedFile
также содержит методы для доступа к полному пути к файлу и его расширению. Метод extension
попытается угадать расширение файла на основе его содержимого. Это расширение может отличаться от расширения, предоставленного клиентом:
$path = $request->photo->path(); $extension = $request->photo->extension();
Другие файловые методы
Для экземпляров UploadedFile
доступно множество других методов. Дополнительную информацию об этих методах смотрите в документации API для класса.
Сохранение загруженных файлов
Для хранения загруженного файла обычно используется одна из настроенных файловых систем. Класс UploadedFile
имеет метод store
, который перемещает загруженный файл на один из Ваших дисков, который может быть местом в Вашей локальной файловой системе или облачным хранилищем, например Amazon S3.
Метод store
принимает путь, по которому файл должен храниться, относительно настроенного корневого каталога файловой системы. Этот путь не должен содержать имени файла, поскольку в качестве имени файла будет автоматически создан уникальный идентификатор.
Метод store
также принимает необязательный второй аргумент для имени диска, который должен использоваться для хранения файла. Метод вернет путь к файлу относительно корня диска:
$path = $request->photo->store('images'); $path = $request->photo->store('images', 's3');
Если Вы не хотите, чтобы имя файла создавалось автоматически, Вы можете использовать метод storeAs
, который принимает путь, имя файла и имя диска в качестве аргументов:
$path = $request->photo->storeAs('images', 'filename.jpg'); $path = $request->photo->storeAs('images', 'filename.jpg', 's3');
{tip} Для получения дополнительной информации о хранении файлов в Laravel ознакомьтесь с полной документацией по хранению файлов.
Настройка доверенных прокси
При запуске Ваших приложений за балансировщиком нагрузки, который завершает сертификаты TLS / SSL, Вы можете заметить, что Ваше приложение иногда не генерирует ссылки HTTPS при использовании помощника url
. Обычно это происходит потому, что Ваше приложение перенаправляет трафик от Вашего балансировщика нагрузки на порт 80 и не знает, что оно должно генерировать безопасные ссылки.
Чтобы решить эту проблему, Вы можете использовать мидлвар App\Http\Middleware\TrustProxies
, который включен в Ваше приложение Laravel, которое позволяет Вам быстро настраивать балансировщики нагрузки или прокси, которым Ваше приложение должно доверять. Ваши доверенные прокси должны быть указаны в виде массива в свойстве $proxies
этого мидлвара. В дополнение к настройке доверенных прокси Вы можете настроить прокси $headers
, которым следует доверять:
<?php namespace App\Http\Middleware; use Illuminate\Http\Middleware\TrustProxies as Middleware;use Illuminate\Http\Request; class TrustProxies extends Middleware{ /** * Надежные прокси для этого приложения. * * @var string|array */ protected $proxies = [ '192.168.1.1', '192.168.1.2', ]; /** * Заголовки, которые следует использовать для обнаружения прокси. * * @var int */ protected $headers = Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO;}
{tip} Если Вы используете AWS Elastic Load Balancing, значение
$headers
должно бытьRequest::HEADER_X_FORWARDED_AWS_ELB
. Для получения дополнительной информации о константах, которые могут использоваться в свойстве$headers
, ознакомьтесь с документацией Symfony о доверенных прокси-серверах.
Доверять всем прокси
Если Вы используете Amazon AWS или другой поставщик «облачных» балансировщиков нагрузки, Вы можете не знать IP-адреса своих фактических балансировщиков. В этом случае Вы можете использовать *
, чтобы доверять всем прокси:
/** * Надежные прокси для этого приложения. * * @var string|array */protected $proxies = '*';
Настройка доверенных хостов
По умолчанию Laravel будет отвечать на все запросы, которые он получает, независимо от содержимого заголовка HTTP-запроса Host
. Кроме того, значение заголовка Host
будет использоваться при генерации абсолютных URL-адресов вашего приложения во время веб-запроса.
Как правило, вам следует настроить свой веб-сервер, такой как Nginx или Apache, так, чтобы он отправлял вашему приложению только запросы, соответствующие заданному имени хоста. Однако, если у вас нет возможности напрямую настроить свой веб-сервер и вам нужно указать Laravel отвечать только на определенные имена хостов, вы можете сделать это, включив мидлвар App\Http\Middleware\TrustHosts
для вашего приложения.
Мидлвар TrustHosts
уже включен в стек вашего приложения $middleware
; однако вы должны раскомментировать его, чтобы он стал активным. В методе этого мидлвара hosts
вы можете указать имена хостов, на которые ваше приложение должно отвечать. Входящие запросы с другими заголовками значений Host
будут отклонены:
/** * Get the host patterns that should be trusted. * * @return array */public function hosts(){ return [ 'laravel.test', $this->allSubdomainsOfApplicationUrl(), ];}
Вспомогательный метод allSubdomainsOfApplicationUrl
вернет регулярное выражение, соответствующее всем поддоменам значения конфигурации вашего приложения app.url
. Этот вспомогательный метод предоставляет удобный способ разрешить все поддомены вашего приложения при создании приложения, которое использует поддомены с подстановочными знаками.