Features:

  • Quickly annotate existing Doctrine entities to become a fully functional REST resource
    @Drest\Resource(
        routes={
            @Drest\Route(
                name="get_user",
                route_pattern="/user/:id",
                verbs={"GET"}
    )})
  • Utilises its own internal router for matching resource route patterns.
    [GET] http://myapplication.com/api/user/123
    
  • Specify what data you want to expose from your entities (including relations), or let the client choose! (see code)

    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);
  • Generate data objects for your API users to interact with. (see code)

    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();
    
    
  • Comes shipped with both JSON and XML representations, or you can create your own. (see code)

    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"}
        .....
    )
  • Allows media type detection from your client requests, getting you one step close to RMM level 3. (see code)

    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)
    ));
  • Use it independently from your existing framework stack, or alongside it. (see code)

    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');
    
    On the condition that drest request / response adapters have been created for that particular framework.
  • Allows extension points so you can configure requests to your specific needs. (see code)

    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');
        }
    }