> For the complete documentation index, see [llms.txt](https://docs.exoclick.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.exoclick.com/api/ru/publichnyi-api-exoclick/api-manual-php-examples.md).

# Примеры на PHP

## Обзор

Все примеры кода в этом разделе используют следующие классы.

Класс Request использует **cURL** для выполнения запросов к API.

Класс Response содержит ответ API и информацию о возвращенном коде состояния.

<details>

<summary>Классы Request и Response</summary>

```php
class Request {

        /**
         * @var resource
         */
        protected $_request;

        /**
         * @var integer
         */
        protected $_method;

        /**
         * @var string
         */
        protected $_url;

        /**
         * @var array
         */
        protected $_headers = array(
            'Content-type: application/json'
        );

        /**
         * @var string|array
         */
        protected $_params;

        /**
         * @var object Response
         */
        protected $_reponse;

        /**
         * Конструктор
         *
         * @param   string      $url
         * @param   string      $method
         * @param   array       $params
         */
        public function __construct($url, $method, $params = array()) {

            $this->_url = $url;

            // Установить метод
            $this->_method = $method;

            // Установить параметры
            $this->_params = $params;
        }

        /**
         * Определить метод Request
         *
         * @param   string  $method
         */
        private function setMethod() {

            switch($this->_method) {
                case 'GET':
                    break;
                case 'POST':
                    curl_setopt($this->_request, CURLOPT_POST, 1);
                    break;
                case 'PUT':
                    curl_setopt($this->_request, CURLOPT_CUSTOMREQUEST, 'PUT');
                    break;
                case 'DELETE':
                    curl_setopt($this->_request, CURLOPT_CUSTOMREQUEST, 'DELETE');
                    break;
            }
        }

        /**
         * Добавить заголовок авторизации
         *
         * @param   string  $type
         * @param   string  $token
         */
        public function setAuthorizationHeader($type, $token) {

            $authorization = $type . ' ' . $token;

            $this->_headers[] = 'Authorization: ' . $authorization;
        }

        /**
         * Добавить тело запроса
         */
        private function addBody() {

            if($this->_method != 'GET' && empty($this->_params) == false) {

                if(is_array($this->_params)) {
                    // Закодировать массив в JSON
                    $this->_params = json_encode($this->_params);
                }

                curl_setopt($this->_request, CURLOPT_POSTFIELDS, $this->_params);

                // Добавить заголовок Content-Length
                $this->_headers[] = 'Content-length: ' . strlen($this->_params);
            }
        }

        /**
         * Добавить строку запроса к запросу
         */
        private function addQueryString() {

            if($this->_method == 'GET' && is_array($this->_params) && count($this->_params) > 0) {

                $query_string = '?';

                foreach($this->_params as $param => $value) {

                    $query_string = $query_string . $param . '=' . $value . '&';
                }

                trim($query_string, '&');

                $this->_url = $this->_url . $query_string;
            }
            else {

                if(is_array($this->_params) && count($this->_params) > 0 && strpos($this->_url, '{') !== false) {
                    // Сопоставить параметры с URL
                    foreach($this->_params as $param => $value) {
                        $this->_url = preg_replace('/{' . $param . '}/', $value, $this->_url);
                    }
                }
            }
        }

        /**
         * Отправить запрос
         */
        public function send() {

            // Инициализировать запрос cUrl
            $this->_request = curl_init();

            // Вернуть ответ в виде строки
            curl_setopt($this->_request, CURLOPT_RETURNTRANSFER, 1);

            // Добавить строку запроса
            $this->addQueryString();

            // Установить URL
            curl_setopt($this->_request, CURLOPT_URL, $this->_url);

            // Установить метод запроса
            $this->setMethod();

            // Добавить тело
            $this->addBody();

            if(empty($this->_headers) == false) {
                // Установить заголовки
                curl_setopt($this->_request, CURLOPT_HTTPHEADER, $this->_headers);
            }

            // Отключить проверки SSL
            curl_setopt($this->_request, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($this->_request, CURLOPT_SSL_VERIFYHOST, false);

            // Отправить запрос и сохранить тело
            $this->_response = new Response(curl_exec($this->_request));

            // Установить код состояния
            $this->_response->setStatusCode(curl_getinfo($this->_request, CURLINFO_HTTP_CODE));

            // Закрыть соединение
            curl_close($this->_request);
        }

        /**
         * Получить ответ
         *
         * @return object
         */
        public function getResponse() {

            return $this->_response;
        }
    }

    class Response {

        /**
         * @var array
         */
        protected $_reason_phrases = array(
            // Информационные 1xx
            100 => "Продолжать",
            101 => "Переключение протоколов",

            // Успешные 2xx
            200 => "ОК",
            201 => "Создано",
            202 => "Принято",
            203 => "Информация не является авторитетной",
            204 => "Нет содержимого",
            205 => "Сбросить содержимое",
            206 => "Частичное содержимое",

            // Перенаправление 3xx
            300 => "Множественный выбор",
            301 => "Перемещено навсегда",
            302 => "Найдено",
            303 => "См. другое",
            304 => "Не изменено",
            305 => "Использовать прокси",
            306 => "(Не используется)",
            307 => "Временное перенаправление",

            // Ошибка клиента 4xx
            400 => "Неверный запрос",
            401 => "Не авторизован",
            402 => "Требуется оплата",
            403 => "Запрещено",
            404 => "Не найдено",
            405 => "Метод не разрешен",
            406 => "Неприемлемо",
            407 => "Требуется аутентификация прокси",
            408 => "Время ожидания запроса истекло",
            409 => "Конфликт",
            410 => "Удалено",
            411 => "Требуется длина",
            412 => "Предварительное условие не выполнено",
            413 => "Слишком большой размер запроса",
            414 => "Слишком длинный URI запроса",
            415 => "Неподдерживаемый тип медиа",
            416 => "Запрошенный диапазон не может быть удовлетворен",
            417 => "Ожидание не выполнено",

            // Ошибка сервера 5xx
            500 => "Внутренняя ошибка сервера",
            501 => "Не реализовано",
            502 => "Плохой шлюз",
            503 => "Сервис недоступен",
            504 => "Время ожидания шлюза истекло",
            505 => "Версия HTTP не поддерживается"
        );

        /**
         * @var integer
         */
        protected $_status_code;

        /**
         * @var string
         */
        protected $_body;

        /**
         * Конструктор
         *
         * @param   string      $body
         */
        public function __construct($body) {

            $this->_body = $body;
        }

        /**
         * Конструктор
         *
         * @param   string      $status_code
         */
        public function setStatusCode($status_code) {

            $this->_status_code = $status_code;
        }

        /**
         * Получить код состояния
         *
         * @return  integer
         */
        public function getStatusCode() {

            return $this->_status_code;
        }

        /**
         * Получить тело
         *
         * @return  string
         */
        public function getBody() {

            return $this->_body;
        }

        /**
         * Получить тело, декодированное из JSON
         *
         * @return  object|null
         */
        public function getBodyDecoded() {

            return json_decode($this->_body);
        }

        /**
         * Получить фразу причины
         *
         * @return string|boolean
         */
        public function getReasonPhrase() {

            if(array_key_exists($this->_status_code, $this->_reason_phrases)) {

                return $this->_reason_phrases[$this->_status_code];
            }
            else {

                return false;
            }
        }
    }
```

</details>

## Вход

Есть два варианта запросить **вход** маршрут:

* с именем пользователя и паролем
* с API-токеном (токеном доступа)

Пример входа с параметрами имени пользователя и пароля.

```php
<?php

    // Подключить классы Request и Response

    $url = 'https://api.example.com/v2/login';

    $params = array(
        'username'  => 'sample_username',
        'password'  => 'sample_password'
    );

    // Создать новый объект Request
    $request = new Request($url, 'POST', $params);

    // Отправить запрос
    $request->send();

    // Получить объект Response
    $response = $request->getResponse();

    if($response->getStatusCode() == 200) {

        // Получить данные сессионного токена
        $token = $response->getBodyDecoded();

        print_r($token);
    }
    else {

        echo $response->getStatusCode() . PHP_EOL;
        echo $response->getReasonPhrase() . PHP_EOL;
        echo $response->getBody() . PHP_EOL;
    }
?>
```

### Пример входа с API-токеном (токеном доступа)

```php
<?php

    // Подключить классы Request и Response

    $url = 'https://api.example.com/v2/login';

    $params = array(
            'api_token'  => 'sample_token_2bb447abb71b69368901a....'
        );

    // Создать новый объект Request
    $request = new Request($url, 'POST', $params);

    // Отправить запрос
    $request->send();

    // Получить объект Response
    $response = $request->getResponse();

    if($response->getStatusCode() == 200) {

        // Получить данные сессионного токена
        $token = $response->getBodyDecoded();

        print_r($token);
    }
    else {

        echo $response->getStatusCode() . PHP_EOL;
        echo $response->getReasonPhrase() . PHP_EOL;
        echo $response->getBody() . PHP_EOL;
    }
?>
```

## Аутентификация

Каждый запрос к контенту, связанному с пользователем, требует **Авторизация** установки заголовка, значение которого содержит тип токена и сессионный токен, полученный из запроса входа в API.

Действительный **/login** запрос к API вернет следующую JSON-нагрузку.

```json
{
  "token": "",
  "type": "",
  "expires_in": 0
}
```

Этот **Сессионный токен** должен быть включен во все последующие запросы к API, связанные с пользовательским контентом.

Этот **type** должен быть добавлен перед токеном, отделяясь одним пробелом.

```
Bearer 4e63518d383d8fcaefb516fe708b893727463031
```

Этот **expires\_in** — это время в секундах, в течение которого токен будет действителен. Когда это время истечет, потребуется получить новый токен через запрос /login.

### Пример получения и установки заголовка авторизации с именем пользователя и паролем

```php
<?php

    // Подключить классы Request и Response

    // Вход
    $url = 'https://api.example.com/v2/login';

    $params = array(
        'username'  => 'sample_username',
        'password'  => 'sample_password'
    );

    // Создать новый объект Request
    $request = new Request($url, 'POST', $params);

    // Отправить запрос
    $request->send();

    // Получить объект Response
    $response = $request->getResponse();

    if($response->getStatusCode() == 200) {

        // Получить данные сессионного токена
        $token = $response->getBodyDecoded();

        // Получить кампании
        $url = 'https://api.example.com/v2/campaigns';

        // Создать новый объект Request
        $request = new Request($url, 'GET');

        // Установить заголовок авторизации
        $request->setAuthorizationHeader($token->type, $token->token);

        // Отправить запрос
        $request->send();

        // Получить объект Response
        $response = $request->getResponse();

        if($response->getStatusCode() == 200) {

            // Получить кампании
            $campaigns = $response->getBodyDecoded();

            foreach($campaigns->result as $campaign) {
                // Отобразить названия кампаний
                echo $campaign->name . PHP_EOL;
            }
        }
        else {
            // Ошибка запроса кампаний
            echo $response->getStatusCode() . PHP_EOL;
            echo $response->getReasonPhrase() . PHP_EOL;
            echo $response->getBody();
        }
    }
    else {
        // Неверный вход
        echo $response->getStatusCode() . PHP_EOL;
        echo $response->getReasonPhrase() . PHP_EOL;
        echo $response->getBody();
    }
?>
```

### Пример получения и установки заголовка авторизации с API-токеном

```php
<?php

    // Подключить классы Request и Response

    // Вход
    $url = 'https://api.example.com/v2/login';

    $params = array(
        'api_token'  => 'sample_token_2bb447abb71b69368901a....'
    );

    ...

?>
```

## Коллекции

Ниже приведен пример запроса для получения **Браузеры** коллекции.

```php
<?php

    // Подключить классы Request и Response

    $url = 'https://api.example.com/v2/collections/browsers';

    // Создать новый объект Request
    $request = new Request($url, 'GET');

    // Установить заголовок авторизации, полученный из предыдущего запроса входа
    $request->setAuthorizationHeader($token->type, $token->token);

    // Отправить запрос
    $request->send();

    // Получить объект Response
    $response = $request->getResponse();

    if($response->getStatusCode() == 200) {

        $browsers = $response->getBodyDecoded();

        foreach($browsers as $browser) {

            echo $browser->id . ': ' . $browser->name . PHP_EOL;
        }
    }
    else {
        // Коллекция не найдена
        echo $response->getStatusCode() . PHP_EOL;
        echo $response->getReasonPhrase() . PHP_EOL;
        echo $response->getBody();
    }
?>
```

## Статистика

Ниже приведен пример запроса рекламодателя к **statistics/a/date**.

В случае **additional\_group\_by** если значение задано, запрос будет сгруппирован по основному полю маршрута и дополнительному(-ым).

### Пример статистики по датам, отфильтрованной по ID кампании 1234.

```php
<?php

    // Подключить классы Request и Response

    $url = 'https://api.example.com/v2/statistics/a/date';

    // Указать ID кампании
    $params = array(
       'campaignid'  => 1234
    );

    $request = new Request($url, 'GET', $params);

    // Установить заголовок авторизации, полученный из предыдущего запроса входа
    $request->setAuthorizationHeader($token->type, $token->token);

    // Отправить запрос
    $request->send();

    // Получить объект ответа
    $response = $request->getResponse();

    if($response->getStatusCode() == 200) {

        $statistics = $response->getBodyDecoded();

        foreach($statistics->result as $statistic) {

            echo $statistic->ddate . ': ' . $statistic->value . PHP_EOL;
        }
    }
    else {
        // Статистика кампаний не найдена
        echo $response->getStatusCode() . PHP_EOL;
        echo $response->getReasonPhrase() . PHP_EOL;
        echo $response->getBody();
    }
?>
```

### Пример статистики по датам с дополнительной группировкой по кампании.

```php
<?php

    // Подключить классы Request и Response

    $url = 'https://api.example.com/v2/statistics/a/date';

    // Указать ID кампании
    $params = array(
       'additional_group_by'  => 'campaign'
    );

    $request = new Request($url, 'GET', $params);

    // Установить заголовок авторизации, полученный из предыдущего запроса входа
    $request->setAuthorizationHeader($token->type, $token->token);

    // Отправить запрос
    $request->send();

    // Получить объект ответа
    $response = $request->getResponse();

    if($response->getStatusCode() == 200) {

        $statistics = $response->getBodyDecoded();

        foreach($statistics->result as $statistic) {
            echo $statistic->ddate . ' - ' . $statistic->idcampaign . ': ' . $statistic->value . PHP_EOL;
        }
    }
    else {
        // Статистика кампаний не найдена
        echo $response->getStatusCode() . PHP_EOL;
        echo $response->getReasonPhrase() . PHP_EOL;
        echo $response->getBody();
    }
?>
```

post /statistics/a/global

Получить глобальную статистику рекламодателя

### Пример 1 глобальной статистики

Пример запроса глобальной статистики.

Только `group_by` параметр обязателен. Значения по умолчанию для остальных параметров можно найти [здесь](https://api.exoclick.com/v2/docs/#!/47statistics/post_statistics_a_global).

Обратите внимание, что маршруты глобальной статистики (`statistics/a/global`, `statistics/p/global`) имеют другой формат параметров.

```php
<?php

    // Подключить классы Request и Response

    $url = 'https://api.example.com/v2/statistics/a/global';

    // Указать group_by
    $params = [
        "group_by" => ["date"]
    ];

    $request = new Request($url, 'POST', $params);

    // Установить заголовок авторизации, полученный из предыдущего запроса входа
    $request->setAuthorizationHeader($token->type, $token->token);

    // Отправить запрос
    $request->send();

    // Получить объект ответа
    $response = $request->getResponse();

    if($response->getStatusCode() == 200) {

        $statistics = $response->getBodyDecoded();

        foreach($statistics->result as $statistic) {
            echo 'Дата: ' . $statistic->group_by->date->date . ' -  Показов: ' . $statistic->impressions .' - Стоимость: ' .  $statistic->cost . PHP_EOL;
        }
    }
    else {
        // Статистика кампаний не найдена
        echo $response->getStatusCode() . PHP_EOL;
        echo $response->getReasonPhrase() . PHP_EOL;
        echo $response->getBody();
    }
?>
```

### Пример 2 глобальной статистики

Получить статистику по датам, включая суммарные итоги.

```php
<?php

    // Подключить классы Request и Response

    $url = 'https://api.example.com/v2/statistics/a/global';

    // Указать ID кампании
    $params = [
        "filter" => [
            "date_from" => "2019-01-10",
            "date_to" => "2019-01-31",
        ],
        "totals" => 1,
        "group_by" => ["date"]
    ];

    $request = new Request($url, 'POST', $params);

    // Установить заголовок авторизации, полученный из предыдущего запроса входа
    $request->setAuthorizationHeader($token->type, $token->token);

    // Отправить запрос
    $request->send();

    // Получить объект ответа
    $response = $request->getResponse();

    if($response->getStatusCode() == 200) {

        $statistics = $response->getBodyDecoded();

        foreach($statistics->result as $statistic) {
            echo 'Дата: ' . $statistic->group_by->date->date . ' -  Показов: ' . $statistic->impressions .' - Стоимость: ' .  $statistic->cost . PHP_EOL;
        }

        echo 'Общая стоимость:' . $statistics->result_total->cost . PHP_EOL;
    }
    else {
        // Статистика кампаний не найдена
        echo $response->getStatusCode() . PHP_EOL;
        echo $response->getReasonPhrase() . PHP_EOL;
        echo $response->getBody();
    }
?>
```

### Пример 3 глобальной статистики

Получить статистику по кампаниям и странам, отфильтрованную по конкретной дате и отсортированную по показам.

```php
<?php

    // Подключить классы Request и Response

    $url = 'https://api.example.com/v2/statistics/a/global';

    $params = [
        "filter" => [
            "date_from" => "2019-01-30",
            "date_to" => "2019-01-30",
        ],
        "group_by" => ["country_iso", "campaign_id"],
        "order_by" => [
            ["field" => "impressions", "order" => "desc"]
        ]
    ];


    $request = new Request($url, 'POST', $params);

    // Установить заголовок авторизации, полученный из предыдущего запроса входа
    $request->setAuthorizationHeader($token->type, $token->token);

    // Отправить запрос
    $request->send();

    // Получить объект ответа
    $response = $request->getResponse();

    if($response->getStatusCode() == 200) {

        $statistics = $response->getBodyDecoded();

        foreach($statistics->result as $statistic) {
            echo 'Страна: ' . $statistic->group_by->country_iso->country_iso . ' -  ID кампании: ' . $statistic->group_by->campaign_id->id .' - Стоимость: ' .  $statistic->cost . PHP_EOL;
        }
    }
    else {
        // Статистика кампаний не найдена
        echo $response->getStatusCode() . PHP_EOL;
        echo $response->getReasonPhrase() . PHP_EOL;
        echo $response->getBody();
    }
?>
```

### Пример 4 глобальной статистики

Получить статистику издателя по зонам и странам, отфильтрованную по конкретной операционной системе.

```php
<?php

    // Подключить классы Request и Response

    $url = 'https://api.example.com/v2/statistics/p/global';

    $params = [
        "filter" => [
            "date_from" => "2019-01-30",
            "date_to" => "2019-01-30",
            "operating_system_id" => [11, 12]
        ],
        "group_by" => ["zone_id", "country_iso"]
    ];


    $request = new Request($url, 'POST', $params);

    // Установить заголовок авторизации, полученный из предыдущего запроса входа
    $request->setAuthorizationHeader($token->type, $token->token);

    // Отправить запрос
    $request->send();

    // Получить объект ответа
    $response = $request->getResponse();

    if($response->getStatusCode() == 200) {

        $statistics = $response->getBodyDecoded();

        foreach($statistics->result as $statistic) {
            echo ' ID зоны:' . $statistic->group_by->zone_id->id . ' - Страна: ' . $statistic->group_by->country_iso->country_iso .' - Доход: ' .  $statistic->revenue . PHP_EOL;
        }
    }
    else {
        // Статистика кампаний не найдена
        echo $response->getStatusCode() . PHP_EOL;
        echo $response->getReasonPhrase() . PHP_EOL;
        echo $response->getBody();
    }
?>
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.exoclick.com/api/ru/publichnyi-api-exoclick/api-manual-php-examples.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
