1. Основы
  2. HTTP-запросы

Присоединяйся к нашему Telegram сообществу @webblend!

Здесь ты найдешь сниппеты по Laravel и полезные советы по веб-разработке.

Введение

Класс Illuminate\Http\Request Laravel предоставляет объектно-ориентированный способ взаимодействия с текущим HTTP-запросом, обрабатываемым вашим приложением, а также получение вводных данных, куки и файлов, отправленных с запросом.

Взаимодействие С Запросом

Доступ К Запросу

Чтобы получить экземпляр текущего HTTP-запроса с помощью внедрения зависимости, вы должны задать тип Illuminate\Http\Request на вашем маршруте или методе контроллера. Экземпляр входящего запроса будет автоматически внедрен Laravel контейнером служб:

<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
 
class UserController extends Controller
{
/**
* Сохранить нового пользователя.
*/
public function store(Request $request): RedirectResponse
{
$name = $request->input('name');
 
// Сохранить пользователя...
 
return redirect('/users');
}
}

Как упоминалось ранее, вы также можете использовать тип-подсказку класса 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\RedirectResponse;
use Illuminate\Http\Request;
 
class UserController extends Controller
{
/**
* Обновить указанного пользователя.
*/
public function update(Request $request, string $id): RedirectResponse
{
// Обновить пользователя...
 
return redirect('/users');
}
}

Путь, Хост И Метод Запроса

Экземпляр 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']);

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

$request->fullUrlWithoutQuery(['type']);

Получение Хоста Запроса

Вы можете получить "хост" входящего запроса с помощью методов host, httpHost и schemeAndHttpHost:

$request->host();
$request->httpHost();
$request->schemeAndHttpHost();

Получение Метода Запроса

Метод 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 request вместо запроса 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) {
// ...
});

Примечание Если вы возвращаете экземпляр PSR-7 response из маршрута или контроллера, он автоматически будет преобразован обратно в экземпляр Laravel response и отображен фреймворком.

Ввод

Получение Ввода

Получение Всех Данных Ввода

Вы можете получить все входящие данные запроса в виде массива с помощью метода all. Этот метод может быть использован независимо от того, является ли входящий запрос HTML-формой или является XHR-запросом:

$input = $request->all();

С помощью метода collect вы можете получить все входящие данные запроса в виде коллекции:

$input = $request->collect();

Метод collect также позволяет получить подмножество входящих данных запроса в виде коллекции:

