Permintaan cache jarak jauh (HTTP) dengan Transients API

8

Saya mencoba menggunakan get_transient()metode di Wordpress saya, saya sudah membaca dokumen dan sepertinya saya melakukan apa yang telah dijelaskan dalam dokumen.

Saya perlu menunjukkan cuaca di situs web saya dan saya menggunakan API cuaca pihak ketiga yang diperbarui setiap 6 jam.

Kami membuat cache cuaca lokal sehingga API hanya dapat dipanggil setelah waktu kedaluwarsa. (Alasan lain: pembatasan tingkat API)

Ini kode saya:

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

Ketika saya mengirim lokasi untuk mendapatkan cuaca ( say delhi) dan jika tidak ada di cache, saya berharap itu akan kembali falsesaat itu mengembalikan saya mengikuti string

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

Saya digunakan var_dump($weather);untuk memeriksa nilai$weather

Adakah yang bisa memperbaiki saya di tempat saya melakukan kesalahan?

Umesh Awasthi
sumber
1
Ini tidak terkait dengan get_transient()- tetapi dengan permintaan API: seperti yang diberikan oleh pesan kesalahan. Selain menyarankan Anda menggunakan wp_remote_postAnda hanya perlu memastikan bahwa permintaan yang dikirim adalah valid.
Stephen Harris
@StephenHarris: Saya tidak yakin tentang panggilan karena hanya diberikan di dalam if (false === $weather). Saya telah memperbarui pertanyaan saya
Umesh Awasthi
1
Intinya adalah cache akan menyimpan apa pun yang Anda berikan - dan dalam hal ini Anda memberikan pesan kesalahan dari API cuaca. Cache hanya akan mengembalikan false jika tidak ada yang disimpan - jadi Anda harus memeriksa respons dari API cuaca dan jika valid - simpanlah.
Stephen Harris
@StephenHarris: aha saya mendapatkan poin Anda hanya melewatkannya sepenuhnya. Saya baru saja mulai dengan PHP dan saya hanya mengabaikan semuanya dan bahkan tidak melihat dengan hati-hati pada kode :)
Umesh Awasthi

Jawaban:

11

Menangkap data jarak jauh API cuaca

The msg, yang Anda tunjukkan dalam pertanyaan Anda pada dasarnya adalah hasil dari API cuaca. Dan dikatakan, bahwa tidak ada data tersedia untuk lokasi Anda.

Hal pertama yang ingin Anda lakukan adalah penelitian di Codex dan "WP HTTP API" .

Cara kanan / WP untuk mengambil data jarak jauh

Setelah Anda belajar tentang WP HTTP API, Anda akan melihat bahwa cara umum untuk melakukannya adalah (disederhanakan seperti ini):

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

Jika ada kesalahan (seperti yang ditunjukkan pada contoh Anda), maka Anda dapat menangkapnya menggunakan WP_Errorkelas:

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

Maka saatnya untuk mendapatkan data yang sesuai. Ini akan menunjukkan 200dan OK, jika semuanya di sisi jarak jauh berhasil. PENTING: Data jarak jauh kemungkinan tidak mengikuti standar selain yang internal. Jadi mungkin ada kesalahan, tetapi Anda masih akan mendapatkan 200/OKpesan positif kembali dari mereka.

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

Dapatkan hasilnya

Akhirnya saatnya untuk memeriksa hasilnya. Pertama, kita menyingkirkan ruang putih terdepan / tertinggal. Dalam sampel berikut, Anda melihat cara menggunakan WP HTTP API untuk memeriksa header. Jika kita ketahuan JSON, maka kita pergi dengan json_decode()dan jika kita punya XML, maka kita pergi dengan SimpleXMLkelas asli 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...

Dalam hal file CSV, Anda harus menemukan solusi khusus atau mencari kelas PHP pada jalinan. Tapi jujur: Jika mereka menggunakan CSV, lebih mudah untuk mencari layanan lain.

Cache data dengan Transient

The API Transient menawarkan cara yang cukup bagus untuk melakukan hal ini:

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

Anda kemudian dapat menangkap transient dengan get_transient().

Kesalahan Umum

Kesalahan yang sering dijumpai adalah verifikasi SSL tidak berfungsi. Dengan senang hati Anda dapat menyalakan / mematikannya dengan mudah:

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

Ada satu hal yang cukup lucu, karena Anda akan tahu ketika memeriksa file inti yang sesuai: Core juga mendapat filter untuk permintaan lokal . Tapi jangan tertipu oleh yang satu ini. Filter ini hanya dimaksudkan untuk digunakan jika Anda A) menyediakan layanan jarak jauh dari dalam instalasi WP Anda dan B) juga mengkonsumsinya sendiri! Saya tahu, ini bisa menjadi #WTF?!momen yang cukup sulit bagi Anda untuk menggunakan pengaturan verifikasi SSL yang berbeda antara instalasi lokal Anda dan lingkungan produksi / server Anda, tetapi juga memiliki ide di baliknya: Ini untuk menguji layanan yang Anda gunakan berikan diri Anda seperti yang saya jelaskan kepada komunitas WP G + di sini .

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

