пятница, 24 августа 2012 г.

[PHP] Отправляем POST запрос через file_get_contens

Чтобы получить содержимое веб-страницы все с удовольствием используют file_get_contents(), например file_get_contents('http://www.habrahabr.ru/'). Но я уже давно наблюдаю, что, как дело доходит до того, чтобы отправить POST, разработчики используют либо CURL, либо открывают сокеты. Я не считаю, что это плохо или что не надо так делать, просто для решения простых задач можно использовать простые решения.


Я и сам так раньше делал, пока на наткнулся на понятие контекстов потоковых операций в PHP. Контекст позволяет передать дополнительные параметры потоковому обработчику. Для http например, можно сконфигурировать POST-запрос или передать дополнительные заголовки.

file_get_contents() принимает третьим параметром «контекст», который собственно и конфигурирует сам запрос.
Ниже пример такого запроса или RTFM


<?php
error_reporting(E_ALL);
require_once 'simpletest/unit_tester.php';
require_once 'simpletest/default_reporter.php';

define('PARAM_NAME',  'var');
define('PARAM_VALUE''testData');
define('QUERY',       'var=testData');

/**
 * Набор тестов
 */
class FileGetContentsTest extends UnitTestCase {

    /**
     * Проверить, что пришел POST
     */
    public function testIsPost() {
        $this->assertEqual('POST', $_SERVER['REQUEST_METHOD'],
            'Expected POST request');
        $this->assertTrue(isset($_POST[PARAM_NAME]) && $_POST[PARAM_NAME] == PARAM_VALUE,
            'Expected POST contains ' . QUERY);
    }
}

/**
 * Отправить POST
 */
if (!$_SERVER['QUERY_STRING']) {

    // Создать контекст и инициализировать POST запрос
    $context = stream_context_create(array(
        'http' => array(
            'method' => 'POST',
            'header' => 'Content-Type: application/x-www-form-urlencoded' . PHP_EOL,
            'content' => QUERY,
        ),
    ));

    // Отправить запрос на себя, чтобы запустить тесты
    // и показать результат выполнения тестов
    echo file_get_contents(
        $file = "http://{$_SERVER['HTTP_HOST']}{$_SERVER['PHP_SELF']}?runTests",
        $use_include_path = false,
        $context);

/**
 * Запустить тесты
 */
} else {
    $suite = new FileGetContentsTest;
    $suite->run(new DefaultReporter());
}
Следуюшие файловые функции принимают контексты:
  • file
  • fopen
  • readfile
  • file_get_contents
  • file_put_contents