2014-09-28 05:59:48 +02:00
|
|
|
summary: Consume external data through their RESTFul interfaces.
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
# Restful Service
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
`[api:RestfulService]` is used to enable connections to remote web services through PHP's `curl` command. It provides an
|
|
|
|
interface and utility functions for generating a valid request and parsing the response returned from the web service.
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
<div class="alert" markdown="1">
|
|
|
|
RestfulService currently only supports XML. It has no JSON support at this stage.
|
|
|
|
</div>
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
## Examples
|
|
|
|
|
|
|
|
### Creating a new RestfulObject
|
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
`getWellingtonWeather` queries the Yahoo Weather API for an XML file of the latest weather information. We pass a query
|
|
|
|
string parameter `q` with the search query and then convert the resulting XML data to an `ArrayList` object to display
|
|
|
|
in the template.
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
**mysite/code/Page.php**
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
:::php
|
2014-09-28 05:59:48 +02:00
|
|
|
public function getWellingtonWeather() {
|
|
|
|
$fetch = new RestfulService(
|
|
|
|
'https://query.yahooapis.com/v1/public/yql'
|
|
|
|
);
|
|
|
|
|
|
|
|
$fetch->setQueryString(array(
|
|
|
|
'q' => 'select * from weather.forecast where woeid in (select woeid from geo.places(1) where text="Wellington, NZ")'
|
|
|
|
));
|
|
|
|
|
|
|
|
// perform the query
|
|
|
|
$conn = $fetch->request();
|
|
|
|
|
|
|
|
// parse the XML body
|
|
|
|
$msgs = $fetch->getValues($conn->getBody(), "results");
|
|
|
|
|
|
|
|
// generate an object our templates can read
|
|
|
|
$output = new ArrayList();
|
|
|
|
|
|
|
|
if($msgs) {
|
|
|
|
foreach($msgs as $msg) {
|
|
|
|
$output->push(new ArrayData(array(
|
|
|
|
'Description' => Convert::xml2raw($msg->channel_item_description)
|
|
|
|
)));
|
|
|
|
}
|
2011-02-07 07:48:44 +01:00
|
|
|
}
|
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
return $output;
|
|
|
|
}
|
|
|
|
|
|
|
|
## Features
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
### Basic Authenication
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
:::php
|
|
|
|
$service = new RestfulService("http://example.harvestapp.com");
|
|
|
|
$service->basicAuth('username', 'password');
|
2014-09-28 05:59:48 +02:00
|
|
|
|
|
|
|
### Make multiple requests
|
|
|
|
|
|
|
|
:::php
|
|
|
|
$service = new RestfulService("http://example.harvestapp.com");
|
2014-09-21 02:07:58 +02:00
|
|
|
|
2014-04-23 16:31:22 +02:00
|
|
|
$peopleXML = $service->request('/people');
|
2011-02-07 07:48:44 +01:00
|
|
|
$people = $service->getValues($peopleXML, 'user');
|
2014-09-21 02:07:58 +02:00
|
|
|
|
2012-10-02 11:38:16 +02:00
|
|
|
// ...
|
2014-09-21 02:07:58 +02:00
|
|
|
|
2014-04-23 16:31:22 +02:00
|
|
|
$taskXML = $service->request('/tasks');
|
2011-02-07 07:48:44 +01:00
|
|
|
$tasks = $service->getValues($taskXML, 'task');
|
|
|
|
|
|
|
|
|
2014-09-21 02:07:58 +02:00
|
|
|
### Caching
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
To set the cache interval you can pass it as the 2nd argument to constructor.
|
|
|
|
|
|
|
|
:::php
|
2014-09-28 05:59:48 +02:00
|
|
|
$expiry = 60 * 60; // 1 hour;
|
|
|
|
|
|
|
|
$request = new RestfulService("http://example.harvestapp.com", $expiry );
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
|
|
|
|
### Getting Values & Attributes
|
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
You can traverse through document tree to get the values or attribute of a particular node using XPath. Take for example
|
|
|
|
the following XML that is returned.
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
:::xml
|
2014-04-23 16:31:22 +02:00
|
|
|
<entries>
|
2011-02-07 07:48:44 +01:00
|
|
|
<entry id='12'>Sally</entry>
|
|
|
|
<entry id='15'>Ted</entry>
|
|
|
|
<entry id='30'>Matt</entry>
|
|
|
|
<entry id='22'>John</entry>
|
2014-04-23 16:31:22 +02:00
|
|
|
</entries>
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
To extract the id attributes of the entries use:
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
:::php
|
2014-09-28 05:59:48 +02:00
|
|
|
$this->getAttributes($xml, "entries", "entry");
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
// array(array('id' => 12), array('id' => '15'), ..)
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
To extract the values (the names) of the entries use:
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
:::php
|
2014-09-28 05:59:48 +02:00
|
|
|
$this->getValues($xml, "entries", "entry");
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
// array('Sally', 'Ted', 'Matt', 'John')
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
### Searching for Values & Attributes
|
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
If you don't know the exact position of DOM tree where the node will appear you can use xpath to search for the node.
|
|
|
|
|
|
|
|
<div class="note">
|
|
|
|
This is the recommended method for retrieving values of name spaced nodes.
|
|
|
|
</div>
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
:::xml
|
2014-04-23 16:31:22 +02:00
|
|
|
<media:guide>
|
2011-02-07 07:48:44 +01:00
|
|
|
<media:entry id="2030">video</media:entry>
|
2014-04-23 16:31:22 +02:00
|
|
|
</media:guide>
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
To get the value of entry node with the namespace media, use:
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
:::php
|
2014-09-28 05:59:48 +02:00
|
|
|
$this->searchValue($response, "//media:guide/media:entry");
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
// array('video');
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
|
|
|
|
## Best Practices
|
|
|
|
|
|
|
|
### Handling Errors
|
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
If the web service returned an error (for example, API key not available or inadequate parameters),
|
|
|
|
`[api:RestfulService]` can delegate the error handling to it's descendant class. To handle the errors, subclass
|
|
|
|
`RestfulService and define a function called errorCatch.
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
:::php
|
2014-09-28 05:59:48 +02:00
|
|
|
<?php
|
2014-09-21 02:07:58 +02:00
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
class MyRestfulService extends RestfulService {
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
public function errorCatch($response) {
|
|
|
|
$err_msg = $response;
|
|
|
|
|
|
|
|
if(strpos($err_msg, '<') === false) {
|
|
|
|
user_error("YouTube Service Error : $err_msg", E_USER_ERROR);
|
|
|
|
}
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
}
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
If you want to bypass error handling, define `checkErrors` in the constructor for `RestfulService`
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
:::php
|
2014-09-28 05:59:48 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
class MyRestfulService extends RestfulService {
|
|
|
|
|
|
|
|
public function __construct($expiry = NULL) {
|
|
|
|
parent::__construct('http://www.flickr.com/services/rest/', $expiry);
|
|
|
|
|
|
|
|
$this->checkErrors = false;
|
|
|
|
}
|
2014-04-23 16:31:22 +02:00
|
|
|
}
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
|
2014-05-07 11:12:08 +02:00
|
|
|
### Setting cURL options
|
|
|
|
|
|
|
|
Restful service uses cURL to make requests. There are various settings that can be defined on the cURL
|
|
|
|
request (see http://www.php.net/manual/en/function.curl-setopt.php) via the curl_setopts function.
|
|
|
|
|
|
|
|
There are two ways to define these for `RestfulService`; they can be global settings or per request settings.
|
|
|
|
|
|
|
|
It is important to note that your cURL options will be applied LAST and so take preference over any default
|
|
|
|
values that `RestfulService` sets (such as `CURLOPT_RETURNTRANSFER`) so changing these options may result
|
|
|
|
in unexpected behaviour or broken functionality.
|
|
|
|
|
|
|
|
|
|
|
|
#### Global cURL settings
|
|
|
|
|
|
|
|
To set global cURL settings you can update the `RestfulService` config via the Config system or YAML.
|
|
|
|
|
|
|
|
Here is an example to increase the HTTP Timeout globally. Insert this in your `_config.php` file:
|
|
|
|
|
|
|
|
```php
|
|
|
|
Config::inst()->update('RestfulService', 'default_curl_options', array(
|
|
|
|
CURLOPT_DNS_CACHE_TIMEOUT => 3600,
|
2014-05-07 13:06:44 +02:00
|
|
|
CURLOPT_CONNECTTIMEOUT => 10,
|
2014-05-07 11:12:08 +02:00
|
|
|
));
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### Per request settings
|
|
|
|
|
|
|
|
When making a request using `RestfulService` one can also pass through an array of cURL options in the last
|
|
|
|
parameter in `RestfulService::request()`.
|
|
|
|
|
|
|
|
For example:
|
|
|
|
|
|
|
|
```php
|
|
|
|
|
|
|
|
//cURL options
|
|
|
|
$curlOptions = array(
|
|
|
|
CURLOPT_UNRESTRICTED_AUTH => true,
|
|
|
|
);
|
|
|
|
|
|
|
|
$service = new RestfulService('http://example.com/');
|
|
|
|
$service->request('service.json', 'GET', null, null, $curlOptions);
|
|
|
|
|
|
|
|
```
|
|
|
|
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2014-09-28 05:59:48 +02:00
|
|
|
## How to's
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2015-02-28 01:09:15 +01:00
|
|
|
* [Embed an RSS Feed](how_tos/embed_rss)
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
## API Documentation
|
2014-09-28 05:59:48 +02:00
|
|
|
|
|
|
|
* `[api:RestfulService]`
|