#Kohana RESTful Web Service Library
- Author: Jeremy Fowler
- Copyright: (c) 2012 Jeremy Fowler
- License: http://www.opensource.org/licenses/BSD-3-Clause
##Requires
- Kohana >= 3.2
- PHP >= 5.3
##Features
- X-HTTP-METHOD-OVERRIDE support
- Cross-Origin Resource Sharing
- ETags
##Installation
cd modules
git clone git://github.com/jerfowler/REST.git
- Enable the REST module in bootstrap
- Create REST extended models in classes/model/rest
- Optional: create your own custom controller_rest
##Controllers handle content type and output Each controller must implement one or more of the REST_Content Interfaces
class Controller_Template_REST extends Controller
implements REST_Content_HTML,
REST_Content_JSON,
REST_Content_XML,
REST_Content_CSV {
###The Rest module gets instantiated in the before method of the controller
- The model is determined by the Controller's action
- REST supports X-HTTP-METHOD-OVERRIDE by using
method_override(TRUE)
/**
* Rest object
* @var Rest
*/
protected $_rest;
public function before()
{
parent::before();
$this->_rest = REST::instance($this)
->method_override(TRUE)
->content_override(TRUE)
->execute();
}
####Content-Type is auto-detected by the headers (as is Language & Charset)
This can be overridden by using content_override(TRUE)
and using a special route
Route::set('rest', 'rest/<action>((/<id>)(.<content_type>))')
->defaults(array(
'controller' => 'rest'
));
###Output is handled by the various REST_Content Interface Methods
- Models pass the values generated by the HTTP method which is then retrieved by
result()
and then various otherresult_x()
helper functions. - ETags read/generated using the
etag()
method
public function action_html()
{
$values = $this->_rest->result();
$view = View::factory('rest/html', array('values' => $values));
$this->response->body($view);
}
public function action_json()
{
$json = $this->_rest->etag()->result_json();
$this->response->body($json);
}
public function action_xml()
{
$xml = $this->_rest->etag()->result_xml();
$this->response->body($xml->asXML());
}
public function action_csv()
{
$csv = $this->_rest->result_csv();
$this->response->body($csv);
}
##Models handle the HTTP methods
- Each model must implement one or more of the REST_Method Interfaces
- Model names are pluralized
class Model_REST_Users
implements REST_CORS,
REST_Method_Get,
REST_Method_Post {
###Each HTTP method is handled by the corresponding Interface method
/**
* Cross-Origin Resource Sharing
*/
public function rest_cors(Rest $rest)
{
$origin = $rest->request()->headers('Origin');
if (in_array($origin, self::$origin))
{
$rest->cors(array('origin' => $origin, 'creds' => 'true'));
}
}
public function rest_options(Rest $rest)
{
$rest->send_code(200);
}
public function rest_get(Rest $rest)
{
$data = Session::instance()->get('rest_test_data', $this->_data);
$id = $rest->param('id');
if ( ! empty($id))
{
if ( ! isset($data[$id]))
{
$rest->send_code(404); //Not Found
}
return $data[$id];
}
else
{
return $data;
}
}
public function rest_put(Rest $rest)
{
$id = $rest->param('id');
if ( ! empty($id))
{
$data = Session::instance()->get('rest_test_data', $this->_data);
$data[$id] = $rest->body('json', TRUE);
Session::instance()->set('rest_test_data', $data);
return $data[$id];
}
else
{
$rest->send_code(403); //Forbidden
}
}
public function rest_post(Rest $rest)
{
$data = Session::instance()->get('rest_test_data', $this->_data);
$post = $rest->post();
if (empty($post))
{
$post = $rest->body('json', TRUE);
}
$data[] = $post;
Session::instance()->set('rest_test_data', $data);
$rest->send_created(count($data)+1);
}
public function rest_delete(Rest $rest)
{
$id = $rest->param('id');
$data = Session::instance()->get('rest_test_data', $this->_data);
if (isset($data[$id]))
{
unset($data[$id]);
Session::instance()->set('rest_test_data', $data);
}
$rest->send_code(204);
}