Transients APIを使用したリモート(HTTP)リクエストのキャッシュ


8

get_transient()Wordpressでメソッドを使用しようとしています。ドキュメントを読みましたが、ドキュメントに記載されていることを実行しているようです。

私は自分のウェブサイトで天気を表示する必要があり、6時間ごとに更新されるサードパーティのWeather APIを使用しています。

天気のローカルキャッシュを作成して、APIが有効期限の後にのみ呼び出されるようにします。(その他の理由:APIレート制限)

これは私のコードです:

$country   = 'India';
$API_Key  = 'xxxxxxxxxxxxxx';
$url        = 'http://weatherAPI.com/feed/weather.ashx?q='.$latlong.'&format=json&num_of_days=4&key='.$API_Key;

$weather = get_transient($location);
if (false === $weather) {
        $ch = curl_init();
        curl_setopt ($ch, CURLOPT_URL, $url);
        curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 0);
        $weather = curl_exec($ch);
        curl_close($ch);
        set_transient($location, $weather, 60*60*6);
 }

天気を取得するための場所(say delhi)を送信しているときに、その場所がキャッシュにない場合、false次の文字列を返している間に返されると期待していました

'{ "data": { "error": [ {"msg": "Unable to find any matching weather location to the query submitted!" } ] }}'

var_dump($weather);値をチェックするために使用しました$weather

誰かが私が間違っているところを修正できますか?


1
これは、関連はありませんget_transient()が、APIリクエストの場合:エラーメッセージで示されます。使用wp_remote_postを推奨する以外に、送信されるリクエストが有効であることを確認する必要があります。
スティーブンハリス

@StephenHarris:.i内でのみ提供さ if (false === $weather)れているため、この質問は更新されていません
Umesh Awasthi

1
ポイントは、キャッシュはあなたが与えたものをすべて保存することです-そしてこの場合、あなたはWeather APIからエラーメッセージを与えています。キャッシュは、何も保存されていない場合にのみfalseを返します。そのため、weather APIからの応答を確認し、有効な場合は保存してください。
スティーブンハリス

@StephenHarris:aha私はあなたの要点を完全に逃しただけです。私はPHPから始めたばかりで、すべてを無視し、コードを注意深く見ていませんでした:)
Umesh Awasthi

回答:


11

Weather APIリモートデータの取得

msg、あなたがあなたの質問に見せていることは基本的に天候APIからの結果です。そして、それはあなたの場所のために利用可能なデータがないと言います。

最初に行いたいのは、コーデックスと「WP HTTP API」での調査です。

リモートデータを取得するための適切な方法

WP HTTP APIについて学んだ後、それを行う一般的な方法が(このように簡略化されている)であることがわかります。

$response = wp_remote_request( 'http://example.com?some=parameter', array(
    'ssl_verify' => true
) );

(例に示されているように)エラーが発生した場合は、WP_Errorクラスを使用してエラーをキャッチできます。

is_wp_error( $response ) AND printf(
    'There was an ERROR in your request.<br />Code: %s<br />Message: %s',
    $response->get_error_code(),
    $response->get_error_message()
);

次に、適切なデータを取得します。これが表示されます200OK、リモート側のすべてが働いた場合は、。重要:リモートデータは、内部データよりも標準に準拠していない可能性があります。したがって、エラーが発生する可能性がありますが、それでも肯定的な200/OKメッセージが返されます。

$response_code   = wp_remote_retrieve_response_code( $response );
$response_status = wp_remote_retrieve_response_message( $response );

結果を得る

最後に、結果を検査します。最初に、先頭/末尾の空白を削除します。次のサンプルでは、​​WP HTTP APIを使用してヘッダーを確認する方法を示しています。キャッチした場合はJSONそれjson_decode()で、を得た場合はXMLPHPのネイティブSimpleXMLクラスを使用します。

// Prepare the data:
$content = trim( wp_remote_retrieve_body( $response ) );
// Convert output to JSON
if ( strstr( wp_remote_retrieve_header( $response, 'content-type' ), 'json' ) )
{
    $content = json_decode( $content );
}
// … else, after a double check, we simply go with XML string
elseif ( strstr(
        wp_remote_retrieve_header( $response, 'content-type' ),
        'application/xhtml+xml'
    ) )
{
    // Lets make sure it is really an XML file
    // We also get cases where it's "<?XML" and "<?xml"
    if ( '<?xml' !== strtolower( substr( $content, 0, 5 ) ) )
        return false;

    // Also return stuff wrapped up in <![CDATA[Foo]]>
    $content = simplexml_load_string( $content, null, LIBXML_NOCDATA );
}
// If both didn't work out, then we maybe got a CSV, or something else...

CSVファイルの場合は、カスタムソリューションを見つけるか、インターウェブでPHPクラスを検索する必要があります。しかし正直なところ、CSVを使用している場合は、別のサービスを検索する方が簡単です。

一時的にデータをキャッシュする

一時APIはこれを行うにはかなりいいの方法を提供しています:

// Set Transient
$transient = set_transient(
    'Your cache key',
    $content,
    60*60*6
);

その後、を使用して一時的なエラーをキャッチできるはずget_transient()です。

一般的なエラー

よく発生するエラーは、SSL検証が機能しないことです。嬉しいことに、非常に簡単にオン/オフを切り替えることができます。

