Quickly and easily expose Doctrine entities as REST resource endpoints with the use of simple configuration with annotations, yaml, json or a PHP array.

Related tags

API drest
Overview

Drest

Dress up doctrine entities and expose them as REST resources

Build Status Code Coverage Scrutinizer Quality Score Latest Stable Version Total Downloads Dependency Status HHVM Status License

This library allows you to quickly annotate your doctrine entities into restful resources. 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.

Setting up endpoints is as easy as adding in a simple annotation to an entity

/* @Drest\Resource(
 *    routes={
 *        @Drest\Route(
 *            name="get_user",
 *            route_pattern="/user/:id",
 *            verbs={"GET"}
 * )})
 * @ORM\Table(name="user")
 * @ORM\Entity
 */
class User
{
   .......
}

// hitting [GET] http://myapplication.com/user/123 may return:

{
  "user": {
    "name": "lee",
    "email": "[email protected]"
    ... + other attributes set up to be exposed ...
  }
}

Documentation

Check out how to use drest by reading the documentation

Features

  • Quickly annotate existing Doctrine entities to become a fully functional REST resource.

  • Utilises the internal router for matching resource route patterns.

  • Specify what data you want to expose from your entities (including relations), or let the client choose!

  • Generate data objects using exposable data for your API users to consume.

  • Comes shipped with both JSON and XML representations, or you can create your own.

  • Allows media type detection from your client requests, getting you one step close to RMM level 3.

  • Use it independently from your existing framework stack, or alongside it.

  • Allows extension points so you can configure requests to your specific needs.

