Компонент BrowserKit
Дата оновлення перекладу 2024-04-30
Компонент BrowserKit
Компонент BrowserKit симулює поведінку веб-брайзера, дозволяючи вам програмно робити запити, натискати на посилання та відправляти форми.
Установка
1
$ composer require symfony/browser-kit
Note
Якщо ви встановлюєте цей компонент поза додатком Symfony, вам потрібно підключити
файл vendor/autoload.php
у вашому коді для включення механізму автозавантаження
класів, наданих Composer. Детальніше можна прочитати у цій статті.
Базове застосування
See also
Ця стаття поясннює, як використовувати функції BrowserKit в якості незалежного компоненту в будь-якому PHP-додатку. Прочитайте статтю Функціональні тести Symfony , щоб зрозуміти, як використовувати його у додатках Symfony.
Створення клієнта
Компонент адає лише абстрактного клієнта, і не надає готового до використання
бекенду для рівня HTTP. Щоб створити вашого власного клієнта, вам потрібно
розширити клас AbstractBrowser
та реалізувати метод doRequest().
Цей метод приймає запит та повинен повернути відповідь:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
namespace Acme;
use Symfony\Component\BrowserKit\AbstractBrowser;
use Symfony\Component\BrowserKit\Response;
class Client extends AbstractBrowser
{
protected function doRequest($request): Response
{
// ... перетворити запит у відповідь
return new Response($content, $status, $headers);
}
}
Для простої реалізації браузера, заснованого на шарі HTTP, подивіться на
HttpBrowser, наданий
цим компонентом . Для реалізації,
заснованої на HttpKernelInterface
, подивіться на HttpClientKernel,
наданий компонентом HttpKernel.
Як робити запити
Використовуйте метод request(), щоб робити HTTP-запити. Перші два аргументів - HTTP-метод та запитуваний URL:
1 2 3 4
use Acme\Client;
$client = new Client();
$crawler = $client->request('GET', '/');
Значення, повернене методом request()
- це екземпляр класу
Crawler, наданий
DomCrawler component, який дозволяє
програмний доступ та траверсування HTML елементів.
Метод jsonRequest(),
який визначає ті ж аргументи, що і метод request()
, є ярликом для перетворення
параметрів запиту в JSON-рядок та встановлення необхідних HTTP-заголовків:
1 2 3 4 5
use Acme\Client;
$client = new Client();
// це зашифровує параметри як JSON і встановлює необхідні заголовки CONTENT_TYPE та HTTP_ACCEPT
$crawler = $client->jsonRequest('GET', '/', ['some_parameter' => 'some_value']);
Метод xmlHttpRequest(),
який визначає ті ж аргументи, що і метод request()
, є ярликом для створення
AJAX-запитів:
1 2 3 4 5
use Acme\Client;
$client = new Client();
// необхідний заголовок HTTP_X_REQUESTED_WITH додається автоматично
$crawler = $client->xmlHttpRequest('GET', '/');
Натискання на посилання
AbstractBrowser
здатний симулювати натискання на посилання. Передайте зміст
тексту посиланння, а клієнт виконає необхідний запит HTTP GET, щоб симулювати
натискання на посилання:
1 2 3 4 5 6
use Acme\Client;
$client = new Client();
$client->request('GET', '/product/123');
$crawler = $client->clickLink('Go elsewhere...');
Якщо вам потрібен обʼєкт Link, який надає доступ
до властивостей посилання (наприклад, $link->getMethod()
, $link->getUri()
), використайте
цей другий метод:
1 2 3 4
// ...
$crawler = $client->request('GET', '/product/123');
$link = $crawler->selectLink('Go elsewhere...')->link();
$client->click($link);
Методи click() та
clickLink()
можуть прийняти опціональний аргумент serverParameters
. Цей параметр
дозволяє вам додавати додаткову інформацію на кшталт заголовків при натисканні
на посилання:
1 2 3 4 5 6 7 8 9 10 11
use Acme\Client;
$client = new Client();
$client->request('GET', '/product/123');
// працює як з `click()`...
$link = $crawler->selectLink('Go elsewhere...')->link();
$client->click($link, ['X-Custom-Header' => 'Some data']);
// ... так і з `clickLink()`
$crawler = $client->clickLink('Go elsewhere...', ['X-Custom-Header' => 'Some data']);
Відправка форм
AbstractBrowser
також здатний відправлляти форми. Спочатку, оберіть форму,
використовуючи будь-яку її кнопку, а потім перевизначте будь-яку з її властивостей
(метод, значення поля та ін.), перед її відправкою:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
use Acme\Client;
$client = new Client();
$crawler = $client->request('GET', 'https://github.com/login');
// знайти форму з кнопкою 'Log in' та відправити її
// 'Log in' може бути текстовим змістом, id, значенням або імʼям <button> чи <input type="submit">
$client->submitForm('Log in');
// другий необовʼязковий аргумент дозволяє вам перевизначати значення полів форми за замовчуванням
$client->submitForm('Log in', [
'login' => 'my_user',
'password' => 'my_pass',
// щоб завантажити файл, значення має бути абсолютнним шляхом файлу
'file' => __FILE__,
]);
// ви можете також перевизначити інші опції форми
$client->submitForm(
'Log in',
['login' => 'my_user', 'password' => 'my_pass'],
// перевизначити HTTP-метод форми за замовчуванням
'PUT',
// перевизначити деякі параметри $_SERVER (наприклад, HTTP-заголовки)
['HTTP_ACCEPT_LANGUAGE' => 'es']
);
Якщо вам потрібен обʼєкт Form, який
надає доступ до властивостей форми (наприклад, $form->getUri()
,
$form->getValues()
, $form->getFields()
), використайте цей інший метод:
1 2 3 4 5 6 7 8 9
// ...
// обрати форму та заповнити якісь значення
$form = $crawler->selectButton('Log in')->form();
$form['login'] = 'symfonyfan';
$form['password'] = 'anypass';
// відправити цю форму
$crawler = $client->submit($form);
Обробка користувацьких заголовків
Необовʼязкові HTTP-заголовки, передані методу request()
, слідують формату запиту
FastCGI (верхній регістр, нижні підкреслення замість дефісів та префікс HTTP_
).
До збереження цих заголовків у запит, вони переводяться у нижний регістр, HTTP_
прибирається, а нижні підкреслення перетворюються на дефіси.
Якщо ви робите запит до додатку, який має спеціальні правила про регістр або пунктуацію
заголовків, перевизначте метод getHeaders()
, який має повертати асоційований масив
заголовків:
1 2 3 4 5 6 7 8 9
protected function getHeaders(Request $request): array
{
$headers = parent::getHeaders($request);
if (isset($request->getServer()['api_key'])) {
$headers['api_key'] = $request->getServer()['api_key'];
}
return $headers;
}
Куки
Вилучення куки
Реалізація AbstractBrowser
відображає куки (якщо вони є) через клас
CookieJar, який дозволяє вам зберігати
та вилучати будь-який куки під час виконання запитів з клієнтом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
use Acme\Client;
// Зробіть запит
$client = new Client();
$crawler = $client->request('GET', '/');
// Отримайте cookie Jar
$cookieJar = $client->getCookieJar();
// Отримайте куки за імʼям
$cookie = $cookieJar->get('name_of_the_cookie');
// Отримайте дані куки
$name = $cookie->getName();
$value = $cookie->getValue();
$rawValue = $cookie->getRawValue();
$isSecure = $cookie->isSecure();
$isHttpOnly = $cookie->isHttpOnly();
$isExpired = $cookie->isExpired();
$expires = $cookie->getExpiresTime();
$path = $cookie->getPath();
$domain = $cookie->getDomain();
$sameSite = $cookie->getSameSite();
Note
Ці методи повертають лише куки, строк дії яких не закінчився.
Кільцювання через куки
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
use Acme\Client;
// Зробіть запит
$client = new Client();
$crawler = $client->request('GET', '/');
// Отримайте cookie Jar
$cookieJar = $client->getCookieJar();
// Отримайте масив з усіма куки
$cookies = $cookieJar->all();
foreach ($cookies as $cookie) {
// ...
}
// Отримайте всі значення
$values = $cookieJar->allValues('http://symfony.com');
foreach ($values as $value) {
// ...
}
// Отримайте всі сирі значення
$rawValues = $cookieJar->allRawValues('http://symfony.com');
foreach ($rawValues as $rawValue) {
// ...
}
Установка куки
Ви також можете створювати куки та додавати їх у cookie jar, яка може бути впроваджена у контруктор клієнта:
1 2 3 4 5 6 7 8 9 10
use Acme\Client;
// створіть куки та додайте в cookie jar
$cookie = new Cookie('flavor', 'chocolate', strtotime('+1 day'));
$cookieJar = new CookieJar();
$cookieJar->set($cookie);
// створіть клієнта та встановіть куки
$client = new Client(array(), null, $cookieJar);
// ...
Відправка куки
Запити можуть містити куки. Щоб зробити це, використайте аргумент serverParameters
методу request(), щоб
встановити значення заголовку Cookie
:
1 2 3 4 5 6
$client->request('GET', '/', [], [], [
'HTTP_COOKIE' => new Cookie('flavor', 'chocolate', strtotime('+1 day')),
// ви також можете передати зміст куки в якості рядка
'HTTP_COOKIE' => 'flavor=chocolate; expires=Sat, 11 Feb 2023 12:18:13 GMT; Max-Age=86400; path=/'
]);
Note
Всі HTTP-заголовки, встановлені з аргументом serverParameters
, повинні
мати префікс HTTP_
.
Історія
Клієнт зберігає всі ваши запити, дозволяючи вам переміщуватися по вашій історії вперед та назад:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
use Acme\Client;
$client = new Client();
$client->request('GET', '/');
// оберіть та натисніть на посилання
$link = $crawler->selectLink('Documentation')->link();
$client->click($link);
// перейдіть назад до домашньої сторінки
$crawler = $client->back();
// перейдіть вперео до сторінки документації
$crawler = $client->forward();
Ви можете видаляти історію клієнта методом restart()
. Це також видалить
усі куки:
1 2 3 4 5 6 7
use Acme\Client;
$client = new Client();
$client->request('GET', '/');
// перезапустіть клієнта (історія та куки також очищуються)
$client->restart();
Зовнішні HTTP-запити
До цих пір, всі приклади у цій статті припускали, що ви робите внутрішні запити до вашого власного додатку. Однак, ви можете виконати точно такі ж приклади під час HTTP-запитів до зовнішніх веб-сайтів та додатків.
Спочатку встановіть та сконфігуруйте компонент HttpClient. Потім, використайте HttpBrowser, щоб створити клієнта, який буде робити зовнішні HTTP-запити:
1 2 3 4
use Symfony\Component\BrowserKit\HttpBrowser;
use Symfony\Component\HttpClient\HttpClient;
$browser = new HttpBrowser(HttpClient::create());
Тепер ви можете використовувати будь-який з методів, показаних у цій статті, щоб вилучати інформацію, натискати на посилання, відправляти форми і т.д. Це означає, що вам більше не потрібно використовувати відповідний веб-краулер або скрейпер, на кшталт Goutte:
1 2 3 4 5 6 7 8
$browser = new HttpBrowser(HttpClient::create());
$browser->request('GET', 'https://github.com');
$browser->clickLink('Sign in');
$browser->submitForm('Sign in', ['login' => '...', 'password' => '...']);
$openPullRequests = trim($browser->clickLink('Pull requests')->filter(
'.table-list-header-toggle a:nth-child(1)'
)->text());
Tip
Ви також можете використовувати опції клієнта HTTP типу ciphers
, auth_basic
та query
. Вони мають бути передані як аргумент опції за замовчуванням клієнту,
який використовується HTTP-браузером.
Робота з HTTP-відповідями
При використанні компонента BrowserKit, вам може знадобитися працювати з відповідями на
запити, які ви робили. Щоб зробити це, викличте метод getResponse()
обʼєкта HttpBrowser
.
Цей метод повертає останню відповідь, яку отримав браузер:
1 2 3 4
$browser = new HttpBrowser(HttpClient::create());
$browser->request('GET', 'https://foo.com');
$response = $browser->getResponse();
Якщо ви робите запити, які призводять до відповідей JSON, ви можете використати метод
toArray()
, щоб перетворити документ JSON на PHP-масив, без необхідності викликати
json_decode()
чітко:
1 2 3 4 5
$browser = new HttpBrowser(HttpClient::create());
$browser->request('GET', 'https://api.foo.com');
$response = $browser->getResponse()->toArray();
// $response - це PHP-масив дешифрованого змісту JSON