Jump to content

Cacheing output of XML API


Tyssen
 Share

Recommended Posts

I'm working on a site that is using the Goodreads API but I'm finding the page very slow to render so would like to speed it up by cacheing the output of the API.

The page is made up of several child page 'bundles' each of which displays a selection of books which are chosen with a repeating field containing ISBN numbers.

$goodreads_api = 'xxxxxx';

foreach($page->children as $bundle) :

  foreach($bundle->goodreads as $goodreads) :

    $xml_string = file_get_contents('https://www.goodreads.com/search/index.xml?key='.$goodreads_api.'&q='.$goodreads->isbn);
    $book_xml = new SimpleXMLElement($xml_string);

    foreach ($book_xml->search->results->work as $book) :

    // content goes here

    endforeach;

  endforeach;

endforeach;

I've looked at the Markup Cache module but when I try cacheing the second foreach loop, I get the correct number of bundles and the correct number of books, but same output for every book.

If I cache the first foreach, I get the correct number of bundles, but only one book and again, the same content for each bundle.

So is Markup Cache the way to go, and if so, what am I doing wrong, or if not, what else should I be looking at?

Link to comment
Share on other sites

If I cache the first foreach, I get the correct number of bundles, but only one book and again, the same content for each bundle.

It would be good to see some code here, i.e. what exactly you're doing, but based on this comment it sounds like you're caching all the books with the same name and thus always overwriting previous one with the next one. Does this sound familiar?

If this is really the case, you should either generate unique name for each cached portion of the content OR cache them together instead of book-by-book.

Also: if you're using a relatively new version of ProcessWire, I'd suggest looking into the $cache API variable. MarkupCache is still valid approach, but $cache is a newer solution and widely used by the core itself. Additiionally it provides improved tools for invalidating the cache, which could come in handy here.

Link to comment
Share on other sites

The bits I left out are:

<img src="'.$book->best_book->image_url.'" alt="">
<h3 itemprop="name"><a href="https://www.goodreads.com/book/isbn/'.$goodreads->isbn.'">' . $book->best_book->title .'</a></h3>
<p class="bundle-book-author">by '. $book->best_book->author->name . '</p>

where it says // content goes here

If this is really the case, you should either generate unique name for each cached portion of the content OR cache them together instead of book-by-book.

I really just want to cache the XML output itself so that I can continue to work on the template markup and styles without having to wait several seconds for each page refresh. When you say generate a unique name for each cached portion, do you mean with a count and then something like ${'var' . $i}?

Link to comment
Share on other sites

This would cache only the xml for an hour. 

<?php

$goodreads_api = 'xxxxxx';

foreach($page->children as $bundle) :

  foreach($bundle->goodreads as $goodreads) :

    $xml_string = $cache->get($goodreads->isbn, 3600, function() use($goodreads_api, $goodreads) {
      return file_get_contents('https://www.goodreads.com/search/index.xml?key='.$goodreads_api.'&q='.$goodreads->isbn);
    });
    $book_xml = new SimpleXMLElement($xml_string);

    foreach ($book_xml->search->results->work as $book) :

    // content goes here

    endforeach;

  endforeach;

endforeach;
  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...