Save entities to a REST API instead of DB using Doctrine 2

前端 未结 6 681
半阙折子戏
半阙折子戏 2021-02-02 10:00

This is related to my other question: Persisting entities using a REST API.

For a project in Symfony2 I need to be able to persist entities using an remote (third-pa

相关标签:
6条回答
  • 2021-02-02 10:07

    DoctrineRestDriver is exactly doing what you are looking for. https://github.com/CircleOfNice/DoctrineRestDriver

    Configure Doctrine:

    doctrine: dbal: driver_class: "Circle\\DoctrineRestDriver\\Driver" host: "http://www.your-url.com/api" port: 80 user: "Circle" password: "CantRenember"

    Build entity:

    /**
     * This annotation marks the class as managed entity:
     *
     * @ORM\Entity
     *
     * You can either only use a resource name or the whole url of
     * the resource to define your target. In the first case the target 
     * url will consist of the host, configured in your options and the 
     * given name. In the second one your argument is used as it is.
     * Important: The resource name must begin with its protocol.
     *
     * @ORM\Table("products|http://www.yourSite.com/api/products")
     */
    class Product {
    
        /**
         * @ORM\Column(type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        private $id;
    
        /**
         * @ORM\Column(type="string", length=100)
         */
        private $name;
    
        public function getId() {
            return $this->id;
        }
    
        public function setName($name) {
            $this->name = $name;
            return $this;
        }
    
        public function getName() {
            return $this->name;
        }
    }
    

    Let's assume we have used the value http://www.yourSite.com/api/products for the product entity's @Table annotation.

    Controller:

    <?php
    
    namespace CircleBundle\Controller;
    
    use Symfony\Bundle\FrameworkBundle\Controller\Controller;
    use Symfony\HttpFoundation\Response;
    
    class UserController extends Controller {
    
        /**
         * Sends the following request to the API:
         * POST http://www.yourSite.com/api/products HTTP/1.1
         * {"name": "Circle"}
         *
         * Let's assume the API responded with:
         * HTTP/1.1 200 OK
         * {"id": 1, "name": "Circle"}
         *
         * Response body is "1"
         */
        public function createAction() {
            $em     = $this->getDoctrine()->getManager();
            $entity = new CircleBundle\Entity\Product();
            $entity->setName('Circle');
            $em->persist($entity);
            $em->flush();
    
            return new Response($entity->getId());
        }
    
        /**
         * Sends the following request to the API by default:
         * GET http://www.yourSite.com/api/products/1 HTTP/1.1
         *
         * which might respond with:
         * HTTP/1.1 200 OK
         * {"id": 1, "name": "Circle"}
         *
         * Response body is "Circle"
         */
        public function readAction($id = 1) {
            $em     = $this->getDoctrine()->getManager();
            $entity = $em->find('CircleBundle\Entity\Product', $id);
    
            return new Response($entity->getName());
        }
    
        /**
         * Sends the following request to the API:
         * GET http://www.yourSite.com/api/products HTTP/1.1
         *
         * Example response:
         * HTTP/1.1 200 OK
         * [{"id": 1, "name": "Circle"}]
         *
         * Response body is "Circle"
         */
        public function readAllAction() {
            $em       = $this->getDoctrine()->getManager();
            $entities = $em->getRepository('CircleBundle\Entity\Product')->findAll();
    
            return new Response($entities->first()->getName());
        }
    
        /**
         * After sending a GET request (readAction) it sends the following
         * request to the API by default:
         * PUT http://www.yourSite.com/api/products/1 HTTP/1.1
         * {"name": "myName"}
         *
         * Let's assume the API responded the GET request with:
         * HTTP/1.1 200 OK
         * {"id": 1, "name": "Circle"}
         *
         * and the PUT request with:
         * HTTP/1.1 200 OK
         * {"id": 1, "name": "myName"}
         *
         * Then the response body is "myName"
         */
        public function updateAction($id = 1) {
            $em     = $this->getDoctrine()->getManager();
            $entity = $em->find('CircleBundle\Entity\Product', $id);
            $entity->setName('myName');
            $em->flush();
    
            return new Response($entity->getName());
        }
    
        /**
         * After sending a GET request (readAction) it sends the following
         * request to the API by default:
         * DELETE http://www.yourSite.com/api/products/1 HTTP/1.1
         *
         * If the response is:
         * HTTP/1.1 204 No Content
         *
         * the response body is ""
         */
        public function deleteAction($id = 1) {
            $em     = $this->getDoctrine()->getManager();
            $entity = $em->find('CircleBundle\Entity\Product', $id);
            $em->remove($entity);
            $em->flush();
    
            return new Response();
        }
    }
    

    You can even use DQL or native queries.

    0 讨论(0)
  • 2021-02-02 10:08

    As a ready-to-use solution wasn't available, I decided to write my own. I called it RAPL. It's heavily inspired by Doctrine's ORM (in fact, it uses many of the interfaces provided by Doctrine Common).

    Using RAPL I can simply write a small YAML file to configure the mapping between my entities and the web service, allowing me to persist/retrieve entities using the custom EntityManager.

    0 讨论(0)
  • 2021-02-02 10:12

    I think you are in not right way.
    I'm not ready to dig into the documentation now, but I understand doctrine stack as:

    ORM -> DQL (doctrine query language) ->dbal ->Some database sql

    And point for implementation you feature in DBAL as custom database driver.

    I think create common REST-Driver realy interesting feature and it will do easy integration with third-party services.

    0 讨论(0)
  • 2021-02-02 10:12

    I'm not sure, but you can try to use lifecycle callback events for entities to perform persisting logic via REST.

    0 讨论(0)
  • 2021-02-02 10:20

    You might use https://github.com/doctrine/rest to build a REST client, which talks to the target server. The essential part here is the mapping from entity (local) to REST API (target).

    In short: Doctrine2 (local DB) -> Rest client (entity to rest mapping) -> Request (target server)

    Doctrine/Rest provides also the other way around: a Doctrine Rest Server, to expose your local entities via REST (requests to your server). But thats not what you are looking for.

    0 讨论(0)
  • 2021-02-02 10:26

    I wanted to do a similar thing, so I built this library to help expose doctrine entities as RESTful resources. It has a fair amount of features, and allows you to define exactly what you want to have exposed via both pull (GET) and push (POST/PUT/PATCH) methods.

    http://leedavis81.github.io/drest/

    https://github.com/leedavis81/drest

    Hope it helps

    0 讨论(0)
提交回复
热议问题