Компонент HttpFoundation определяет объектно-ориентированный уровень для HTTP.
В PHP запрос представлен некоторыми глобальными переменными ($ _GET, $ _POST, $ _FILES, $ _COOKIE, $ _SESSION, …), и ответ генерируется некоторыми функциями (echo, header (), setcookie (), …).
Компонент Symfony HttpFoundation заменяет эти глобальные переменные и функции PHP отдельным объектно-ориентированным слоем.
Создание Request
Самый распространенный способ создания Request — это создать его на основе текущих глобальных переменных PHP с помощью createFromGlobals():
use Symfony\Component\HttpFoundation\Request;
$request = Request::createFromGlobals();
Это почти эквивалентно более многословному, но и более гибкому вызову методу __construct():
$request = new Request(
$_GET,
$_POST,
[],
$_COOKIE,
$_FILES,
$_SERVER
);
Получение доступа к данным в объекте Request Symfony
Объект Request содержит информацию о клиентском запросе. К этой информации можно получить доступ через несколько общедоступных свойств:
- request: эквивалент $ _POST;
- query: эквивалент $ _GET ($request->query->get(‘name’));
- cookies: эквивалент $ _COOKIE;
- attributes: нет эквивалента — используется вашим приложением для хранения других данных (см. ниже);
- files: эквивалент $ _FILES;
- server: эквивалент $ _SERVER;
- headers: в основном эквивалентны подмножеству $ _SERVER ($request->headers->get(‘User-Agent’)).
Каждое свойство является экземпляром ParameterBag (или подклассом), который является классом содержащим данные:
- request: ParameterBag;
- query: ParameterBag;
- cookies: ParameterBag;
- attributes: ParameterBag;
- files: FileBag;
- server: ServerBag;
- headers: HeaderBag.
Все экземпляры ParameterBag имеют методы для извлечения и обновления своих данных:
- all() Возвращает параметры.
- keys() Возвращает ключи параметров.
- replace() Заменяет текущие параметры новым набором.
- add() Добавляет параметры.
- get() Возвращает параметр по имени.
- set() Устанавливает параметр по имени.
- has() Возвращает true, если параметр определен.
- remove() Удаляет параметр.
Экземпляр ParameterBag также имеет несколько методов для фильтрации входных значений:
- getAlpha() Возвращает буквенные символы значения параметра;
- getAlnum() Возвращает буквенные символы и цифры значения параметра;
- getBoolean() Возвращает значение параметра, преобразованное в логическое значение;
- getDigits() Возвращает цифры значения параметра;
- getInt() Возвращает значение параметра, преобразованное в целое число;
- filter() Фильтрует параметр с помощью функции PHP filter_var.
Все получатели принимают до двух аргументов: первый — это имя параметра, а второй — значение по умолчанию, которое возвращается, если параметр не существует:
// the query string is '?foo=bar'
$request->query->get('foo');
// returns 'bar'
$request->query->get('bar');
// returns null
$request->query->get('bar', 'baz');
// returns 'baz'
Когда PHP импортирует запрос, он обрабатывает параметры запроса, такие как foo[bar]=baz особым образом, так как создает массив. Таким образом, вы можете получить параметр foo и получить обратно массив с элементом bar:
// the query string is '?foo[bar]=baz'
$request->query->get('foo');
// returns ['bar' => 'baz']
$request->query->get('foo[bar]');
// returns null
$request->query->get('foo')['bar'];
// returns 'baz'
Благодаря публичному свойству attributes вы можете хранить дополнительные данные в запросе, который также является экземпляром ParameterBag. Это в основном используется для прикрепления информации, которая относится к Request и к которой необходимо получить доступ из разных точек вашего приложения.
Наконец, необработанные данные, отправленные с телом запроса, могут быть доступны с помощью getContent():
$content = $request->getContent();
Например, это может быть полезно для обработки строки JSON, отправленной приложению удаленной службой с использованием метода HTTP POST.
Идентификация Request.
В вашем приложении вам нужен способ идентифицировать запрос; в большинстве случаев это делается через «информацию о пути» запроса, к которой можно получить доступ через метод getPathInfo():
// for a request to http://example.com/blog/index.php/pqost/hello-world
// the path info is "/post/hello-world"
$request->getPathInfo();
Имитация Request
Вместо того чтобы создавать запрос на основе глобальных переменных PHP, вы также можете смоделировать запрос:
$request = Request::create(
'/hello-world',
'GET',
['name' => 'Fabien']
);
Метод create() создает запрос на основе URI, метода и некоторых параметров (параметров запроса query или запроса request в зависимости от метода HTTP); и, конечно, вы также можете переопределить все другие переменные (по умолчанию Symfony создает разумные значения по умолчанию для всех глобальных переменных PHP).
Основываясь на таком запросе, вы можете переопределить глобальные переменные PHP с помощью overrideGlobals():
$request->overrideGlobals();
Вы также можете дублировать существующий запрос с помощью duplicate() или изменить набор параметров одним вызовом initialize().
Доступ к сессии запроса Request.
Если у вас есть сеанс, прикрепленный к запросу, вы можете получить к нему доступ через метод getSession(); метод hasPreviousSession() сообщает вам, содержит ли запрос сеанс, который был запущен в одном из предыдущих запросов.
Обработка заголовков запроса HTTP в Symfony.
Обработка заголовков HTTP не является тривиальной задачей из-за экранирования и обработки пустого пространства их содержимого. Symfony предоставляет класс HeaderUtils, который абстрагирует эту сложность и определяет некоторые методы для наиболее распространенных задач:
use Symfony\Component\HttpFoundation\HeaderUtils;
// Splits an HTTP header by one or more separators
HeaderUtils::split('da, en-gb;q=0.8', ',;');
// => [['da'], ['en-gb','q=0.8']]
// Combines an array of arrays into one associative array
HeaderUtils::combine([['foo', 'abc'], ['bar']]);
// => ['foo' => 'abc', 'bar' => true]
// Joins an associative array into a string for use in an HTTP header
HeaderUtils::toString(['foo' => 'abc', 'bar' => true, 'baz' => 'a b c'], ',');
// => 'foo=abc, bar, baz="a b c"'
// Encodes a string as a quoted string, if necessary
HeaderUtils::quote('foo "bar"');
// => '"foo \"bar\""'
// Decodes a quoted string
HeaderUtils::unquote('"foo \"bar\""');
// => 'foo "bar"'
Доступ в Symfony к данным заголовковAccept- *
Вы можете получить доступ к основным данным, извлеченным из заголовков Accept- *, используя следующие методы:
- getAcceptableContentTypes() Возвращает список принятых типов контента, упорядоченных по убыванию качества.
- getLanguages() Возвращает список принятых языков, упорядоченных по убыванию качества.
- getCharsets() Возвращает список принятых кодировок, отсортированных по убыванию качества.
- getEncodings() Возвращает список принятых кодировок, упорядоченных по убыванию качества.
Если вам нужно получить полный доступ к проанализированным данным из Accept, Accept-Language, Accept-Charset или Accept-Encoding, вы можете использовать служебный класс AcceptHeader:
use Symfony\Component\HttpFoundation\AcceptHeader;
$acceptHeader = AcceptHeader::fromString($request->headers->get('Accept'));
if ($acceptHeader->has('text/html')) {
$item = $acceptHeader->get('text/html');
$charset = $item->getAttribute('charset', 'utf-8');
$quality = $item->getQuality();
}
// Accept header items are sorted by descending quality
$acceptHeaders = AcceptHeader::fromString($request->headers->get('Accept'))
->all();
Значения по умолчанию, которые могут быть дополнительно включены в заголовки Accept- *, также поддерживаются:
$acceptHeader = 'text/plain;q=0.5, text/html, text/*;q=0.8, */*;q=0.3';
$accept = AcceptHeader::fromString($acceptHeader);
$quality = $accept->get('text/xml')->getQuality(); // $quality = 0.8
$quality = $accept->get('application/xml')->getQuality(); // $quality = 0.3
Анонимизация IP-адресов в Symfony Request.
Все более распространенная потребность приложений в соблюдении правил защиты пользователей заключается в анонимизации IP-адресов перед их регистрацией и хранением в целях анализа. Используйте метод anonymize() из IpUtils, чтобы сделать это:
use Symfony\Component\HttpFoundation\IpUtils;
$ipv4 = '123.234.235.236';
$anonymousIpv4 = IPUtils::anonymize($ipv4);
// $anonymousIpv4 = '123.234.235.0'
$ipv6 = '2a01:198:603:10:396e:4789:8e99:890f';
$anonymousIpv6 = IPUtils::anonymize($ipv6);
// $anonymousIpv6 = '2a01:198:603:10::'
Переопределение Request
Класс Request не должен быть переопределен, поскольку это объект данных, представляющий сообщение HTTP. Но при переходе от устаревшей системы может помочь добавление методов или изменение поведения по умолчанию. В этом случае зарегистрируйте вызываемый PHP, который может создать экземпляр вашего класса Request:
use App\Http\SpecialRequest;
use Symfony\Component\HttpFoundation\Request;
Request::setFactory(function (
array $query = [],
array $request = [],
array $attributes = [],
array $cookies = [],
array $files = [],
array $server = [],
$content = null
) {
return new SpecialRequest(
$query,
$request,
$attributes,
$cookies,
$files,
$server,
$content
);
});
$request = Request::createFromGlobals();