Пример использования в PHP библиотеки Curl для создания запросов Get/Post

Если вы работали с Linux, то использовали Curl для загрузки ресурсов из интернета. Эта библиотека также может использоваться для PHP post запросов.

Мы будем использовать

  • Ubuntu (14.04) в качестве операционной системы;
  • HTTP-сервер Apache (2.4.7);
  • PHP (5.5.9).

Подготовка среды

Установка

Ниже приведены команды для установки Apache, PHP и PHP-библиотеки Curl:

sudo apt-get update
sudo apt-get install apache2 php5 libapache2-mod-php5 php5-curl
sudo service apache2 restart

Конфигурация PHP

В файле /etc/php/apache2/php.ini необходимо включить расширение Curl:

extension=php_curl.so

Не забудьте перезапустить Apache после внесения изменений, чтобы осуществлять PHP отправку post запроса Curl.

Запрос GET

Давайте посмотрим, как использовать Curl для создания запросов GET:

curl_get.php

<?php
/**
 * Проверяем, установлен ли заданный параметр. Если один из указанных параметров 
 * не задан, вызывается die().
 *
 * @param $parameters Параметры, которые проверяются.
 */
function checkGETParametersOrDie($parameters) {
    foreach ($parameters as $parameter) {
        isset($_GET[$parameter]) || die("Please, provide '$parameter' parameter.");
    }
}
/**
 * Получаем параметры GET.
 *
 * @return GET строка параметра.
 */
function stringifyParameters() {
    $parameters = '?';
    foreach ($_GET as $key => $value) {
        $key = urlencode($key);
        $value = urlencode($value);
        $parameters .= "$key=$value&";
    }
    rtrim($parameters, '&');
    return $parameters;
}
/**
 * Создаем Curl-запрос для заданного URL-адреса.
 *
 * @param $url URL-адрес, к которому создается запрос.
 * @return Curl-запрос к url-адресу; false, если возникает ошибка.
 */
function createCurlRequest($url) {
    $curl = curl_init();
    if (!$curl) {
        return false;
    }
    $configured = curl_setopt_array($curl, [
        CURLOPT_URL => $url . stringifyParameters(),
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_RETURNTRANSFER => true
    ]);
    if (!$configured) {
        return false;
    }
    return $curl;
}
// Здесь начинается поток.
checkGETParametersOrDie(['url']);
$url = $_GET['url'];
$curl = createCurlRequest($url);
if (!$curl) {
    die('An error occured: ' . curl_error($curl));
}
$result = curl_exec($curl);
if (!$result) {
    die('An error occured: ' . curl_error($curl));
}
echo '<div>The result of the cURL request:</div>';
echo '<hr>';
echo $result;
curl_close($curl); // Don't forget to close!

Вот, что мы делаем для PHP Curl post запроса:

  1. Мы создали сессию Curl с помощью функции curl_init(). В случае возникновения ошибки возвращается false, поэтому, прежде чем продолжить, мы должны проверить ее;
  2. После того, как мы успешно создали сессию Curl, нужно настроить ее с помощью функции curl_setopt_array(). В данном случае мы настроили сессию со следующими параметрами:
  • Сам URL-адрес. Для запросов GET нужно указать URL-адрес со строкой параметров, в формате key=value. Обратите внимание, как эта строка параметров составлена в функции stringifyParameters(): значения должны быть закодированы с помощью функции urlencode();
  • Для параметра CURLOPT_FOLLOWLOCATION задается значение true. Это нужно для перехода по HTTP-редиректам 3xx. Если установлено значение false, и для указанного URL-адреса задано перенаправление, мы не сможем достичь конечного (целевого) URL-адреса;
  • Для параметра CURLOPT_RETURNTRANSFER задается значение true. Это позволяет сохранять HTTP - ответ в переменной;
  1. Необходимо проверить, не возвращают ли Curl ошибки, проверяя возвращаемые значения функций. Когда получаем значение false, можно получить информацию о последней ошибке для данной сессии Curl с помощью функции curl_error();
  2. Когда мы закончили обработку сессии Curl, нужно ее закрыть с помощью функции curl_close().

Можно проверить этот скрипт и PHP отправить post запрос, введя, например, в адресной строке браузера localhost/path/to/curl_get.php?url=webcodegeeks.com&s=php.

Запрос POST

Для запросов POST мы должны настроить параметры Curl в несколько ином виде:

curl_post.php

// ...
function createCurlRequest($url) {
    $curl = curl_init();
    if (!$curl) {
        return false;
    }
    $configured = curl_setopt_array($curl, [
        CURLOPT_URL => $url,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => stringifyParameters(),
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_RETURNTRANSFER => true
    ]);
    if (!$configured) {
        return false;
    }
    return $curl;
}
// ...

При установке URL-адреса мы задаем сам URL-адрес без параметров, которые задавались для запросов GET. Эти параметры указаны в опции CURLOPT_POSTFIELDS. Кроме этого мы определяем, что запрос будет выполнен с помощью метода POST (CURLOPT_POST).

Единственное различие между Curl-запросами POST и GET заключается в конфигурации сессии. Остальная часть скрипта отправки post запроса PHP одинакова для обоих случаев.

Инкапсуляция операций в классе Curl

При использовании Curl в проекте рекомендуется инкапсулировать весь код вместо использования функций, описанных выше. Иначе придется повторно запускать больше кода. Кроме этого повышается вероятность возникновения ошибок. Мы собираемся создать класс, который инкапсулирует эту логику.

