171 lines
5.6 KiB
Markdown
171 lines
5.6 KiB
Markdown
WellRESTed
|
|
==========
|
|
|
|
WellRESTed provides classes to help you create RESTful APIs and work with HTTP requests and responses.
|
|
|
|
|
|
|
|
Requirements
|
|
------------
|
|
|
|
- PHP 5.3
|
|
- [Composer](http://getcomposer.org/) for autoloading
|
|
- [PHP cURL](http://php.net/manual/en/book.curl.php) for making requests
|
|
|
|
|
|
|
|
Install
|
|
-------
|
|
|
|
Add an entry for "pjdietz/wellrested" to your composer.json file's **require** property. If you are not already using Composer, create a file in your project called **composer.json** with the following content:
|
|
|
|
```json
|
|
{
|
|
"require": {
|
|
"pjdietz/wellrested": "1.*"
|
|
}
|
|
}
|
|
```
|
|
|
|
Use Composer to download and install WellRESTed. Run these commands from the directory containing the composer.json file.
|
|
|
|
```bash
|
|
$ curl -s https://getcomposer.org/installer | php
|
|
$ php composer.phar install
|
|
```
|
|
|
|
You can now use WellRESTed by including the autoload.php file generated by Composer. (vendor/autoload.php)
|
|
|
|
|
|
|
|
Examples
|
|
--------
|
|
|
|
### Routing
|
|
|
|
WellRESTed's primary goal is to facilitate mapping of URIs to classes that will provide or accept representations. To do this, create a Router instance and load it up with some Routes. Each Route is simply a mapping of a URI pattern to a classname. The classname represents the Handler class which the router will dispatch at the time it recieves a request for the given URI. The handlers are never loaded until they are needed.
|
|
|
|
Here's an example of a Router that will handle two URIs:
|
|
|
|
```php
|
|
// Build the router.
|
|
$myRouter = new Router();
|
|
$myRouter->addRoute(Route::newFromUriTemplate('/things/', 'ThingCollectionHandler'));
|
|
$myRouter->addRoute(Route::newFromUriTemplate('/things/{id}', 'ThingItemHandler'));
|
|
|
|
// Determine and output the response.
|
|
$response = $router->getResponse();
|
|
$response->respond();
|
|
```
|
|
|
|
When you create your Handler subclass, you will provide a method for each HTTP verb you would like the endpoint to support. For example, if /things/ should support GET, you would override the get() method. For POST, post(), etc.
|
|
|
|
If your endpoint should reject particular verbs, no worries. The Handler base class defines the default verb-handling methods to respond with a 405 Method Not Allowed status.
|
|
|
|
Here's a simple Handler that matches the first endpoint, /things/.
|
|
|
|
```php
|
|
class ThingCollectionHandler extends \pjdietz\WellRESTed\Handler
|
|
{
|
|
protected function get()
|
|
{
|
|
// Read some things from the database, cache, whatever.
|
|
// ...
|
|
|
|
// Set the values for the instance's reponse member. This what the
|
|
// Router will eventually use to output a response to the client.
|
|
$this->response->statusCode = 200;
|
|
$this->response->setHeader('Content-Type', 'application/json');
|
|
$this->response->body = json_encode($data);
|
|
}
|
|
|
|
protected function post()
|
|
{
|
|
// Read from the instance's request member and store a new Thing.
|
|
// ...
|
|
|
|
// Build a reponse to send to the client.
|
|
$this->response->statusCode = 201;
|
|
$this->response->body = 'You added a thing!';
|
|
}
|
|
}
|
|
```
|
|
|
|
This Handler works with the second endpoint, /things/{id}. The pattern for this endpoing has a variable in it ({id}). The Handler can access path variables through its args member, which is an associative array of variable from the URI.
|
|
|
|
```php
|
|
class ThingItemHandler extends \pjdietz\WellRESTed\Handler
|
|
{
|
|
protected function get()
|
|
{
|
|
// Lookup a Thing based on $this->args['id']
|
|
// ...
|
|
|
|
if ($thing) {
|
|
// The Thing exists! Let's output a representation.
|
|
$this->response->statusCode = 200;
|
|
$this->response->setHeader('Content-Type', 'application/json');
|
|
$this->response->body = json_encode($thing);
|
|
} else {
|
|
// The ID did not match anything.
|
|
$this->response->statusCode = 404;
|
|
$this->response->setHeader('Content-Type', 'text/plain');
|
|
$this->response->body = 'No thing with id ' . $this->args['id'];
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Requests and Responses
|
|
|
|
You've already seen a Response in use in the examples above. You can also use Responses outside of Handlers. Let's take a look at creating a new Response, setting a headers, supplying the body, and outputting.
|
|
|
|
```php
|
|
$resp = new \pjdietz\WellRESTed\Response();
|
|
$resp->statusCode = 200;
|
|
$resp->setHeader('Content-type', 'text/plain');
|
|
$resp->body = 'Hello world!';
|
|
$resp->respond();
|
|
exit;
|
|
```
|
|
|
|
The Request class goes hand-in-hand with the Response class. Again, this is used in the Handler class to read the information from the request being handled. From outside the context of a Handler, you can also use the Request class to read info for the request sent to the server.
|
|
|
|
```php
|
|
$rqst = \pjdietz\WellRESTed\Request::getRequest();
|
|
|
|
if ($rqst->method === 'PUT') {
|
|
$obj = json_decode($rqst->body);
|
|
// Do something with the JSON sent as the message body.
|
|
}
|
|
```
|
|
|
|
The Request class can also make a request to another server and provide the response as a Respones object. (This feature requires [PHP cURL](http://php.net/manual/en/book.curl.php).)
|
|
|
|
```php
|
|
// Prepare a request.
|
|
$rqst = new \pjdietz\WellRESTed\Request();
|
|
$rqst->uri = 'http://my.api.local/resources/';
|
|
$rqst->method = 'POST';
|
|
$rqst->body = json_encode($newResource);
|
|
|
|
// Make the request.
|
|
$resp = $rqst->request();
|
|
|
|
// Read the response.
|
|
if ($resp->statusCode === 201) {
|
|
// The new resource was created.
|
|
$newResource = json_decode($resp->body);
|
|
}
|
|
```
|
|
|
|
More Examples
|
|
---------------
|
|
|
|
For more examples, see the project [pjdietz/wellrested-samples](https://github.com/pjdietz/wellrested-samples).
|
|
|
|
|
|
Copyright and License
|
|
---------------------
|
|
Copyright © 2013 by PJ Dietz
|
|
Licensed under the [MIT license](http://opensource.org/licenses/MIT) |