質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

1回答

2193閲覧

GuzzleHttpで取得数に上限があるAPIデータを、繰り返しリクエストして全件取得したいがreturnすると空になる

jiyo-ta

総合スコア13

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2021/07/19 12:13

表題の件です。
取得数に300件という上限のあるAPIデータを繰り返しリクエストすることで300件ずつ全件取得したいと考えております。
APIは、リクエストが返ってきた時にhasMoreがtrueならばさらにデータが存在することを意味します。その時、nextPageTokenも発行され、urlにtokenをつけて再リクエストすることで次のデータが取得できる仕様になっています。

Laravelのartisanコマンドを使い、以下のGetDataクラスを実行し試みました。全ての取得が終わり、hasMoreがtrueでなくなったときにreturnして値を返すようにしています。しかし、返ってきた値はどうしても空になってしまいます。return直前のprint_r($allrecords)をチェックすると問題なく全件取得できているのですが、returnして返ってきた値は空です。
どういう現象なのか理解できす、解決方法も分かりません。拙い説明で申し訳ありません。
別のクラスへ値を渡し、データを加工→別システムにあるデータを更新、ということをしたいと考えております。どうかご教授お願い致します。同期、非同期が関係するのかと考えましたが、全然詳しくなく手を出せずにいます。

public function GetData () { $Data = $this->searchData('',''); print_r($Data);  //これは空になってしまいます } public function searchData ($opt_records, $nextPageToken) { if (isset($opt_records)) { $allrecords = $opt_records; }else{ $allrecords = []; } $limit = 300; $url = "https://api.abc.com/v2.0/xxxx/search?range=all&limit=".$limit; $method = "GET"; $token = 'xxxxxxxxxxxxxxxxxxx'; if ($nextPageToken) { $url = $url.$nextPageToken; } //接続 $client = new Client(); $response = $client->request($method, $url,[ 'headers' => [ 'X-xxxxxx-Api-Key' => $token ], ]); //エラーの場合 if ($response->getStatusCode() !== 200) { $this->log("searchData error:" . print_r($response, true)); return $allrecords; } if($response->getStatusCode() == 200){ $posts = $response->getBody(); $posts = json_decode($posts, true); if (!$allrecords) { $allrecords = $posts['data']; }else{ $allrecords = array_merge($allrecords,$posts['data']); } if ($posts['hasMore'] == 1 || $posts['nextPageToken']) { $nextPageToken = '&nextPageToken='.$posts['nextPageToken']; $this->searchSansanData($allrecords,$nextPageToken); }else{ print_r($allrecords); //ここで取得できていることは確認できました return $allrecords; //returnすると空になってしまいます } } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

再現することが考えにくい不具合なので,勘違いしている可能性をまず疑ってください。

  • 関数内部の print_r() で表示と,関数外部の print_r() で表示は,どちらも1回のリクエストで一気に表示されたものでしょうか?連続した別々のリクエストで表示されたものではありませんか?

勘違いしている可能性としては↑が一番濃厚だと思います。
適当にリファクタリングしてみます,参考までに↓

php

1protected $client; 2 3public function __construct() 4{ 5 // 共通部分はこういうところでセットしておくとやりやすい 6 // (理想を言うと ServiceProvider からコンストラクタ引数として注入したほうがユニットテストは書きやすかったりするがここでは簡略化) 7 $this->client = new Client([ 8 'base_uri' => 'https://api.sansan.com/v2.0/', 9 'headers' => [ 10 'X-Sansan-Api-Key' => 'xxxxxxxxxxxxxxxxxxx', 11 ], 12 ]); 13} 14 15public function searchAllData() 16{ 17 // 再帰呼び出しよりはループのほうがいいかも 18 $posts = []; 19 $nextPageToken = null; 20 21 do { 22 $result = $this->sendRequest($nextPageToken); 23 $posts = array_merge($posts, $result['data']); 24 } while ($nextPageToken = $result['nextPageToken']); 25 26 return $posts; 27} 28 29protected function sendRequest($nextPageToken = null) 30{ 31 // クエリストリングは query オプションで連想配列形式で指定できる 32 $options = [ 33 'query' => [ 34 'range' => 'all', 35 'limit' => 300, 36 ], 37 ]; 38 39 if ($nextPageToken) { 40 $options['query']['nextPageToken'] = $nextPageToken; 41 } 42 43 // Guzzle は 200 系以外は Exception をスローするのでステータスコードのチェックは不要 44 // (必要に応じて try-catch 構文で包む必要あり) 45 $response = $this->client->request('GET', 'bizCards/search', $options); 46 47 return json_decode($response->getBody(), true); 48}

投稿2021/07/20 05:44

編集2021/07/20 06:04
mpyw

総合スコア5223

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mpyw

2021/07/20 05:57

ちなみに既存コードの一番「動かない」問題点は $this->searchSansanData($allrecords,$nextPageToken); この部分です。メソッド名を間違えていますし,return を忘れています。
jiyo-ta

2021/07/21 12:14

返信が遅くなりまして申し訳ありません。 大変ありがとうございます。 >関数内部の print_r() で表示と,関数外部の print_r() で表示は,どちらも1回のリクエストで一気に表示さ >れたものでしょうか?連続した別々のリクエストで表示されたものではありませんか? 再帰処理をしているつもりだったのですが、連続した別々のリクエストになっているのだとご指摘いただいて理解しました。 __construct()の使い方や再帰よりもループの方が良い、など貴重なレビューを頂き大変有り難く存じます。 お恥ずかしながらいつもコピペで切り抜けてきたため、本当に理解が乏しいと改めて実感しました。 結局、頂戴しましたソースを使ってみたところ思い通りの値を取得することができました。 >Guzzle は 200 系以外は Exception をスローするのでステータスコードのチェックは不要 >必要に応じて try-catch 構文で包む必要あり) なるほどです。try-catch 構文を試してみようと思います。 >ちなみに既存コードの一番「動かない」問題点は >$this->searchSansanData($allrecords,$nextPageToken); >この部分です。メソッド名を間違えていますし,return を忘れています。 ご指摘ありがとうございます。searchDataの間違いでした。この質問を投稿した際に間違ってしまいました。 大変ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問