Yêu cầu bộ nhớ cache từ xa (HTTP) với API khách hàng


8

Tôi đang cố gắng sử dụng get_transient()phương thức trong Wordpress của mình, tôi đã đọc tài liệu và có vẻ như tôi đang làm những gì đã được mô tả trong các tài liệu.

Tôi cần hiển thị thời tiết trên trang web của mình và tôi đang sử dụng API thời tiết của bên thứ ba được cập nhật mỗi 6 giờ.

Chúng tôi đang tạo bộ đệm cục bộ về thời tiết để API chỉ được gọi sau khi hết thời gian. (Lý do khác: giới hạn tỷ lệ API)

Đây là mã của tôi:

$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);
 }

Khi tôi đang gửi một vị trí để nhận thời tiết ( say delhi) và nếu nó không có trong bộ đệm, tôi đã hy vọng rằng nó sẽ quay trở lại falsetrong khi nó trả lại cho tôi chuỗi theo

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

Tôi đã sử dụng var_dump($weather);để kiểm tra giá trị của$weather

Bất cứ ai có thể sửa cho tôi nơi tôi đang làm sai?


1
Điều này không liên quan đến get_transient()- nhưng với yêu cầu API: như được đưa ra bởi thông báo lỗi. Ngoài việc khuyến nghị bạn sử dụng, wp_remote_postbạn chỉ cần đảm bảo rằng yêu cầu được gửi là hợp lệ.
Stephen Harris

@StephenHarris: Tôi không chắc chắn về cuộc gọi vì nó chỉ được đưa ra bên trong if (false === $weather). Tôi đã cập nhật câu hỏi của tôi
Umesh Awasthi

1
Vấn đề là bộ đệm sẽ lưu trữ bất cứ thứ gì bạn cung cấp - và trong trường hợp này bạn đang đưa ra thông báo lỗi từ API thời tiết. Bộ đệm sẽ chỉ trả về sai nếu không có gì được lưu trữ - vì vậy bạn nên kiểm tra phản hồi từ API thời tiết và nếu nó hợp lệ - lưu trữ nó.
Stephen Harris

@StephenHarris: aha tôi đã nhận quan điểm của bạn chỉ bỏ lỡ nó completely.i chỉ mới bắt đầu với PHP và tôi chỉ đơn giản là bỏ qua tất cả mọi thứ và thậm chí không nhìn cẩn thận vào mã :)
Umesh Awasthi

Câu trả lời:


11

Bắt dữ liệu từ xa API thời tiết

Các msg, bạn đang hiển thị trong câu hỏi của bạn về cơ bản là kết quả từ API thời tiết. Và nó nói rằng không có dữ liệu cho vị trí của bạn.

Điều đầu tiên bạn muốn làm là một số nghiên cứu về Codex và "WP HTTP API" .

Cách đúng / WP để lấy dữ liệu từ xa

Sau khi bạn đã tìm hiểu về API HTTP HTTP, bạn sẽ thấy rằng cách phổ biến để làm điều đó là (đơn giản hóa như thế này):

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

Nếu có lỗi (như trong ví dụ của bạn), thì bạn sẽ có thể bắt lỗi bằng cách sử dụng WP_Errorlớp:

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

Sau đó là thời gian để có được dữ liệu thích hợp. Điều này sẽ hiển thị 200OK, nếu mọi thứ ở phía xa hoạt động. QUAN TRỌNG: Dữ liệu từ xa có thể sẽ không theo tiêu chuẩn nào so với dữ liệu nội bộ của chúng. Vì vậy, có thể có lỗi, nhưng bạn vẫn sẽ nhận được 200/OKthông điệp tích cực từ họ.

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

Nhận kết quả

Cuối cùng cũng đến lúc kiểm tra kết quả. Đầu tiên, chúng ta thoát khỏi khoảng trắng hàng đầu / dấu. Trong mẫu sau, bạn thấy cách sử dụng API HTTP HTTP để kiểm tra tiêu đề. Nếu chúng ta bắt được JSON, thì chúng ta sẽ đi json_decode()và nếu chúng ta có XML, thì chúng ta sẽ đi với SimpleXMLlớp bản địa của PHP .

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

Trong trường hợp tệp CSV, bạn sẽ phải tìm một giải pháp tùy chỉnh hoặc tìm kiếm một lớp PHP trên các bản interwebs. Nhưng thành thật mà nói: Nếu họ đang sử dụng CSV, việc tìm kiếm dịch vụ khác sẽ dễ dàng hơn.

Lưu trữ dữ liệu với Transient

Các API thoáng Mời một cách khá thoải mái để làm điều này:

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

Sau đó bạn sẽ có thể bắt được thoáng qua với get_transient().

Lỗi thông thường

Một lỗi thường gặp là xác minh SSL không hoạt động. Rất vui khi bạn có thể bật / tắt nó khá dễ dàng:

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

Có một điều khá buồn cười, như bạn sẽ tìm ra khi kiểm tra tệp lõi thích hợp: Core cũng có một bộ lọc cho các yêu cầu cục bộ . Nhưng đừng để bị lừa bởi cái này. Bộ lọc này chỉ có nghĩa là được sử dụng trong trường hợp bạn A) cung cấp dịch vụ từ xa trong cài đặt WP của bạn và B) cũng tự tiêu thụ nó! Tôi biết, đây có thể là một #WTF?!khoảnh khắc mà đây không phải là một công tắc để bạn sử dụng các cài đặt xác minh SSL khác nhau giữa cài đặt cục bộ và môi trường / máy chủ sản xuất của bạn, nhưng nó cũng có một ý tưởng đằng sau nó: Đó là để kiểm tra các dịch vụ mà bạn cung cấp cho mình như tôi cũng đã giải thích cho cộng đồng WP G + ở đây .

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

Gỡ lỗi yêu cầu và kết quả của nó

Không đào sâu 'quá sâu vào quá trình cập nhật, nhưng API HTTP WP sử dụng lớp WP_HTTP. Nó cũng cung cấp một điều tốt đẹp: Một cái móc gỡ lỗi.

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

Nơi $responsecũng có thể là một WP_Errorđối tượng có thể cho bạn biết nhiều hơn.

Lưu ý: Từ một thử nghiệm ngắn, bộ lọc này dường như chỉ hoạt động (vì một số lý do) hoạt động nếu bạn đặt nó gần với nơi bạn thực sự thực hiện yêu cầu. Vì vậy, có thể bạn cần gọi nó từ trong một cuộc gọi lại trên một trong các bộ lọc dưới đây.

Y KHÔNG CÓ HIỆN TẠI?

Dễ dàng. Tất cả sự thú vị của "API HTTP WP", mà tôi đã trình bày ở trên, về cơ bản là một trình bao bọc dựa trên chức năng cho các phần WP_HTTPbên trong lớp, hoạt động như lớp cơ sở (và sẽ được mở rộng cho các kịch bản khác nhau). Các mở rộng WP_HTTP_*lớp học Fsockopen, Streams, Curl, Proxy, Cookie, Encoding. Nếu bạn kết nối một cuộc gọi lại với 'http_api_debug'-action, thì đối số thứ ba sẽ cho bạn biết lớp nào đã được sử dụng cho yêu cầu của bạn. Bạn không phải gọi các lớp trực tiếp. Chỉ cần sử dụng các chức năng.

Đối với hầu hết các yêu cầu API từ xa / HTTP, đó là WP_HTTP_curllớp, là trình bao bọc cho curlthư viện gốc PHP .

Trong WP_HTTP_curlLớp học, bạn sẽ tìm thấy request()phương pháp. Phương pháp này cung cấp hai bộ lọc để chặn hành vi SSL: Một cho các yêu cầu cục bộ 'https_local_ssl_verify'và một cho các yêu cầu từ xa 'https_ssl_verify'. WP có thể sẽ xác định locallocalhostvà những gì bạn nhận được returntừ get_option( 'siteurl' );.


Lưu ý: Câu trả lời này có thể được đọc là phần mở rộng cho câu trả lời này tôi đã đưa ra .
kaiser

Cám ơn các đầu vào, tôi không chắc chắn về câu trả lời từ API waether như nó đang nhận được gọi là chỉ khi chúng ta không có dữ liệu, tôi đã kiểm tra các URL cho API và nó trở về tôi hợp lệ data.Will cố gắng để gỡ lỗi nó nhiều hơn
Umesh Awasthi

@UmeshAwasthi Vui lòng thử những gì tôi đã viết ở trên - từng bước một. Trước tiên hãy xem những gì bạn nhận được từ wp_remote_request()URL của mình, sau đó đi xa hơn với câu trả lời. Đây là một hướng dẫn khá đầy đủ và chỉ cho bạn cách đúng để thực hiện các yêu cầu HTTP trong WP. Để làm rõ hơn một vết cắn: Bạn không phải gọi WP_HTTP_curllớp, vì WordPress đã làm điều này cho bạn, khi bạn sử dụng các chức năng được hiển thị ở trên.
kaiser

tôi đang trên đường để kiểm tra cái này. Cho đến khi tôi hoàn thành nó :)
Umesh Awasthi

1
mặc dù vấn đề là một vấn đề khác, nhưng tôi đã đánh dấu câu trả lời của bạn là được chấp nhận vì nó cung cấp một cách tốt hơn để thực hiện cùng một công việc và tôi cho rằng nếu nền tảng cung cấp một số API, tốt hơn là sử dụng chúng Cảm ơn !!
Umesh Awasthi

3

Vấn đề không nằm ở chức năng 'quá độ'. Trông giống như một thông báo lỗi được trả về từ API bên thứ ba của bạn. Bạn có thể cần kiểm tra trước khi sử dụng set_transient. set_transientsẽ chèn bất cứ thứ gì nó được đưa ra và get_transientsẽ lấy bất cứ thứ gì có trong DB. Nói cách khác, tôi khá chắc chắn rằng vấn đề không nằm ở chỗ bạn nghĩ nó xảy ra.

$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);
        }
 }

Tôi đoán về một số đầu ra từ API thời tiết của bạn để bạn có thể cần phải điều chỉnh nó để có được kết quả bạn muốn.

Lưu ý: API của bạn đang trả về JSON. Ví dụ của bạn giải mã thành:

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

Cảm ơn về đầu vào, nhưng có vẻ khá lạ đối với tôi khi chỉ gọi API được đưa ra bên trong if (false === $weather)câu lệnh. Tôi không biết WP_HTTP_curllớp sẽ cố gắng sử dụng điều đó
Umesh Awasthi

@UmeshAwasthi, không có gì lạ về điều kiện đó. Nếu bạn có dữ liệu hiện tại trong bộ đệm tạm thời, bạn không muốn truy xuất nó từ API. Chỉ khi bộ đệm tạm thời của bạn hết hạn, bạn mới lấy thông tin mới.
s_ha_dum
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.