Men-debug permintaan & hasilnya

Tanpa diggin terlalu jauh ke dalam proses pembaruan, tetapi WP HTTP API menggunakan kelas WP_HTTP. Ini juga menawarkan hal yang menyenangkan: Sebuah kait debug.

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

Di mana $responsejuga bisa menjadi WP_Errorobjek yang mungkin memberi tahu Anda lebih banyak.

Catatan: Dari tes singkat, filter ini tampaknya hanya (karena alasan tertentu) berfungsi jika Anda menempatkannya sedekat mungkin dengan tempat Anda benar-benar melakukan permintaan. Jadi mungkin Anda perlu meneleponnya dari dalam panggilan balik di salah satu filter di bawah ini.

Y TIDAK ADA CURL?

Mudah. Semua kegembiraan "WP HTTP API", yang telah saya perlihatkan di atas, pada dasarnya adalah pembungkus berbasis fungsi untuk WP_HTTPinternal kelas, yang bertindak sebagai kelas dasar (dan akan diperluas untuk skenario yang berbeda). The memperpanjang WP_HTTP_*kelas yang Fsockopen, Streams, Curl, Proxy, Cookie, Encoding. Jika Anda mengaitkan panggilan balik ke 'http_api_debug'-aksi, maka argumen ketiga akan memberi tahu Anda kelas mana yang digunakan untuk permintaan Anda. Anda tidak harus memanggil kelas secara langsung. Cukup gunakan fungsinya.

Untuk sebagian besar permintaan API jarak jauh / HTTP, ini adalah WP_HTTP_curlkelasnya, yang merupakan pembungkus untuk curlperpustakaan asli PHP .

Di dalam WP_HTTP_curlKelas, Anda akan menemukan request()metodenya. Metode ini menawarkan dua filter untuk mencegat perilaku SSL: Satu untuk permintaan lokal 'https_local_ssl_verify'dan satu untuk permintaan jarak jauh 'https_ssl_verify'. WP kemungkinan akan mendefinisikan localsebagai localhostdan apa yang Anda dapatkan di returndari get_option( 'siteurl' );.

kaisar
sumber
Catatan: Jawaban ini dapat dibaca sebagai ekstensi dari jawaban yang saya berikan ini .
kaiser
Terima kasih untuk masukan, saya tidak yakin tentang respon dari API waether sebagai yang sedang mendapatkan dipanggil hanya ketika kita tidak memiliki data, saya memeriksa URL untuk API dan yang kembali saya berlaku data.Will mencoba untuk debug lebih
Umesh Awasthi
@UmeshAwasthi Silakan coba apa yang saya tulis di atas - langkah demi langkah. Pertama lihat apa yang Anda dapatkan kembali wp_remote_request()dengan URL Anda, kemudian lanjutkan dengan jawabannya. Ini adalah tutorial yang cukup lengkap dan menunjukkan kepada Anda cara yang tepat untuk membuat permintaan HTTP di WP. Untuk memperjelas lebih banyak: Anda tidak perlu memanggil WP_HTTP_curlkelas, karena WordPress sudah melakukan ini untuk Anda, ketika Anda menggunakan fungsi yang ditunjukkan di atas.
kaiser
Saya sedang dalam perjalanan untuk menguji ini. Akan diperbarui setelah saya menyelesaikannya :)
Umesh Awasthi
1
meskipun masalahnya adalah sesuatu yang lain, tetapi saya menandai jawaban Anda sebagai diterima karena menyediakan cara yang lebih baik untuk melakukan pekerjaan yang sama dan saya berpendapat bahwa jika platform menyediakan beberapa API, lebih baik untuk menggunakannya Terima kasih !!
Umesh Awasthi
3

Masalahnya bukan dengan fungsi 'sementara'. Itu tampak seperti pesan kesalahan yang dikembalikan dari API pihak ketiga Anda. Anda mungkin perlu memeriksa itu sebelum digunakan set_transient. set_transientakan memasukkan apa pun yang diberikan dan get_transientakan mengambil apa pun yang ada di DB. Dengan kata lain, saya cukup yakin masalahnya bukan di mana Anda pikir itu.

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

Saya menebak tentang beberapa output dari API cuaca Anda sehingga Anda mungkin perlu mengubah itu untuk mendapatkan hasil yang Anda inginkan.

Catatan: Anda API mengembalikan JSON. Contoh Anda diterjemahkan ke:

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!',
      )),
    ),
  )),
))
s_ha_dum
sumber
Terima kasih atas masukannya, tetapi tampaknya agak aneh bagi saya karena hanya panggilan ke API yang diberikan hanya if (false === $weather)pernyataan di dalam. Saya tidak tahu WP_HTTP_curlkelas akan mencoba menggunakannya
Umesh Awasthi
@UmeshAwasthi, tidak ada yang aneh dengan persyaratan itu. Jika Anda memiliki data saat ini di cache transien, Anda tidak ingin mengambilnya dari API. Hanya jika cache transien Anda kedaluwarsa barulah Anda menarik informasi baru.
s_ha_dum