Comments
  • Implementation of PhpDriver, JsonDriver, YamlDriver

    Implementation of PhpDriver, JsonDriver, YamlDriver

    This is a branch off of jdrich's recently accepted pull request. Wrote some code to allow for the use of configuration files for Drest rather than annotations in the Doctrine models.

    opened by ptheberge 5
  • Removing the hard coupling between Drest and the AnnotationDriver.

    Removing the hard coupling between Drest and the AnnotationDriver.

    This removes some of the tight coupling in this aspect of the metadata parsing. The goal here is to be able to use drivers other than annotations (specifically yaml) to power Drest. Drivers for Yaml, Json, and PHP will be coming in a later commit.

    opened by jdrich 4
  • Named routes not working in standalone mode

    Named routes not working in standalone mode

    Hello Your framework looks promising, but I had some trouble getting it to work. Routes with params in them did not work correctly So something like this

     *          @Drest\Route(
     *              name="get_brand",
     *              routePattern="/brands/:id",
     *              routeConditions={"id": "\d+"},
     *              verbs={"GET"}
     *          ),
    

    and using a bootstrap like this

    <?php
    // bootstrap.php
    use Doctrine\ORM\EntityManager;
    use Drest\Configuration;
    use Drest\Event;
    
    require_once "vendor/autoload.php";
    
    // Create a simple "default" Doctrine ORM configuration for Annotations
    $isDevMode = true;
    
    // Create an example doctrine application
    $ormConfig = new \Doctrine\ORM\Configuration();
    $pathToEntities = array(__DIR__ . '/src/');
    $ORMDriver = $ormConfig->newDefaultAnnotationDriver($pathToEntities, false);
    $ormConfig->setMetadataDriverImpl($ORMDriver);
    
    // Other various configuration options..
    $ormConfig->setProxyDir(__DIR__ . '/Entities/Proxies');
    $ormConfig->setProxyNamespace('Entities\Proxies');
    $ormConfig->setAutoGenerateProxyClasses(true);
    
    
    // the connection configuration
    $dbParams = array(
        'driver'   => 'pdo_mysql',
        'user'     => 'foo',
        'password' => 'foo',
        'dbname'   => 'phpapi',
    );
    
    $em = EntityManager::create($dbParams, $ormConfig);
    
    $drestConfig = new Configuration();
    $drestConfig->setDetectContentOptions(array(
        Configuration::DETECT_CONTENT_HEADER => 'Accept',
        Configuration::DETECT_CONTENT_EXTENSION => true,
        Configuration::DETECT_CONTENT_PARAM => 'format'
    ));
    $drestConfig->setExposureDepth(3);
    $drestConfig->setExposeRequestOption(Configuration::EXPOSE_REQUEST_PARAM_GET, 'expose');
    $drestConfig->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache());
    $drestConfig->setDebugMode(true);
    $drestConfig->addPathsToConfigFiles($pathToEntities);
    // Set up event manager
    $evm = new Event\Manager();
    //$evm->addEventListener(array('preServiceAction', 'postServiceAction', 'preRouting', 'postRouting', 'preDispatch', 'postDispatch'), new MyEvents\MyEvent());
    $emr = \Drest\EntityManagerRegistry::getSimpleManagerRegistry($em);
    $drestManager = \Drest\Manager::create($emr, $drestConfig, $evm);
    echo $drestManager->dispatch();
    

    (so this uses the default HttpFoundation lib, which is installed) a call to /brands/1 would never see the param. Strangely, calling

    echo $drestManager->dispatch(null, null, "Brands::get_brand", array('id'=>1));
    

    works

    To fix this, I had to add the following line to MappingRouteMetaData.php -> matcher method

    $this->route_params = $matcher->getRouteParams();
    

    Bests

    opened by wirtsi 2
  • Zend Framework 2 Example

    Zend Framework 2 Example

    Great idea behind this project. I've tried to integrate it with ZF2 and I'm having some problems (I use modules DoctrineModule and DoctrineORMModule) and existing entities.

    I've was able to install Drest via composer and that went smooth, and further I was able to add Drest\Resources annotations so that part looks OK. Now I'm having problems with accessing the API via browser, while ZF throws a routing error.

    EDIT: I am now trying with a ZF2 module for api/Drest with one controller, which will handle api routing. I'm not sure if this is the right approach but I guess I'll find that out soon. I was actually able to get Drest router to get executed, but it throws an error: "There are no routes configured to match this request path". I'm using dispatcher like this: $drestManager->dispatch($this->getRequest(), new \Zend\Http\PhpEnvironment\Response()) Is there a way for Drest to automatically get parameters from getRequest?

    Btw, currently ZF2 router looks like this:

    'router' => array(
        'routes' => array(
            'apps' => array(
                'type' => 'Zend\Mvc\Router\Http\Literal',
                'options' => array(
                    'route'    => $root_route,
                    'defaults' => array(
                        'controller' => 'Api\Controller\Apps',
                        'action'     => 'index',
                    ),
                ),
                'may_terminate' => true,
                'child_routes' => array(
                    'default' => array(
                        'type'    => 'Segment',
                        'options' => array(
                            'route'    => '/[apps[/][:appId]]',
                            'constraints' => array(
                                'appId'     => '[0-9]+',
                            ),
                            'defaults' => array(
                            ),
                        ),
                    ),
                ),
            ),
    

    EDIT2: I was actually able to get this working in ZF2 by adding 3rd and 4th parameter to dispatch function. I was wondering if this approach is OK or is there a better more general way for doing this?

    WORKING ZF2 Controller with Drest:

        public function indexAction()
        {
            $id = (int) $this->params()->fromRoute('appId', 0);
    
            $entityManager = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default');
    
            $pathToEntities = array(__DIR__ . '/../../../../Application/src/Application/Entity');
    
            $request = $this->getRequest();
    
            $drestConfig = new \Drest\Configuration();
            $drestConfig->setDetectContentOptions(array(
                Configuration::DETECT_CONTENT_HEADER => 'Accept',
                Configuration::DETECT_CONTENT_EXTENSION => true,
                Configuration::DETECT_CONTENT_PARAM => 'format'
            ));
    
            $drestConfig->setExposureDepth(1);
            $drestConfig->setExposeRequestOption(Configuration::EXPOSE_REQUEST_PARAM_GET, 'expose');
            $drestConfig->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache());   // use a different adapter for production
            $drestConfig->setDebugMode(true);
            $drestConfig->addPathsToConfigFiles($pathToEntities);
    
            $evm = new Event\Manager();
            //$evm->addEventListener(array('preServiceAction', 'postServiceAction', 'preRouting', 'postRouting', 'preDispatch', 'postDispatch'), new MyEvents\MyEvent());
    
            $drestManager = \Drest\Manager::create($entityManager, $drestConfig, $evm);
    
            $test = new \Zend\Http\PhpEnvironment\Response();
    
            $viewModel =  new ViewModel(array(
                'data'=>$drestManager->dispatch($request, new \Zend\Http\PhpEnvironment\Response(), 'Application\Entity\Apps::get_apps', array('id' => $id)),
            ));
    
            $viewModel->setTerminal(true);
    
            return $viewModel;
        }
    

    EDIT3 - POST Request:

    I also tried to implement POST functionality with similar dispatcher than above (just didn't pass in array with id), and I didn't have that much luck here. I'm getting an error

        Requests to push data (PUT/POST/PATCH) can only be used on individual elements. Data collections cannot be pushed
    

    stack trace:

        Drest\Manager.php(310): Drest\Query\ExposeFields->configurePushRequest(NULL)
        Manager.php(211): Drest\Manager->handlePushExposureConfiguration(Object(Drest\Mapping\RouteMetaData), Object(DrestCommon\Representation\Json))
        ...
    

    Any idea what I'm doing wrong?

    opened by tad3j 2
  • DateTime isn't correctly parsed with xml formatter

    DateTime isn't correctly parsed with xml formatter

    As the subject suggests, it looks like the XML formatter doesn't correctly handle the DateTime object.

    Doctrine Column:

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="account_created_on", type="datetime", precision=0, scale=0, nullable=false, unique=false)
     */
     private $createdOn;
    
    Warning: DOMDocument::createTextNode() expects parameter 1 to be string, object given in ..\vendor\leedavis81\drest-common\src\DrestCommon\Representation\Xml.php on line 67
    
    Argument 1 passed to DOMNode::appendChild() must be an instance of DOMNode, null given, called in ..\vendor\leedavis81\drest-common\src\DrestCommon\Representation\Xml.php on line 63 and defined in C:\Users\matlab\git\website\vendor\leedavis81\drest-common\src\DrestCommon\Representation\Xml.php on line 67
    bug 
    opened by mlabrum 2
  • Annotation Driver assuming representations are set in the metadata

    Annotation Driver assuming representations are set in the metadata

    The annotation driver at line 182 assumes the representations are set in the metadata contrary to what the documentation says. It doesn't appear to fall back on the defaults set in the configuration:

    Argument 1 passed to Drest\Mapping\ClassMetaData::addRepresentations() must be of the type array, null given

    I assume simply wrapping this in a check to find out if the metadata is set or not and then falling back on default configuration would solve this issue.

    opened by carllcombs 1
  • Alternative configuration options

    Alternative configuration options

    All examples in the documentation seem to use annotations for configuring the mapping between entity and REST resource. Are there any alternative options, such as YAML / XML files, like when using Doctrine?

    Something like this:

    Acme\DemoBundle\Entity\User:
        routes:
            get_users:
                pattern:    /users
                verbs:      [GET]
                collection: true
            get_user:
                pattern:    /user/:id
                verbs:      [GET]
            update_user:
                pattern:    /user/:id
                verbs:      [PUT, PATCH]
                origin:     get_user
    

    The reason for this is that I want to keep the persistance logic seperated from my entities. My entities shouldn't know how they are going to be saved.

    Is it possible? If not, I'd like to propose this as a new feature.

    opened by nicwortel 1
  • Symfony example

    Symfony example

    I like the look of this project but I would find it really helpful to see an example of how to set it up in the context of a Symfony 2 application. Specifically, how do I register my entities as resources and how does the Symfony router interact with the Drest router?

    opened by tamlyn 1
  • Entity manager's spurious injection

    Entity manager's spurious injection

    The orm entity manager is injected into the drest manager object but may be required to determine default behaviours on a number of drest features.

    Currently the entity manager is being injected and passed around a number of function calls in ClassMetaData, RouteMetaData and ExposeFields. Implement a cleaner way of allowing access (service locator? dependency injector?)

    enhancement 
    opened by leedavis81 1
  • Origin routes are only determined if  :id has been used as the primary key

    Origin routes are only determined if :id has been used as the primary key

    Routes are grouped for the sake of option requests to return an "Allow" HTTP header with actionable verbs.

    Eg OPTIONS /user/1

    may return

    Allow: GET, PUT, PATCH

    Of the available routes in the group the "origin" route (where that resource resides) will be a GET route and will match the pattern {string}/:id. :id is hard coded in to the AnnotationDriver. This should instead be using the primary key(s) declared in the ORM annotations. This can be read from the entity managers metadata.

    Note: Origin routes are optional, "unknown" is used in push service actions if one isn't established. They can also be hard set using the "origin" property on a Route object.

    bug 
    opened by leedavis81 1
  • Separate client tools into their own library.

    Separate client tools into their own library.

    Identify shared components required for both server and client and abstract them into their own VCS. (Representations will be one).

    The end goal would be to have 3 components:

    drest (server) drest-client drest-common

    • Ensure the client only generates exceptions of a custom type "Drest\ClientException"
    enhancement 
    opened by leedavis81 1
  • Allow custom service actions to be injected/constructed upon request

    Allow custom service actions to be injected/constructed upon request

    Documentation specifies to register a custom entity against a particular route(s)..

    $customAction = new Action\Custom()
    $actionRegistry = new Drest\Service\Action\Registry();
    $actionRegistry->register(
        $customAction,
        ['Entities\User::get_user']
    );
    

    However this is poor as it means constructing every service action per request regardless of whether it's used. It would be far better to allow users to register the required class name

    opened by leedavis81 0
  • Default creation actions instantiate entity objects

    Default creation actions instantiate entity objects

    This is a problem as they (currently) have no knowledge of the construction requirements. There are a number of ways this could be be solved.

    • Provide a construction mechanism for the route
    • Disable the constructor and depend on a defined handle (would require refactoring)
    opened by leedavis81 0
Releases(1.0.5)
  • 1.0.0(Oct 23, 2015)

    Changes from BETA:

    • No longer allowed to inject the EntityManager directly. A Drest\EntityManagerRegistry must be used. A convenience method is allowed to quickly set up where only a single entity manager is needed.
    • Service actions can now hook onto the entity manager registry where ->getEntityManager() simple returns the default.
    • Service actions are no longer constructed by Drest and must be injected. They must implement AbstractAction and be registered on the service action registry object. See http://leedavis81.github.io/drest/docs/service-actions/#creating_your_own for more information
    • Removed optional support for php 5.6
    • Dropped support for php 5.3 (sorry, traits are really handy), which makes this a >= php 5.4 tool now
    • Added support for HHVM
    • Added support for php 7
    • A large number of tidy up changes
    • Pushed code coverage to 100%
    • Pushed scrutinizer quality score above 8.0
    • Removed injectRequest option, and always inject request object into a handle.
    • Add support for multiple drivers
    • Add YAML, PHP and JSON configuration drivers
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0-beta(Jul 29, 2013)

Owner
Lee Davis
Software Engineer since 2002
Lee Davis
Read and write OpenAPI 3.0.x YAML and JSON files and make the content accessible in PHP objects.

php-openapi Read and write OpenAPI 3.0.x YAML and JSON files and make the content accessible in PHP objects. It also provides a CLI tool for validatin

Carsten Brandt 399 Dec 23, 2022
Generates OpenApi specification for Laravel, Lumen or Dingo using a configuration array and cebe/php-openapi

OpenApi Generator for Laravel, Lumen and Dingo. About The openapi-gen package provides a convenient way to create OpenApi specifications for Laravel,

Jean Dormehl 5 Jan 25, 2022
This small POC aims to show how Symfony is able, natively without modifications, to use subdirectories for Entities, Repositories, controllers, views…

POC - Using Sub Directories in a Symfony Project This small POC aims to show how Symfony is able, natively without modifications, to use subdirectorie

Yoan Bernabeu 2 May 12, 2022
A Symfony bundle that provides #StandWithUkraine banner and has some built-in features to block access to your resource for Russian-speaking users.

StandWithUkraineBundle На русском? Смотри README.ru.md This bundle provides a built-in StandWithUkraine banner for your Symfony application and has so

Victor Bocharsky 10 Nov 12, 2022
Qiniu Resource (Cloud) Storage SDK for PHP

Qiniu Cloud SDK for PHP 安装 推荐使用 composer 进行安装。可以使用 composer.json 声明依赖,或者运行下面的命令。SDK 包已经放到这里 qiniu/php-sdk 。 $ composer require qiniu/php-sdk 直接下载安装,SD

Qiniu Cloud 804 Dec 19, 2022
Adds CORS (Cross-Origin Resource Sharing) headers support in your Laravel application

CORS Middleware for Laravel Implements https://github.com/asm89/stack-cors for Laravel About The laravel-cors package allows you to send Cross-Origin

Fruitcake 6.2k Jan 8, 2023
CORS (Cross-Origin Resource Sharing) for your Symfony/Laravel requests

CORS for PHP (using the Symfony HttpFoundation) Library and middleware enabling cross-origin resource sharing for your http-{foundation,kernel} using

Fruitcake 91 Dec 22, 2022
Simple and effective multi-format Web API Server to host your PHP API as Pragmatic REST and / or RESTful API

Luracast Restler ![Gitter](https://badges.gitter.im/Join Chat.svg) Version 3.0 Release Candidate 5 Restler is a simple and effective multi-format Web

Luracast 1.4k Dec 14, 2022
Doctrine-like fixtures integration for Shopware 6.

Shopware 6 Fixtures Did you ever want to create and load Doctrine-like fixtures in your Shopware 6 plugin? Look no further! This plugin provides an ul

Familiy Office 0 Oct 29, 2021
This project lists all the mandatory steps I recommend to build a Website using Symfony, Twig, Doctrine.

{% raw %} <-- keep this for Jekyll to fully bypass this documents, because of the Twig tags. Symfony Website Checklist ?? Summary~~~~ Elevator pitch P

William Pinaud 6 Aug 31, 2022
Appwrite configuration for Cloud Function runtimes settings 🌩

Appwrite Runtimes Appwrite repository for Cloud Function runtimes that contains the configurations and tests for all of the Appwrite runtime environme

Appwrite 39 Nov 22, 2022
A simple, extensible REST API framework for PHP

Note: This framework is not stable yet. Introduction Aphiria is a suite of small, decoupled PHP libraries that make up a REST API framework. It simpli

Aphiria 119 Dec 23, 2022
Simple PHP API client for tube-hosting.com rest API

Tube-Hosting API PHP client Explanation This PHP library is a simple api wrapper/client for the tube-hosting.com api. It is based on the provided docu

null 4 Sep 12, 2022
Create REST and GraphQL APIs, scaffold Jamstack webapps, stream changes in real-time.

API Platform is a next-generation web framework designed to easily create API-first projects without compromising extensibility and flexibility: Desig

API Platform 7.7k Jan 7, 2023
Joy VoyagerApi module adds REST Api end points to Voyager with Passport and Swagger support.

Joy VoyagerApi This Laravel/Voyager module adds REST Api with Passport and Swagger support to Voyager. By ?? Ramakant Gangwar. Prerequisites Composer

Ramakant Gangwar 14 Dec 12, 2022
Proposed REST and GraphQL APIs for Concrete CMS 9.2+

Concrete CMS API Proposal 2022 Hello there! This is a package for Concrete CMS (9.1.1+) that adds a proposed REST API. This API is reasonably comprehe

Concrete CMS 5 Aug 11, 2022
The efficient and elegant JSON:API 1.1 server library for PHP

Woohoo Labs. Yin Woohoo Labs. Yin is a PHP framework which helps you to build beautifully crafted JSON:APIs. Table of Contents Introduction Features W

Woohoo Labs. 237 Nov 28, 2022
The efficient and elegant, PSR-7 compliant JSON:API 1.1 client library for PHP

Woohoo Labs. Yang Woohoo Labs. Yang is a PHP framework which helps you to communicate with JSON:API servers more easily. Table of Contents Introductio

Woohoo Labs. 160 Oct 16, 2022
Single file PHP script that adds a REST API to a SQL database

PHP-CRUD-API Single file PHP script that adds a REST API to a MySQL/MariaDB, PostgreSQL, SQL Server or SQLite database. NB: This is the TreeQL referen

Maurits van der Schee 3.2k Jan 8, 2023