I was thinking of using Yii to build a small web app using data from a RESTful API. I checked the forums using the search engine and the only topic related to my concern was left unanswered, so I took the liberty to write a new one.
Since the API allows a limited number of requests per day and given that most of the information I’m interested about doesn’t change often, I was wondering how to write my models to use both the API and a database as data sources.
Check the Guide for details on how to implement caching. You can use Yii’s built in caching mechanism or write your own using the database as a caching backend.
One way - polling:
Your site would poll the REST service API every x minutes - this would probably be a console application run via cron. It would fetch the results and store them in cache or your database. In this case I think you’d use the results just like a $_POST array and populate your table model and save to the database.
public function actionCachedDataSample()
{
// Specify the ID for the cache item we wish to
// reference
$api_cache_id = 'my_api_data';
// Attempt to load the data from the cache, based on the key
$apidata = Yii::app()->cache->get( $api_cache_id );
// If the results were false, then we have no valid data,
// so load it
if($apidata===false)
{
// No valid cached data was found, so we will generate it.
$apidata = $this->loadRemoteContent();
// Store the data into the cache and allow it to be
// valid for 1 hour (3600 seconds)
Yii::app()->cache->set( $api_cache_id , $apidata, 3600 );
}
// Render some stuff here with my data
// $this->render( 'sample', array( 'apidata'=>$apidata ) );
// For now we'll just do a print_r so that we can see the data.
print_r( $apidata );
}
/**
* In a real scenario, this would be a curl_exec() to a remote server
* to get a consumable data source - xml, json data, etc.
* For this example, we'll return a simple array that includes the time
* it was generated.
*/
protected function loadRemoteContent( )
{
return array(
'You are viewing cached data.',
'The time is now '.date('Y-m-d H:i:s'),
);
}
Regarding your second point, if I understand correctly I would not be using caching, but instead create a class extending CConsoleCommand and define an action to call the API and update the models?
It really depends on what your goals are. If you never want to wait for an API response you will need to prefetch the data. If you are ok with letting another site’s response time to block your page rendering time it would be acceptable to use code similar to what Dana wrote about. Just depends on your requirements - just making an argument for either side.
As the example was very basic you would probably also consider cache dependency. Rather than fetch the whole api feed every X minutes and save it to your database, you might devise a way to detect if the content was updated. Lets say the feed included a version number, timestamp, or some other thing. You could then query the API for that token, compare to your cache, and skip the pull if unchanged to further optimize your code.
Some 3rd party sites offer ‘push’ notifications that will alert your server when changes occur. If your data source offers this, instead of polling via cron or whatever you can let them push updates to your URL of choice. When you receive the update you can then store it or requery the API to get the updated data. Check out this post for another idea of how to do it: