[PHP] GoogleAdsAPIでSearchした結果の総件数を取得する方法

例えば広告グループをSearchする場合、GoogleAdsAPIのリファレンスやExampleを見ても、API通信のResponseから広告グループ名やResourceNameを取得する方法はすぐわかりますが、広告グループがいくつあるかを取得する方法は探しづらかったので、他の方がこんなことに時間かけなくていいようにという意味も込めてメモ。

#どこに総件数が入っているのか？
結論から言えば、SearchGoogleAdsResponse クラスに、「total_results_count」というプロパティがあり、これが取得結果の総件数にあたります。

URL：https://developers.google.com/google-ads/api/reference/rpc/v8/SearchGoogleAdsResponse

じゃあ公式のExampleを少しいじって、このプロパティを取得しにいけばええやろがいと思われるかもしれませんが、GoogleAdsAPIのリファレンスばかり見ているとその方法にたどり着けないです。

#公式のExampleを見てみよう
私がやったときはアカウント内のキーワードの総件数を取得しようとしていたので、Get Keywordsを見ていきます。

URL：https://developers.google.com/google-ads/api/docs/samples/get-keywords

Response取得部分だけここに書きます。

```GetKeywords.php

        // Issues a search request by specifying page size.
        $response =
            $googleAdsServiceClient->search($customerId, $query, ['pageSize' => self::PAGE_SIZE]);

        // Iterates over all rows in all pages and prints the requested field values for
        // the keyword in each row.
        foreach ($response->iterateAllElements() as $googleAdsRow) {
            /** @var GoogleAdsRow $googleAdsRow */
            printf(
                "Keyword with text '%s', match type '%s', criterion type '%s', and ID %d "
                . "was found in ad group with ID %d.%s",
                $googleAdsRow->getAdGroupCriterion()->getKeyword()->getText(),
                KeywordMatchType::name(
                    $googleAdsRow->getAdGroupCriterion()->getKeyword()->getMatchType()
                ),
                CriterionType::name($googleAdsRow->getAdGroupCriterion()->getType()),
                $googleAdsRow->getAdGroupCriterion()->getCriterionId(),
                $googleAdsRow->getAdGroup()->getId(),
                PHP_EOL
            );
        }
```


これを見ればわかる通り、Response の iterateAllElements()というメソッドを使って GoogleAdsRow クラスのオブジェクトがいくつも入った配列を取得し、それに対して forEach を使って取得結果を一件ずつ取り出しています。
私は最初、「じゃあこの$responseがSearchGoogleAdsResponseクラスのオブジェクトだろう」と考え、クライアントライブラリのSearchGoogleAdsResponse.phpのファイルを見に行き、**getTotalResultsCount()**というメソッドを見つけて、これだと思って意気揚々とこいつを実行してみました。
コードはこんな感じだったと思います。

```getNumOfKeywords.php
    $search = $googleAdsServiceClient->search($customerId, $query, ['pageSize' => 1000]);

    $count = $search -> getTotalResultsCount();

    var_dump($count);
```

しかし、「getTotalResultsCount()なんていうメソッド、**PagedListResponse**クラスには定義されてないよ」というエラー文が出ました。
てっきり$responseの変数にはSearchGoogleAdsResponseクラスのオブジェクトが入っていると思い込んでいた私はビックリしました。

#Google汎用ライブラリのクラスだった
そして思いました。**「このPagedListResponseというクラスはなんぞや」**と。
とりあえずGoogleAdsAPIのリファレンスで検索してみます。(ﾎﾟﾁｰ

**「No results found.」**

えぇ...。

そしてGoogle大先生に質問しに行きます。
すると...



https://googleapis.github.io/gax-php/0.36.0/Google/ApiCore/PagedListResponse.html


ありました。

どうやらGoogleの汎用ライブラリのクラスだったみたいです。
このクラスのメソッド一覧を見てみると、getPage()というメソッドがありました。Pageクラスにありそうだな、と目星をつけ、Pageクラスのリファレンスページに行く。

https://googleapis.github.io/gax-php/0.36.0/Google/ApiCore/Page.html

メソッド一覧を見ると、「**getResponseObject()**　Gets the API response object.」という表記が。
これだ！！！！！！

というわけで、こんなコードで実行してみる。

```getNumOfKeywords.php

    $pagedResponse = $googleAdsServiceClient->search($customerId, $query, ['pageSize' => 1000]);
    
    $count = $pagedResponse->getPage()->getResponseObject()->getTotalResultsCount();

    error_log($count);
```

forEachじゃないのはなんで？と思われる方もいるかもしれませんが、どのPageオブジェクトにも同じようにtotal_results_countプロパティは含まれているので読み込むPageオブジェクトは1個で良く、**iteratePages()**メソッドを使ってPageクラスのオブジェクトの配列を取得してforEachで回す必要はないのです。

そして出力されてきたログを見ると...

**「0」**

なんで！？って叫びそうになりました。

#オプションの値の設定を忘れずに
そこから30分ほどネットの海を漂流し、何も見つからなかったのでクライアントライブラリのSearchGoogleAdsResponse関連のファイルを眺めていたのですが、GoogleAdsServiceGapicClient.phpファイルの、search()メソッドが定義してある部分のコメントに気が付きました。そこに、

```GoogleAdsServiceGapicClient.php
     //@param array  $optionalArgs {
     //     Optional.
     //     @type bool $returnTotalResultsCount
     //         If true, the total number of results that match the query ignoring the
     //         LIMIT clause will be included in the response.
```

という記述があったのです。なるほどパラメーターが必要なのか。
というわけで先ほどのコードを以下のように修正します。

```getNumOfKeywords.php

    $pagedResponse = $googleAdsServiceClient->search($customerId, $query, ['pageSize' => 1000, 'returnTotalResultsCount' => true]);
    
    $count = $pagedResponse->getPage()->getResponseObject()->getTotalResultsCount();

    error_log($count);
```

これで正しい値が出力されました！長かったーーー。


#後書き
実は私は最初、ExampleにあるFor文を使って、results[]の配列の要素数をcount()で数えて、変数に足していけばええやん！と思って作っていたのですが、PHP君に「メモリが足りないよ！！」と泣き言を言われてしまいました。
他の人に相談すると、取得結果の総件数くらいAPIの方で数えて渡してくれるでしょ、と助言いただいたので、こうやって探すことができました。

ちなみにこの方法でも、pageSizeを10000（上限）とかにするとメモリが足りなくなるかもしれないので注意！

最後までお読みいただきありがとうございました。