> 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/zh/exoclick-gong-gong-api/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 请求获取新的令牌。

### 使用用户名和密码获取并设置 Authorization 头的示例

```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();

        // 获取 Campaigns
        $url = 'https://api.example.com/v2/campaigns';

        // 创建一个新的 Request 对象
        $request = new Request($url, 'GET');

        // 设置 Authorization 头
        $request->setAuthorizationHeader($token->type, $token->token);

        // 发送请求
        $request->send();

        // 获取 Response 对象
        $response = $request->getResponse();

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

            // 获取 campaigns
            $campaigns = $response->getBodyDecoded();

            foreach($campaigns->result as $campaign) {
                // 显示 campaign 名称
                echo $campaign->name . PHP_EOL;
            }
        }
        else {
            // Campaigns 请求错误
            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 令牌获取并设置 Authorization 头的示例

```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');

    // 设置之前登录请求中获取的 Authorization 头
    $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** 值已定义，则请求将按主路由字段和额外字段进行分组。

### 按日期统计并按 campaign ID 1234 过滤的示例。

```php
<?php

    // 包含 Request 和 Response 类

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

    // 指定 campaign id
    $params = array(
       'campaignid'  => 1234
    );

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

    // 设置 Authorization 头，来自之前的登录请求
    $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 {
        // 未找到 Campaign 统计
        echo $response->getStatusCode() . PHP_EOL;
        echo $response->getReasonPhrase() . PHP_EOL;
        echo $response->getBody();
    }
?>
```

### 按日期统计并附加按 campaign 分组的示例。

```php
<?php

    // 包含 Request 和 Response 类

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

    // 指定 campaign id
    $params = array(
       'additional_group_by'  => 'campaign'
    );

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

    // 设置 Authorization 头，来自之前的登录请求
    $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 {
        // 未找到 Campaign 统计
        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);

    // 设置 Authorization 头，来自之前的登录请求
    $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 {
        // 未找到 Campaign 统计
        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';

    // 指定 campaign id
    $params = [
        "filter" => [
            "date_from" => "2019-01-10",
            "date_to" => "2019-01-31",
        ],
        "totals" => 1,
        "group_by" => ["date"]
    ];

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

    // 设置 Authorization 头，来自之前的登录请求
    $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 {
        // 未找到 Campaign 统计
        echo $response->getStatusCode() . PHP_EOL;
        echo $response->getReasonPhrase() . PHP_EOL;
        echo $response->getBody();
    }
?>
```

### 全局统计示例 3

获取按 campaign 和国家统计，并按展示次数排序，同时按指定日期过滤。

```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);

    // 设置 Authorization 头，来自之前的登录请求
    $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 . ' -  Campaign ID：' . $statistic->group_by->campaign_id->id .' - 成本：' .  $statistic->cost . PHP_EOL;
        }
    }
    else {
        // 未找到 Campaign 统计
        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);

    // 设置 Authorization 头，来自之前的登录请求
    $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 {
        // 未找到 Campaign 统计
        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/zh/exoclick-gong-gong-api/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.