curl_class.php

<?php
/**
 * Методы обработки Curl-запроса.
 */
class CURL {
    /**
     * Объект Curl-запроса.
     */
    private $request;
    /**
     * Конструктор класса CURL.
     *
     * @throws Exception, если при инициализации возникли ошибки.
     */
    public function __construct() {
        $this->request = curl_init();
        $this->throwExceptionIfError($this->request);
    }
    /**
     * Настройка Curl -запроса.
     *
     * @param $url Целевой url-адрес.
     * @param $urlParameters Массив параметров в формате 'key' => 'value'.
     * @param $method 'GET' или 'POST'; по умолчанию - 'GET'.
     * @param $moreOptions Другие параметры, добавляемые к Curl -запросу. 
     * По умолчанию задано 'CURLOPT_FOLLOWLOCATION'(переходить по редиректам 3XX) и 'CURLOPT_RETURNTRANSFER'
     * (возвращает ответ HTTP в качестве значения, вместо вывода напрямую).
     * @throws Exception, если возникли ошибки при настройке.
     */
    public function configure($url, $urlParameters = [], $method = 'GET',
        $moreOptions = [CURLOPT_FOLLOWLOCATION => true, CURLOPT_RETURNTRANSFER => true]) {
        curl_reset($this->request);
        switch ($method) {
            case 'GET':
                $options = [CURLOPT_URL => $url . $this->stringifyParameters($urlParameters)];
                break;
            case 'POST':
                $options = [
                    CURLOPT_URL => $url,
                    CURLOPT_POST => true,
                    CURLOPT_POSTFIELDS => $this->stringifyParameters($urlParameters) 
                ];
                break;
            default:
                throw new Exception('Method must be "GET" or "POST".');
                break;
        }
        $options = $options + $moreOptions; 
        foreach ($options as $option => $value) {
            $configured = curl_setopt($this->request, $option, $value);
            $this->throwExceptionIfError($configured);
        }
    }
    /**
     * Выполняем Curl-запрос в соответствии с параметрами конфигурации.
     *
     * @return возвращает значение функции curl_exec(). Если настроен CURLOPT_RETURNTRANSFER,
     *     возвращаемое значение будет ответом HTTP. В противном случае, значение true (или false,
     *     если возникла ошибка).
     * @throws Exception, если возникла ошибка при исполнении.
     */
    public function execute() {
        $result = curl_exec($this->request);
        $this->throwExceptionIfError($result);
        return $result;
    }
    /**
     * Закрываем сессию Curl.
     */
    public function close() {
        curl_close($this->request);
    }
    /**
     * Проверяем, вернули ли функции curl_* штатное значение или ошибку, добавляя исключение
     * с сообщением об ошибке Curl в случае возникновения ошибки.
     *
     * @param $success была ли функция curl выполнена успешно или нет.
     * @throws Exception, если функция curl не выполнена.
     */
    protected function throwExceptionIfError($success) {
        if (!$success) {
            throw new Exception(curl_error($this->request));
        }
    }
    /**
     * Составляем строку параметров GET.
     *
     * @param $parameters массив параметров.
     * @return Parameters в формате строки: '?key1=value1&key2=value2'
     */
    protected function stringifyParameters($parameters) {
        $parameterString = '?';
        foreach ($parameters as $key => $value) {
            $key = urlencode($key);
            $value = urlencode($value);
            $parameterString .= "$key=$value&";
        }
        rtrim($parameterString, '&');
        return $parameterString;
    }
}

В этом коде класса PHP Curl post запроса нет ничего, чего мы не рассматривали выше. За исключением способа, с помощью которого задаются параметры через функцию curl_setopt().

Чтобы использовать этот класс, нужно сделать что-то вроде этого:

<?php
require_once('curl_class.php');
try {
    $curl = new CURL();
    $curl->configure('webcodegeeks.com');
    $response = $curl->execute();
    $curl->close();
} catch (Exception $exception) {
    die('An exception has been thrown: ' . $exception->getMessage());
}

Приведенный выше код является более читаемым и простым в обслуживании. А также более гибким, так как он позволяет настроить любой параметр Curl.

Примечание: Запросы Curl могут быть использованы повторно, что позволяет увеличить производительность.

Например:

<?php
require_once('curl_class.php');
try {
    $curl = new CURL();
    $curl->configure('webcodegeeks.com');
    $response1 = $curl->execute();
    $curl->configure('webcodegeeks.com', ['s' => 'php'], 'GET');
    $response2 = $curl->execute();
    $curl->close();
} catch (Exception $exception) {
    die('An exception has been thrown: ' . $exception->getMessage());
}

Данный скрипт обработки post запроса PHP будет работать без проблем. Это лучше, чем закрывать и открывать новую сессию Curl для каждого запроса. В нашем случае прирост производительности будет несущественным, но при нескольких запросах разница будет ощутимой.

Для повторного использования сессий Curl необходимо очистить и удалить установленные параметры, прежде чем добавлять новые. Это было сделано в файле curl_class.php с помощью функции curl_reset().

Заключение

В этом примере я показал, как использовать в PHP-скриптах библиотеку Curl для создания запросов GET и POST, которые должны обрабатываться по-разному. Кроме этого мы разработали класс для более упорядоченной обработки Curl с помощью чистого и гибкого кода. Он позволяет повторно использовать уже открытые сессии для повышения производительности.

6. Скачайте исходный код

Это был пример использования Curl в PHP. Вы можете скачать его исходный код.