git 6357172dc49acd8a2600b8d153f125ee743dfdb9
- Введение
- Взаимодействие с запросом
- Данные полей ввода
- Файлы
- Конфигурирование доверенных прокси
- Конфигурирование доверенных хостов
Класс Illuminate\Http\Request
Laravel предлагает объектно-ориентированный способ взаимодействия с текущим HTTP-запросом, обрабатываемым вашим приложением, а также извлечение входных данных, файлов Cookies и файлов, отправленных вместе с запросом.
Чтобы получить экземпляр текущего 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
или 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-адреса клиента, который сделал запрос к вашему приложению:
$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 определяет интерфейсы для сообщений HTTP, включая запросы и ответы. Если вы хотите получить экземпляр запроса PSR-7 вместо запроса Laravel, вам сначала необходимо установить несколько библиотек. Laravel использует компонент Symfony HTTP Message Bridge для преобразования типичных запросов и ответов Laravel в реализации, совместимой с PSR-7:
composer require symfony/psr-http-message-bridge
composer require nyholm/psr7
После того как вы установили эти библиотеки, вы можете получить запрос PSR-7, объявив тип интерфейса запроса для замыкания вашего маршрута или контроллера:
use Psr\Http\Message\ServerRequestInterface;
Route::get('/', function (ServerRequestInterface $request) {
//
});
{tip} Если вы вернете экземпляр ответа PSR-7 из маршрута или контроллера, он будет автоматически преобразован обратно в экземпляр ответа Laravel и отобразится фреймворком.
Вы можете получить все данные входящего запроса в виде массива, используя метод 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 с помощью метода input
, если заголовок запроса Content-Type
корректно установлен как application/json
. Вы даже можете использовать «точечную» нотацию для извлечения значений, вложенных в JSON-массивы:
$name = $request->input('user.name');
При работе с элементами HTML, такими как флажки, ваше приложение может получать «логические» значения, которые на самом деле являются строками. Например, строковые «true» или «on». Для удобства вы можете использовать метод boolean
, чтобы получить эти значения как логические. Метод boolean
возвращает true
для 1
, true
, и строковых «1», «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
. Оба метода принимают один массив или динамический список аргументов:
$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) {
// Значение "имя" присутствует...
}, function () {
// Значение "имя" отсутствует...
});
Метод hasAny
возвращает true
, если присутствует какое-либо из указанных значений:
if ($request->hasAny(['name', 'email'])) {
//
}
Если вы хотите определить, присутствует ли значение в запросе и не является ли оно пустым, то вы можете использовать метод filled
:
if ($request->filled('name')) {
//
}
Метод whenFilled
выполнит указанное замыкание, если значение присутствует в запросе и не является пустым:
$request->whenFilled('name', function ($input) {
//
});
Второе замыкание может быть передано методу whenFilled
которое будет выполнено, если указанное значение «не заполнено»:
$request->whenFilled('name', function ($input) {
// Значение "имя" заполнено ...
}, function () {
// Значение "имя" не заполнено...
});
Чтобы определить, отсутствует ли конкретный ключ в запросе, вы можете использовать метод 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') }}">
Все файлы Cookies, созданные фреймворком 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
, который расширяет класс SplFileInfo
PHP и содержит различные методы для взаимодействия с файлом:
$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 будет отвечать на все запросы, которые он получает, независимо от содержимого заголовка Host
HTTP-запроса. Кроме того, значение заголовка Host
будет использоваться при генерации абсолютных URL-адресов вашего приложения во время веб-запроса.
Как правило, вам следует настроить свой веб-сервер (Nginx или Apache), так, чтобы он обслуживал запросы, соответствующие только указанному имени хоста. Однако, если у вас нет возможности напрямую настроить свой веб-сервер и вам нужно указать Laravel, чтобы он отвечал только на определенные имена хостов, вы можете сделать это, задействовав посредник App\Http\Middleware\TrustHosts
для вашего приложения.
Посредник TrustHosts
уже содержится в стеке $middleware
вашего приложения; однако вы должны раскомментировать его, чтобы он стал активным. В методе hosts
этого посредника вы можете указать имена хостов, на которые ваше приложение должно отвечать. Входящие запросы с другими значениями заголовка Host
будут отклонены:
/**
* Получить шаблоны доверенных хостов.
*
* @return array
*/
public function hosts()
{
return [
'laravel.test',
$this->allSubdomainsOfApplicationUrl(),
];
}
Метод allSubdomainsOfApplicationUrl
вернет регулярное выражение, соответствующее всем поддоменам значения app.url
конфигурации вашего приложения. Этот метод обеспечивает удобный способ разрешить все поддомены вашего приложения при создании приложения, с использованием поддоменов, определяемых метасимволами подстановки.