使用瞬变API缓存远程(HTTP)请求

时间:2012-11-22 作者:Umesh Awasthi

我正在尝试使用get_transient() 方法在我的Wordpress中,我已经阅读了文档,似乎我正在做文档中描述的事情。

我需要在我的网站上显示天气,我正在使用每6小时更新一次的第三方天气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

谁能纠正我哪里做错了?

2 个回复
最合适的回答,由SO网友:kaiser 整理而成

Catching the weather API remote data

The msg, you\'re showing in your question is basically the result from the weather API. And it says, that there\'s no data available for your location.

The first thing you want to do is some research in the Codex and the "WP HTTP API".

The right/WP way to grab remote data

After you\'ve learned about the WP HTTP API, you\'ll see that the common way to do it is (simplified like this):

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

If there\'s an error (as shown in your example), then you\'ll be able to catch it using the WP_Error class:

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

Then it\'s time to get the appropriate data. This will show 200 and OK, if everything on the remote side worked out. IMPORTANT: The remote data will likely follow no standard than their internal one. So there can be errors, but you will still get the positive 200/OK message back from them.

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

Get the result

Finally it\'s time to inspect the result. First, we get rid of leading/trailing white space(s). In the following sample, you see how to use the WP HTTP API to check the header. If we caught JSON, then we go with json_decode() and if we got XML, then we go with PHPs native SimpleXML class.

// 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...

In case of a CSV file, you\'ll have to find a custom solution or search for a PHP class on the interwebs. But honestly: If they\'re using CSV, it\'s easier to search for another service.

Cache the data with a Transient

The Transient API offers a pretty nice way to do this:

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

You should then be able to catch the transient with get_transient().

Common errors

An often encountered error is that the SSL verification doesn\'t work. Gladly you can turn it on/off pretty easy:

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

There\'s one pretty funny thing, as you\'ll find out when inspecting the appropriate core file: Core also got a filter for local requests. But don\'t get fooled by this one. This filter is only meant to get used in case you\'re A) providing a remote service from within your WP install and B) also consuming it yourself! I know, this can be quite a #WTF?! moment that this isn\'t a switch for you to use different SSL verification settings between your local install and your production environment/server, but it also has an idea behind it: It\'s to test services that you provide yourself as I also explained to the WP G+ community here.

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

Debugging the request & its results

Without diggin\' too deep into the update process, but the WP HTTP API uses the WP_HTTP class. It also offers a nice thing: A debug hook.

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

Where $response can also be a WP_Error object that maybe tells you more.

Note: From a brief test, this filter seems to only (for some reason) work if you place it as close to where you\'re actually doing the request. So maybe you need to call it from within a callback on one of the below filters.

Y NO CURL?

Easy. All the funkiness of the "WP HTTP API", that I\'ve shown above, is basically a function based wrapper for the WP_HTTP class internals, which acts as base class (and will be extended for different scenarios). The extending WP_HTTP_* classes are Fsockopen, Streams, Curl, Proxy, Cookie, Encoding. If you hook a callback to the \'http_api_debug\'-action, then the third argument will tell you which class was used for your request. You don\'t have to call the classes directly. Just use the functions.

For most remote/HTTP API requests, it\'s the WP_HTTP_curl class, which is a wrapper for PHPs native curl library.

Inside the WP_HTTP_curl Class, you\'ll find the request() method. This method offers two filters to intercept the SSL behavior: One for local requests \'https_local_ssl_verify\' and one for remote requests \'https_ssl_verify\'. WP will likely define local as localhost and what you get in return from get_option( \'siteurl\' );.

SO网友:s_ha_dum

问题不在于“瞬态”功能。这看起来像是从第三方API返回的错误消息。在使用之前,您可能需要检查一下set_transient. set_transient 将插入给出的任何内容get_transient 将检索数据库中的任何内容。In other words, I am fairly sure the problem is not where you think it is.

$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);
        }
 }
我正在猜测您的天气API的一些输出,因此您可能需要对其进行调整以获得所需的结果。

注意:您的API正在返回JSON。Your example decodes to:

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!\',
      )),
    ),
  )),
))

结束

相关推荐

有没有人在Dreamhost VPS上成功地使用了WordPress插件w3-Total-cache?

Dreamhost鼓励我使用FCGI、XCache和w3 total cache。但我不确定最佳设置是什么,尤其是对象和数据库缓存。有什么建议吗?此外,我无法消除此错误消息:Recently an error occurred while creating the CSS / JS minify cache 我也无法获取日志文件以显示。。。