$request->collect('users')->each(function (string $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');

Получение Строковых Значений Ввода

Вместо извлечения данных ввода запроса как примитивной string, вы можете использовать метод string для извлечения данных запроса в виде экземпляра Illuminate\Support\Stringable:

$name = $request->string('name')->trim();

Получение Булевых Значений Ввода

При работе с HTML-элементами, такими как флажки, ваше приложение может получать "истинные" значения, которые фактически являются строками. Например, "true" или "on". Для удобства вы можете использовать метод 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.

Получение Значений Ввода Enum

Значения ввода, соответствующие перечислениям PHP, также могут быть извлечены из запроса. Если в запросе отсутствует значение ввода с указанным именем или перечисление не имеет значений, соответствующих значению ввода, будет возвращено null. Метод enum принимает имя значения ввода и класс перечисления в качестве своих первого и второго аргументов соответственно:

use App\Enums\Status;
 
$status = $request->enum('status', Status::class);

Получение Ввода Через Динамические Свойства

Вы также можете получать ввод пользователя с использованием динамических свойств на экземпляре 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');

Внимание Метод only возвращает все ключи / значения, которые вы запрашиваете; однако он не вернет ключи / значения, которых нет в запросе.

Определение Присутствия Ввода

Вы можете использовать метод has, чтобы определить, присутствует ли значение в запросе. Метод has возвращает true, если значение присутствует в запросе:

if ($request->has('name')) {
// ...
}

При передаче массива метод has определит, присутствуют ли все указанные значения:

if ($request->has(['name', 'email'])) {
// ...
}

Метод hasAny возвращает true, если присутствует хотя бы одно из указанных значений:

if ($request->hasAny(['name', 'email'])) {
// ...
}

Метод whenHas выполнит предоставленное замыкание, если значение присутствует в запросе:

$request->whenHas('name', function (string $input) {
// ...
});

К методу whenHas может быть передано второе замыкание, которое будет выполнено, если указанное значение отсутствует в запросе:

$request->whenHas('name', function (string $input) {
// Значение "name" присутствует...
}, function () {
// Значение "name" отсутствует...
});

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

if ($request->filled('name')) {
// ...
}

Метод anyFilled возвращает true, если любое из указанных значений не является пустой строкой:

if ($request->anyFilled(['name', 'email'])) {
// ...
}

Метод whenFilled выполнит предоставленное замыкание, если значение присутствует в запросе и не является пустой строкой:

$request->whenFilled('name', function (string $input) {
// ...
});

К методу whenFilled может быть передано второе замыкание, которое будет выполнено, если указанное значение не является "filled":

$request->whenFilled('name', function (string $input) {
// Значение "name" заполнено...
}, function () {
// Значение "name" не заполнено...
});

Чтобы определить, отсутствует ли данный ключ в запросе, можно использовать методы missing и whenMissing:

if ($request->missing('name')) {
// ...
}
 
$request->whenMissing('name', function (array $input) {
// Значение "name" отсутствует...
}, function () {
// Значение "name" присутствует...
});

Слияние Дополнительного Ввода

Иногда вам может потребоваться вручную объединить дополнительные вводы существующих входных данных запроса. Для этого можно использовать метод merge. Если данный ключ ввода уже существует в запросе, его значения будут перезаписаны данными, предоставленными методу 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

Получение Cookies Из Запросов

Все файлы cookie, созданные фреймворком Laravel, зашифрованы и подписаны аутентификационным кодом, что означает, что они будут считаться недействительными, если их изменит клиент. Чтобы получить значение cookie из запроса, используйте метод cookie на экземпляре Illuminate\Http\Request:

$value = $request->cookie('name');

Обрезка и Нормализация Ввода

По умолчанию Laravel включает средства промежуточной обработки App\Http\Middleware\TrimStrings и Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull в глобальный стек промежуточной обработки вашего приложения. Эти средства промежуточной обработки перечислены в глобальном стеке промежуточной обработки в классе App\Http\Kernel. Эти средства промежуточной обработки автоматически обрезают все поступающие строки в запросе, а также преобразовывают любые пустые строки в null. Это позволяет вам не беспокоиться о таких нормализационных вопросах в ваших маршрутах и контроллерах.

Отключение Нормализации Ввода

Если вы хотите отключить это поведение для всех запросов, вы можете удалить два средства промежуточной обработки из стека промежуточной обработки вашего приложения, удалив их из свойства $middleware вашего класса App\Http\Kernel.

Если вы хотите отключить обрезку строк и преобразование пустых строк для подмножества запросов в вашем приложении, вы можете использовать метод skipWhen, предлагаемый обоими средствами промежуточной обработки. Этот метод принимает замыкание, которое должно возвращать true или false, чтобы указать, следует ли пропустить нормализацию ввода. Обычно метод skipWhen следует вызывать в методе boot вашего AppServiceProvider приложения.

use App\Http\Middleware\TrimStrings;
use Illuminate\Http\Request;
use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull;
 
/**
* Инициализировать все службы приложения.
*/
public function boot(): void
{
TrimStrings::skipWhen(function (Request $request) {
return $request->is('admin/*');
});
 
ConvertEmptyStringsToNull::skipWhen(function (Request $request) {
// ...
});
}

Файлы

Получение Загруженных Файлов

Вы можете получить загруженные файлы из экземпляра 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');

Примечание Для получения более подробной информации о хранении файлов в 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;
}

Примечание Если вы используете балансировку нагрузки 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<int, string>
*/
public function hosts(): array
{
return [
'laravel.test',
$this->allSubdomainsOfApplicationUrl(),
];
}

Метод-вспомогатель allSubdomainsOfApplicationUrl вернет регулярное выражение, соответствующее всем поддоменам значения конфигурации app.url вашего приложения. Этот метод-вспомогатель обеспечивает удобный способ разрешить все поддомены вашего приложения при построении приложения, использующего поддомены-шаблоны.