Что такое контекст потока create_stream_context?
При простом парсинге используется встроеная php-функция file_get_contents. В основном эту функцию применяют без дополнительный надстроек над ней, просто указывая адрес, который нужно открыть: file_get_contenst('http://site.com/page.html')
, и этого хватает.
Однако, бывают случаи, когда всё-же, обычной работы file_get_contents недостаточно. К примеру, нужно отправить POST-запрос, cookie, или работать через прокси, а переход на curl в рамках данной системе невозможен, или нерационален. В этом случае единственным решением является изменение контекста потока функции.
Контекст потока - это изменение поведения при получении данных, который меняется функцией stream_context_create
. Можно указать тип запроса (GET, POST, PUT, и любой другой поддерживаемый http-метод), прокси, заголовки, и т.д.. Все опции можно посмотреть по ссылке
Эта функция и есть ответом на вопрос: "как отправить post запрос file_get_contents
".
Если не передавать в file_get_contents
контекст, то это не означает, что его не будет. Просто, он будет проставляться дефолтным. Увидеть это можно явно, прочитав информацию о запросе, который создаётся стандартным потоком:
Однако, сегодня нас это не устраивает. И наша задача - изменить запрос на POST, передать некоторые данные в теле запроса, и изменить заголовки.
Функция stream_context_create
принимает ассоциативный массив параметров. И ввиду того, что мы будем делать http-запрос, то необходимо передать вложенный массив с ключём http, указав method, header и content:
stream_context_create([
'http' => [
'method' => 'POST', //метод запроса
'header' => 'Content-type: application/x-www-form-urlencoded', //заголовки
'content' => 'key1=value1'
]
]);
Этот код создаёт новый http поток, которые изменяет method на POST, проставляет заголовок, и передаёт POST-параметр key1 = value1, который попадает в массив $_POST.
Однако, простого вызова функции недостаточно для того, чтобы эти изменения вступили в силу. Теперь необходимо передать в функцию этот контекст. Это удобно, когда для разных запросов нужно указывать разные контексты.
В итоге, функция будет иметь вид:
file_get_contents(url, false, stream_context_create(data))
В нашем случае:
//по правилам http-запросов, заголовки отделяются символом переноса строки (\r\n),
//а имена и значения заголовков отделяются двоеточием
$headers = [
'Content-type: application/x-www-form-urlencoded', //заголовок
'Cookie: foo=bar;two=12' //куки, которые так же передаются в заголовке
];
$context = stream_context_create([
'http' => [
'method' => 'POST',
'content' => 'key=value&key2=value2', //формат записи post-данных
'header' => implode("\r\n", $headers), //для удобства заголовки вынесли в массив, и объединили их функцией implode
'user_agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36',
]
]);
$result = file_get_contents($url, false, $context);
И, в итоге, получаем финальный результат:
Который демонстирует, что данные пришли запросом POST, и с указанными нами параметрами.
Для лучшего усвоения материала, можем написать простой скрипт, перевода текста с английского на русский, используя yandex-переводчик.
Перед этим, необходимо получить API-ключ на странице
Сейчас, когда уже есть API-ключ, можем выполнить первый запрос на перевод текста. Однако, сначала, в соответствии с документацией, сформируем параметры самого запроса:
$data = [
'text' => 'Привет мир?', //текст
'lang' => 'ru-en', //язык перевода с русского на английский
'key' => 'ВАШ КЛЮЧ' //API ключ, полученный ранее
];
Однако, в виде массива отправить данные не получится, нам нужно привести их к виду: key1=valu1&key2=value2...
И, для того, чтобы не писать это вручную, существует специальная функция httt_build_query()
, которая и приводит массив к строке такого вида.
И теперь осталось только отправить запрос:
$context = stream_context_create([
'http' => [
'method' => 'POST',
'content' => http_build_query($data)
]
]);
$response = file_get_contents($url, false, $context);
$result = json_decode($response, true);
Здесь результат был получен в специальном формате json, который с помощью функции json_decode
приводится к виду массива. И вуаля, ожидаемый результат:
А сам перевод текста содержится в массиве под ключём text
Теперь вы знаете, назначение функции stream_context_create
, как подменять контекст, и отправлять POST-данные простой функцией file_get_contents, а так же, на примере запроса к API yandex-переводчика, узнали, как парсить json.