web-dev-qa-db-fra.com

Demande de cache à distance (HTTP) avec l'API transitoire

J'essaie d'utiliser la méthode get_transient() dans Wordpress, j'ai lu le document et j'ai l'impression de faire ce qui a été décrit dans la documentation.

Je dois afficher la météo sur mon site Web et j'utilise une API météo tierce mise à jour toutes les 6 heures.

Nous sommes en train de créer un cache local de météo afin que l'API ne soit appelée qu'après l'expiration. (Autre raison: limitation du débit de l'API)

Ceci est mon code:

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

Lorsque j'envoie un emplacement pour obtenir la météo (say delhi) et s'il n'y en a pas dans la mémoire cache, je m'attendais à ce qu'il retourne false pendant qu'il me renvoie chaîne suivante

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

J'ai utilisé var_dump($weather); pour vérifier la valeur de $weather

Quelqu'un peut-il me corriger là où je me trompe?

8
Umesh Awasthi

Saisir les données distantes de l'API météo

La msg, vous indiquez dans votre question le résultat de l’API météo. Et il est dit qu'il n'y a pas de données disponibles pour votre emplacement.

La première chose à faire est de faire une recherche sur le Codex et "l'API HTTP WP" .

La bonne façon/WP de saisir des données distantes

Une fois que vous avez appris à propos de l'API HTTP WP, vous verrez que la façon habituelle de le faire est (simplifiée comme ceci):

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

S'il y a une erreur (comme indiqué dans votre exemple), vous pourrez l'attraper à l'aide de la classe 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()
);

Ensuite, il est temps d'obtenir les données appropriées. Ceci affichera 200 et OK, si tout ce qui se trouve du côté distant a fonctionné. IMPORTANT: Les données distantes ne suivront probablement aucune norme que leur norme interne. Donc, il y a peut des erreurs, mais vous obtiendrez toujours le message positif 200/OK.

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

Obtenir le résultat

Enfin, il est temps d'inspecter le résultat. Premièrement, nous nous débarrassons des espaces blancs de début/fin. Dans l'exemple suivant, vous voyez comment utiliser l'API HTTP WP pour vérifier l'en-tête. Si nous avons attrapé JSON, alors nous allons avec json_decode() et si nous avons XML, alors nous allons avec PHP native SimpleXML classe.

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

Dans le cas d'un fichier CSV, vous devrez trouver une solution personnalisée ou rechercher une classe PHP sur les interwebs. Mais honnêtement: s’ils utilisent le format CSV, il est plus facile de rechercher un autre service.

Cache les données avec un transitoire

L'API Transient offre une belle façon de faire cela:

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

Vous devriez alors pouvoir attraper le transitoire avec get_transient().

Erreurs courantes

Une erreur fréquente est que la vérification SSL ne fonctionne pas. Volontiers, vous pouvez l'activer/le désactiver assez facilement:

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

Comme vous le constaterez lors de l'inspection du fichier core approprié, Core dispose également d'un filtre pour local . Mais ne vous laissez pas berner par celui-ci. Ce filtre est uniquement destiné à être utilisé dans le cas où vous: A) fournissez un service distant à partir de votre WP installation et B) le consommez vous-même! Je sais que cela peut être un assez #WTF?! moment où ce n’est pas un commutateur pour que vous utilisiez différents paramètres de vérification SSL entre votre installation locale et votre environnement/serveur de production, mais cela a aussi une idée derrière cela: c’est de tester des services qui vous vous fournissez comme je aussi expliqué à la WP communauté G + ici .

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

Débogage de la demande et de ses résultats

Sans entrer trop dans le processus de mise à jour, mais l'API HTTP WP utilise la classe WP_HTTP. Il offre également une bonne chose: un crochet de débogage.

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

$response peut également être un objet WP_Error qui en dit peut-être plus.

Remarque: D'un bref test, ce filtre ne semble fonctionner (pour une raison quelconque) que si vous le placez aussi près que vous le souhaitez de la demande. Alors peut-être devez-vous l'appeler à partir d'un rappel sur l'un des filtres ci-dessous.

Y NO CURL?

Facile. Tous les aspects amusants de "l'API HTTP WP", que je viens de montrer ci-dessus, sont fondamentalement des encapsuleurs basés sur des fonctions pour les éléments internes de la classe WP_HTTP, qui agissent comme classe de base (et seront étendus pour différents scénarios). Les classes WP_HTTP_* extensibles sont Fsockopen, Streams, Curl, Proxy, Cookie, Encoding. Si vous associez un rappel à l'action 'http_api_debug'-, le troisième argument vous indiquera quelle classe a été utilisée pour votre demande. _ {Il n'est pas nécessaire d'appeler directement les classes. Il suffit d'utiliser les fonctions.

Pour la plupart des requêtes d'API HTTP/distantes, il s'agit de la classe WP_HTTP_curl, qui encapsule la bibliothèque curl native PHP.

Dans la classe WP_HTTP_curl, vous trouverez la méthode request(). Cette méthode propose deux filtres pour intercepter le comportement SSL: un pour les requêtes locales 'https_local_ssl_verify' et un pour les requêtes distantes 'https_ssl_verify'. WP définira probablement local comme localhost et ce que vous obtenez dans return à partir de get_option( 'siteurl' );.

11
kaiser

Le problème ne vient pas de la fonction 'transitoires'. Cela ressemble à un message d'erreur renvoyé par votre API tierce. Vous devrez probablement vérifier cela avant d'utiliser set_transient. set_transient insérera ce qui est donné et get_transient récupérera tout ce qui se trouve dans la base de données. En d'autres termes, je suis à peu près sûr que le problème n'est pas ce que vous pensez.

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

Je devine certaines des données de votre API météo. Vous devrez peut-être modifier cela pour obtenir les résultats souhaités.

Remarque: votre API renvoie JSON. Votre exemple décode à:

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