This library allows you to quickly/simply generate an API for your application by annotating your entities into RESTful resources.
You can also use PHP, Yaml or JSON to configure your entities. It comes shipped with it's own internal router, and can be used standalone or alongside your existing framework stack.
Routes are mapped to either a default or customised service action that takes care of handling requests.
Already using Doctrine's Object Relational Mapper and want to create a RESTful API? Drest can help you get up and running in a matter of minutes.
With some really simple configurations you can turn any one of your entities into a functioning REST endpoint.
@Drest\Resource( routes={ @Drest\Route( name="get_user", route_pattern="/user/:id", verbs={"GET"} )})
[GET] http://myapplication.com/api/user/123
By using an expose setting you can determine what data you want your users to see, and what they're allowed to update / create. Don't swamp your API consumers bandwidth by throwing data at them they don't need. Let them choose what data they want from the exposable set.
// Set exactly what fields you want to expose @Drest\Route( expose={"username", "profile" : {"id", "lastname", "addresses" : {"address"}}, "phone_numbers"} ) // or let the client choose $config->setExposeRequestOption(Configuration::EXPOSE_REQUEST_PARAM_GET, 'expose'); [GET] http://myapplication.com/api/user/123?expose=username|profile[id, lastname] // Also you can set a specific maximum depth you want to expose - (uses doctrines relations) $config->setExposureDepth(3);
Drest comes with a handy client tool (wrapped around guzzle) that allows your users to operate solely on PHP data objects. Classes tailored to the data you want to expose (or allow for update) from your drest routes are generated via a CLI tool. Users can then operate directly on these, taking away the possibility of getting their XML or JSON syntax incorrect. They simply create a data object, and send it.
--------------------------------CLI TOOL EXAMPLE------------------------------------------ // Generate data classes to interact with php drest-client.php classes:generate --dest-path="/path/for/SomeApi" --namespace="SomeApi" http://yourapi.endpoint Generating client classes.... Successfully wrote client class "/path/for/SomeApi/Entities/Address.php" Successfully wrote client class "/path/for/SomeApi/Entities/Profile.php" Successfully wrote client class "/path/for/SomeApi/Entities/PhoneNumber.php" Successfully wrote client class "/path/for/SomeApi/Entities/User.php" Client classes have been successfully generated at "/path/for/SomeApi" --------------------------------POST EXAMPLE------------------------------------------ // Your users can then start operating on them using the client tool $client = new Drest\Client('http://yourapi.endpoint', 'Json'); $user = SomeApi\Entities\User::create() ->setEmailAddress('hello@somewhere.com') ->setUsername('leedavis81') ->setProfile(SomeApi\Entities\Profile::create() ->setFirstname('lee') ->setLastname('davis')) ->addPhoneNumbers(array( SomeApi\Entities\PhoneNumber::create()->setNumber('02087888888'), SomeApi\Entities\PhoneNumber::create()->setNumber('07515788888'))) ->addPhoneNumber(SomeApi\Entities\PhoneNumber::create()->setNumber('07953788888')); try { $response = $client->post('/user', $user); if (($location = $response->getHttpHeader('Location')) !== null) { echo 'The resource was created at: ' . $location; } } catch (\Drest\Error\ErrorException $e) { echo $e->getErrorDocument()->render(); } --------------------------------GET EXAMPLE------------------------------------------ // They don't ever have to worry about building parsers for your data, the representations handle that for them. $response = $client->get('user/85'); // echo the Json or Xml response echo $response->getRepresentation(); // get it all in a nice tidy array $data = $response->getRepresentation()->toArray();
Data can be represented in any number of ways, you get to control how your data is handled by enabling the representations you would like to use. In future it's likely drest with leverage further "standards conforming" data types such as JSON/XML-HAL.
// Set the default representations to be used $config->setDefaultRepresentations(array('Json', 'Xml')); // Or only allow certain representations per resource @Drest\Resource( representations={"Json"} ..... )
As well as giving you complete access to a request object, drest will automatically determine the media type to be used and build a corresponding representation class for you to work with. Want to use a HTTP header, a ".json" file extension, a "format" parameter or a combination of many to determine the media type? Drest makes it simple.
// Determine the requested media type by reading: $drestConfig->setDetectContentOptions(array( Configuration::DETECT_CONTENT_HEADER => 'Accept', // An HTTP Header called "Accept" Configuration::DETECT_CONTENT_EXTENSION => true, // A dot extension on the URL (eg .json) Configuration::DETECT_CONTENT_PARAM => 'format' // A parameter parsed called "format" (eg format=xml) ));
Drest comes with request / response adapter objects to interact with. By default these are adapted from symfony components but if you already have these object, then you can use them instead. Also if you've already have your API setup in a fully routed MVC environment, you can still instruct drest to dispatch a route by name and have it update your response object. See here for more information.
// Dispatch from an application endpoint (index.php) echo $dm->dispatch(); // Or from within a controller in your framework $updatedResponseObject = $dm->dispatch($myZf2RequestObject, $mySym2ResponseObject); // Or call an exact route by name (bypasses routing) $updatedResponseObject = $dm->dispatch(null, $myResponseObject, 'Entities\User::get_users');
Drest comes with a number of default behaviours to handle requests. These defaults will operate with your entity manager to fetch / persist / update entities depending on the HTTP verb and configurations used. However these behaviours are not set in stone, drest is extensible so you can easily create and inject your own custom behaviour.
// Note that the full namespace (if applicable) to the custom plugin class must be provided in the action. // You will need to include your custom class files, or set them up an autoloader. @Drest\Resource( routes={ @Drest\Route( name="get_user", routePattern="/user/:id+", verbs={"GET"}, action="Action\Custom" )}) namespace Action; class Custom extends \Drest\Service\Action\AbstractAction { /* * From here you'll have access to the following objects via the service property. ie $this->service->get* * * @var \Doctrine\ORM\EntityManager $em - Doctrine Entity Manager * @var \Drest\Manager $dm - Drest Manager * @var \Drest\Request $request - Drest Request Object * @var \Drest\Response $response - Drest Response Object * @var \Drest\Mapping\RouteMetaData $route - The mathced route * @var \Drest\Representation\AbstractRepresentation $representation - The pre-determined media representation */ public function execute() { // .. execute my own logic, return a custom result set .. return ResultSet::create(array('name' => 'lee', 'email' => 'lee@somedomain.com'), 'user'); } }