// ON:
add_filter( 'https_ssl_verify', '__return_true' );
// OFF:
add_filter( 'https_ssl_verify', '__return_false' );

適切なコアファイルを調べるとわかるように、面白い点が1つあります。コアには、ローカルリクエスト用のフィルターもあります。しかし、これにだまされないでください。このフィルターは、A)WPインストール内からリモートサービスを提供し、B)自分で使用している場合にのみ使用することを目的としています。#WTF?!これは、ローカルインストールと運用環境/サーバー間で異なるSSL検証設定を使用するためのスイッチではないことはわかっていますが、その背後にあるアイデアもあります。それは、サービスをテストすることです。ここでWP G +コミュニティも説明したように、自分自身を提供してください。

// Debug your own service without SSL verification.
add_filter( 'https_local_ssl_verify', '__return_false' );

リクエストとその結果のデバッグ

更新プロセスを深く掘り下げることなく、WP HTTP APIはWP_HTTPクラスを使用します。また、デバッグフックという優れた機能も提供します。

do_action( 'http_api_debug', $response, 'response', $class, $args, $url );

どこに$responseWP_Error、おそらくあなたにもっと教えてくれるオブジェクトがあります。

注:簡単なテストから、このフィルターは、(何らかの理由で)実際にリクエストを行っている場所の近くに配置した場合にのみ機能するようです。したがって、以下のフィルターのいずれかのコールバック内から呼び出す必要があるかもしれません。

カールなし?

簡単です。上記で示した「WP HTTP API」のすべてのファンキーさは、基本的にはWP_HTTPクラス内部の関数ベースのラッパーであり、基本クラスとして機能します(さまざまなシナリオで拡張されます)。拡張WP_HTTP_*クラスはFsockopenStreamsCurlProxyCookieEncoding。コールバックを'http_api_debug'-actionにフックすると、3番目の引数で、要求に使用されたクラスがわかります。クラスを直接呼び出す必要はありません。関数を使用するだけです。

ほとんどのリモート/ HTTP APIリクエストの場合WP_HTTP_curl、これはクラスであり、PHPのネイティブcurlライブラリのラッパーです。

WP_HTTP_curlクラスの中には、request()メソッドがあります。このメソッドは、SSL動作をインターセプトする2つのフィルターを提供します。1つはローカルリクエスト用で'https_local_ssl_verify'、もう1つはリモートリクエスト用'https_ssl_verify'です。WPは、あなたが何から何を得るかを定義locallocalhostます。returnget_option( 'siteurl' );


注:この回答は、私が提供したこの回答の延長として読むことができます。
カイザー

入力のおかげで、waether APIからの応答はデータがない場合にのみ呼び出されるため、APIのURLを確認し、有効なデータを返したので、確信が持てません。さらにデバッグしてみます
Umeshアワスティ

@UmeshAwasthi私が上で書いたものを試してください-ステップバイステップ。最初にwp_remote_request()URLで何が返ってくるのかを確認し、次に答えをさらに調べます。これはかなり完全なチュートリアルであり、WPでHTTPリクエストを行う正しい方法を示しています。もう少し明確にするために:WP_HTTP_curl上に示した関数を使用する場合、WordPressが既にこれを行っているので、クラスを呼び出す必要はありません。
カイザー

私はこれをテストする途中です。完了したら更新します:)
Umesh Awasthi

1
問題は別のものでしたが、同じ作業を行うためのより良い方法を提供するため、あなたの答えを承認済みとしてマークしました。プラットフォームがいくつかのAPIを提供している場合、それらを使用する方が良いと思います。ありがとう!!
Umesh Awasthi

3

問題は「一時的」機能にありません。サードパーティのAPIから返されたエラーメッセージのようです。使用する前に確認する必要がありますset_transientset_transient与えられたものを挿入get_transientし、DBにあるものを取得します。言い換えれば、問題はあなたが思っているところにあるのではないと私はかなり確信しています。

$weather = get_transient($location);
if (false === $weather) {
        $ch = curl_init();
        curl_setopt ($ch, CURLOPT_URL, $url);
        curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 0);
        $weather = curl_exec($ch);
        curl_close($ch);
        // now check $weather to see if you got a valid result
        $check = json_decode($weather);
        if (isset($check->data->error)) {
          // there is a problem; do not insert; try something else
        } else {
          set_transient($location, $weather, 60*60*6);
        }
 }

Weather APIからの出力の一部について推測しているので、必要な結果を得るために微調整する必要がある場合があります。

注:APIはJSONを返します。あなたの例は次のようにデコードします:

stdClass::__set_state(array(
   'data' => 
  stdClass::__set_state(array(
     'error' => 
    array (
      0 => 
      stdClass::__set_state(array(
         'msg' => 'Unable to find any matching weather location to the query submitted!',
      )),
    ),
  )),
))

入力のおかげで、しかし、APIへの呼び出しのみが唯一の内側に与えられているとして、それは私には非常に奇妙なようif (false === $weather)statement.Iことに気づいていなかったWP_HTTP_curlクラスは、その使用しようとします
Umesh Awasthi

@UmeshAwasthi、その条件付きについて奇妙なことは何もありません。トランジェントキャッシュに現在のデータがある場合、APIから取得する必要はありません。新しい情報を取得するのは、一時キャッシュが古くなっている場合のみです。
s_ha_dum 2012年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.