Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I am currently working on a personal project and i have implemented service layers. I prefer to store services independently so i don't have a large library within one file. Brief Example of File Structure below
services/
user/
authentication
login
logout
registration
news/
articles
article
I know a few people who implement a userService class that will group everything that i currently have. I prefer my method to save time in future edits + i have a lot of user services/functionality so its better to keep it separate. I was recently advised to implement a userService class in the root of my services folder and use it to call/execute the services needed within the application. Below is my example/understanding
<?php
/**
*-----------------------------------------------------------------
*
* USER SERVICE CLASS
*
* Simplifies Service Usage Within Application
*
*/
namespace Service;
use \Helper\ServiceAccess;
class UserService extends ServiceAccess {
// Define Service Prefix Key
protected $prefix = 'user/';
}
///////////////////////////////////////////////////////////////////
// Separate File ( Helper Function )
///////////////////////////////////////////////////////////////////
/**
*-----------------------------------------------------------------
*
* SERVICE ACCESS LAYER
*
* Used to Simplify the Process of Executing Services, and Grouping
* Alerts For Simple Front-end Error Messages
*
*/
namespace Helper;
class ServiceAccess extends Base {
public $dependencies = ['factory'];
// Default Service Prefix
protected $prefix = '';
// Alert Container Used By Controller to Set UI Alerts
protected $alerts = [
'errors' => [],
'info' => [],
'success' => [],
'warning' => []
];
/**
* Service Execution Method
*
* Used Within Parent Service Classes Such as UserServices
* TournamentServices
* etc.
*
* #param string $key Refers to the Factory Key ( Excluding Prefix )
* #param mixed $input Any Type of Input to Be Passed to Execute Method of Child Service
*/
public function execute($key, $input = []) {
// Create Service Class Via Factory - Call Execute Method Within Service
$service = $this->factory->make($this->prefix . $key);
$execute = $service->execute($input);
// Get & Merge Alerts From Service
$this->setAlerts($service);
// Return Result From Service Execution
return $execute;
}
/**
* Set Alerts
*
* #param array $alerts Front-End User Alerts Defined By Services
*/
private function setAlerts($service) {
$this->alerts = [
'errors' => array_merge($this->alerts['errors'], (array) $service->get('errors')),
'info' => array_merge($this->alerts['info'], (array) $service->get('info')),
'success' => array_merge($this->alerts['success'], (array) $service->get('success')),
'warning' => array_merge($this->alerts['warning'], (array) $service->get('warning'))
];
}
}
CONTROLLER EXAMPLE
<?php
/**
*-----------------------------------------------------------------
*
* LOGIN CONTROLLER
*
*/
namespace Controller\www;
use \Helper\Controller;
class Login extends Controller {
public $dependencies = ['arena', 'login', 'notification', 'site', 'userservice'];
/**
* Login
*
* Login Runs Through Various Checks Including If User is Banned, Account is Locked,
* or Forgot Password Request Is Active. Then the Entered Password is Matched & if Valid
* User is Logged In
*/
public function index() {
// User Already Logged In Redirect
$this->user->get('id') ? $this->redirect->home() : '';
/**
* User Login
*
* If Successful, Login User, Redirect Home
* Else Set Error Alerts
*/
if ($this->form->post('login')) {
// Define and Sanitize Post Data
$input = $this->input->get(['username', 'password']);
// Execute Login Service Layer - Define Flash Alerts
$login = $this->userservice->execute('login', $input);
$this->alerts($this->userservice->get('alerts'));
// Redirect Home on Successful Login
$login === true ? $this->redirect->home() : '';
}
}
}
The execute method within the ServiceAccess class is what i was advised to do the rest i added for my user error handling. My questions are as follows
Why is this better than calling the services directly within the application?
It simplified the execution of the services/setting of alerts within my controllers ( turned ~15 lines of code into 4 lines within controller ) BUT i have services like user/transactions ( Handles credit/debit of user account ) and they have separate methods that need to be used. So i am wondering if it is the UserService Class or my transaction class that needs to be updated. I was thinking of defining an execution method within transaction and just passing a key within the input to define the type of transaction being used.
Is this the best route to go about accessing/implementing services within my application?
The purpose of abstraction is to manage underlying complexity. If the overall complexity of the system is reduced because of an additional layer, do it. If not, reconsider. Every layer in the architecture should have a purpose for being there. And this purpose must be communicated (documented) to the developers, otherwise everyone would just be stabbing in the dark.
A good way to plan your architecture is to draw architectural diagrams and assign roles to each layer. Each layer may be a single or a collection of classes. If you struggle to find a good, clean role for a particular layer, you may not need that layer after all.
I know you're using an MVC pattern in your architecture, but that does not constitute the entire architecture, just the broad approach. Think about the consumption and execution of your services and the various layers. Think about the layers you want in your architecture. Would a UserService class make sense in your architecture? What layer does it belong to? What is the role of that layer? Sometimes you want an additional abstraction layer to reduce duplicate code - like you seem to have achieved in your case; sometimes you simply want to do it the simple, intuitive way rather than over-complicate things.
Every architectural layer, every pattern, every abstraction can be well applied or badly abused. Does adding such a layer confuse you or other developers in the team? If it does, take it out. The application of every layer (abstraction) should be elegant and intuitive - it should make everyone else in the team go "Oh yea, this is smart." But if you end up in a situation where developers are unsure how to extend/maintain the code, it becomes counter-productive.
Without a good understanding of the intent of the entire application and the background of the developers (you), it is impossible to make a good choice or give good advice. So while I understand you're asking for a best practice - in essence, "how much abstraction should we apply in our architecture/framework?", there are really no correct answers. It depends on too many things - developer preference and even coding style included. Some would even say that MVC is the wrong thing to do on the server-side.
To conclude: I can't give you a direct "Yes" or "No" answer. And I don't think anyone can. The only advice anyone can give for an architectural framework: stay DRY but avoid over-engineering.
Related
I have two Laravel sites, a client and a server. The client connects to the server, which (among other things) provides a RESTful api for a database. While this setup may seem a bit convoluted and superfluous, it is necessary for the use-case.
How can I set up the client so that it uses the server's API to interact with resources?
For instance, the sever provides organisation models at an /organisations/{id} end point. If I wanted to display them all on the client, and provide a form for updating each organisation, is there a Laravel-esque way of doing this? Or is it something that'll end up being hand-rolled and hacky?
You have to use the http-client. Laravel provides already one, based on Guzzle.
So, in order to update something You have to create PUT route on Your Server and then just call it from Client like this:
$response = Http::put("https://YOUR.SERVER/organisations/$id", [
'name' => 'Steve',
'role' => 'Network Administrator',
]);
More info, You will find in Laravel Documentation
if you want to use the Laravel as a frontend client to consume a remote API it easy, a part the fact that you can consider the use of vue.js as your frontend in order to keep things simpler.
FRONTEND
Create the Laravel project as usual, the only difference is that you don't need to set up the database and migrations
You are going to use the normal MVC pattern here, so in your Frontend FlightController class, you will fetch the data like this.
getFlights()
{
$response = Http::get(env('API_URL') . '/flights')->json();
}
we can optionally install the package spatie/data-transfer-object
in order to convert your json data to DTO object like this:
getFlights()
{
$flights_data = Http::get(env('API_URL') . '/flights')->json();
$filghts = [];
foreach($flight_data as data)
$filghts->add(new \App\Models\Dto\FlightDto($data));
return view('flights.search-result', compact('filghts'));
}
the DTO class looks like this:
use Spatie\DataTransferObject\DataTransferObject;
class FlightDto extends DataTransferObject
{
/** #var integer|null */
public $id;
/** #var string|null */
public $flight_number;
}
The authentication is little bit tricky, refer to this question to see how you can create custom user provider.
BACKEND
Create a Laravel project, set up database and all your migrations
place all your routes in the default location api.php
Route::get('/trips', 'ApiTripsController#getFlights');
3- in the FlightsController do the following
public getFlights
{
return Flight::all() // where the Flight class is the Eloquent model
}
do not forget to provide a security layer to protect ressources from the server side
I have a Symfony application which I will like to integrate mobile money into. The problem is I cannot add PHP code to twig files and I am a complete newbie to this kind of challenge. The code reads:
<?php
require_once '/path/to/monetbil-php/monetbil.php';
// Setup Monetbil arguments
Monetbil::setAmount(500);
Monetbil::setCurrency('XAF');
Monetbil::setLocale('en'); // Display language fr or en
Monetbil::setPhone('');
Monetbil::setCountry('');
Monetbil::setItem_ref('2536');
Monetbil::setPayment_ref('d4be3535f9cb5a7aff1f84fa94e6f040');
Monetbil::setUser(12);
Monetbil::setFirst_name('KAMDEM');
Monetbil::setLast_name('Jean');
Monetbil::setEmail('jean.kamdem#email.com');
// Start a payment
// You will be redirected to the payment page
Monetbil::startPayment();
I am looking at adding this to App/Resources/Views/members/dashboard.html.twig
Twig is only ment to render your output. Put your (php) logic in your controller and/or create your own service. From your controller you will also render your Twig template with the variables you need but only to render the output that you want to show to the users.
If you're using a framework like Symfony, you shouldn't use require_once (except some exceptions). Read about autoloading and dependency injections (Symfony.com has excellent articles).
For some reason, the monetbil-php library doesn't use composer. I don't know why, but I can imagine three reasons: they don't know what it is (hello developers, it's 2017!), they hate other developers or the library hasn't been updated for years. Despite the recent commits, it looks like a very outdated library (why still supporting PHP 5.2? That's from the dark ages!). Sorry for this slightly offtopic rant, back to the question.
For now, copy the files to your project, give the file a namespace and use it in your project. I've opened an issue here because I think the developers should add a composer file if they want their users to use their library in a framework like Symfony.
The PHP code should be in your controller* since you can't use PHP in Twig and even if you could, you shouldn't. Monetbil defines business logic, so it shouldn't be in a template.
To use it in your controller:
/**
* Pay the bill
*
* #Route("/pay/{id}", name="payment")
* #Method("POST")
* #param Request $request
* #param Order $product
*
* #return JsonResponse
* #throws \Exception
*/
public function payAction(Request $request, Order $product)
{
Monetbil::setAmount(500);
//..
Monetbil::startPayment();
}
According to the comment, startPayment() will redirect, so there's nothing to return to the Twig template.
(*) Business logic in your template is considered as a bad practice, but you should prevent putting too many business logic in a controller too. If you have this example working, try to read about services so you can define the business logic in a framework-agnostic way. It makes maintaining your application (unit tests, Symfony updates, maybe switch to another framework?) easier.
I'm new in Symfony and i have a little problem.
I been searching online, couldn't find the answer to my problem.
I create API and I have two controllers(UserController, InstructorController) with similar method (addUserImage, addInstructorImage). I created abstract BaseImage(Here is saving files), InstructorImage and UserImage(here are set path). This is my controller:
/**
* #ApiDoc(
* name="addInstructorImage", section="Instructors",
* description="Add Instructor Image",
* )
*
* #Route("/instructor/{instructor}/image", name="instructors.image.add")
* #Method("POST")
*
* #param Request $request
* #param Instructor $instructor
* #View
*
* #return \FOS\RestBundle\View\View
*/
public function addInstructorImage(Request $request, Instructor $instructor)
{
$this->denyAccessUnlessGranted('edit', $instructor->getUser());
$image = new InstructorImage();
$form = $this->get('form.factory')
->createNamed('', InstructorImageType::class, $image, ['csrf_protection' => false, 'method' => 'POST']);
$form->handleRequest($request);
if ($form->isValid()) {
$image->setInstructor($instructor);
$em = $this->getDoctrine()->getManager();
$em->persist($image);
$em->flush();
return $this->view(null, Response::HTTP_NO_CONTENT);
}
return $this->view($form, Response::HTTP_BAD_REQUEST);
}
My second controller is identical.
The only difference is another object , and another form. What is the best way to optimize this code. Should I create services that adds photos or use chain handler? Maybe You have better ideas?
Thank you for your help
Short answer: Don't waste time on trying to optimize this sort of stuff.
Your method consist of 19 lines of code. It's all basic boiler plate easy to read code. I know whenever I see duplicate code I'm tempted to try and combine it somehow but what exactly would be gaining? Reducing 19 lines to maybe 15?
If I was going to change your code then I'd be tempted to move some of the business logic into it's own service. Something like:
InstructorManager::addImage($instructor,$image);
That would get rid of the entity manager boiler plate and provide a bit of abstraction. Might make it a bit easier to test though all the method is doing is setting the image and calling flush. Hardly worth the effort. Might be worth it if you have other manager type functionality to add as well. Or maybe you want to be able to add images from a console app.
Of course you may end needing to add functionality in the future. Maybe you want to notify someone when the image is changed. If you find yourself needing to modify duplicated code then you can probably justify the effort of moving common code into it's own service.
And I suppose you could create a service for your form using the container's factory capability. Especially if you had a bunch of these form to make. But again, hardly worth the effort and might even make things more difficult to maintain.
Using Symfony, I am displaying a table with some entries the user is able to select from. There is a little more complexity as this might include calling some further actions e. g. for filtering the table entries, sorting by different criteria, etc.
I have implemented the whole thing in an own bundle, let's say ChoiceTableBundle (with ChoiceTableController). Now I would like to be able to use this bundle from other bundles, sometimes with some more parametrization.
My desired workflow would then look like this:
User is currently working with Bundle OtherBundle and triggers chooseAction.
chooseAction forwards to ChoiceTableController (resp. its default entry action).
Within ChoiceTableBundle, the user is able to navigate, filter, sort, ... using the actions and routing supplied by this bundle.
When the user has made his choice, he triggers another action (like choiceFinishedAction) and the control flow returns to OtherBundle, handing over the results of the users choice.
Based on these results, OtherBundle can then continue working.
Additionally, OtherOtherBundle (and some more...) should also be able to use this workflow, possibly passing some configuration values to ChoiceTableBundle to make it behave a little different.
I have read about the "Controller as Service" pattern of Symfony 2 and IMHO it's the right approach here (if not, please tell me ;)). So I would make a service out of ChoiceTableController and use it from the other bundles. Anyway, with the workflow above in mind, I don't see a "good" way to achieve this:
How can I pass over configuration parameters to ChoiceTableBundle (resp. ChoiceTableController), if neccessary?
How can ChoiceTableBundle know from where it was called?
How can I return the results to this calling bundle?
Basic approaches could be to store the values in the session or to create an intermediate object being passed. Both do not seem particularly elegant to me. Can you please give me a shove in the right direction? Many thanks in advance!
The main question is if you really need to call your filtering / searching logic as a controller action. Do you really need to make a request?
I would say it could be also doable just by passing all the required data to a service you define.
This service you should create from the guts of your ChoiceTableBundleand let both you ChoiceTableBundle and your OtherBundle to use the extracted service.
service / library way
// register it in your service container
class FilteredDataProvider
{
/**
* #return customObjectInterface or scallar or whatever you like
*/
public function doFiltering($searchString, $order)
{
return $this->filterAndReturnData($searchString, $order)
}
}
...
class OtherBundleController extends Controller {
public function showStuffAction() {
$result = $this->container->get('filter_data_provider')
->doFiltering('text', 'ascending')
}
}
controller way
The whole thing can be accomplished with the same approach as lipp/imagine bundle uses.
Have a controller as service and call/send all the required information to that controller when you need some results, you can also send whole request.
class MyController extends Controller
{
public function indexAction()
{
// RedirectResponse object
$responeFromYourSearchFilterAction = $this->container
->get('my_search_filter_controller')
->filterSearchAction(
$this->request, // http request
'parameter1' // like search string
'parameterX' // like sorting direction
);
// do something with the response
// ..
}
}
A separate service class would be much more flexible. Also if you need other parameters or Request object you can always provide it.
Info how to declare controller as service is here:
http://symfony.com/doc/current/cookbook/controller/service.html
How liip uses it:
https://github.com/liip/LiipImagineBundle#using-the-controller-as-a-service
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-party) RESTful API. I also want to be able to retrieve entities with data from that API.
In other words, my objects are saved in the third-party database. They are not saved in my own database. Whenever I need to save data, or find data, I use their REST API.
I have been pointed to several libraries, including one made by Doctrine itself. However, none of them offers me what I'm looking for. The one made by Doctrine is the best option, but uses the Active Record pattern and doesn't offer all the sweet Doctrine 2 stuff. Don't get me wrong, I've been using Active Record implementations for a long time, but I've fallen in love with Doctrine's Data Mapper pattern now.
Ideally, I'd like to be able to use Doctrine's ORM and simply replace the database-specific part with logic that saves entities using an API call. (and of course retrieves them using that same API). This way I can save my entities using roughly the same syntax:
// current way to save $entity in database:
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
// desired way to save $entity using REST API:
// (just an example, it doesn't have to be exactly like this)
$em = $this->getDoctrine()->getManager('rest');
$em->persist($entity);
$em->flush();
Note that I'm not trying to build my own API, I'm simply trying to communicate with a third party API in order to save my entities. I'm relatively new to Doctrine, but I'm liking it so far. I really like the idea of seperating the persistence logic from the entities, but so far I can't find out how I can use that to save them using an API.
There is an article in Symfony's documentation, describing how to work with multiple Entity Managers. I'm looking for a solution similar to this, but with an entity manager that enables me to use REST instead of the DB.
I've been trying to tweak Doctrine's ORM myself, but I only end up rewriting half their code because it (seems to be) too tightly coupled to the Database-specific logic. I might be doing something stupid of course.
So my question is, is there a way to replace / override the database-specific parts of Doctrine's ORM with custom ones? Without rewriting a lot of things that should be common for all persistence methods? Has it been done before? Or is it simply not possible because Doctrine is intended for use with a database and isn't flexible enough for other uses?
My own progress
CakePHP seems to be able to do this, by letting you define a custom DataSource. This way you can save your models using an SQL database, but also using an API, sessions, etc. I want to do roughly the same, but using Doctrine instead of CakePHP.
Update 1
The actual database queries seem to be executed by the
Doctrine\ORM\Persisters\BasicEntityPersister class. There are several other xxxPersister classes, to deal with different types of inheritance. It might be possible to replace the xxxPersister classes with our own, so we can replace the DB code with REST API code.
The persister objects are created within the getEntityPersister() method of the Doctrine\ORM\UnitOfWork class. The classnames are hardcoded so we need to override Doctrine\ORM\UnitOfWork if we want to use our own persisters.
Update 2
Doctrine\ORM\UnitOfWork seems to be hardcoded into Doctrine\ORM\EntityManager, so we need to override that one as well. However, this class seems to contain some database-specific parts. For instance, it's constructor requires a Doctrine\DBAL\Connection object as parameter. Perhaps it's better to create our own EntityManger (implementing the Doctrine\Common\Persistence\ObjectManager interface), as long as that doesn't take too much time / effort.
Update 3
The database-specific code for retrieving/loading/finding objects lives in the same class as the code for persisting / deleting etc: the Doctrine\ORM\Persisters\xxxPersister classes. So if we are able to replace them with our own, in order to persist objects, we can retrieve objects as well. When you call $entityRepository->findAll(), for instance, it will return $entityRepository->findBy(array()) (because findAll() is simply an alias for findBy(array())) which will run the following code:
$persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName);
return $persister->loadAll($criteria, $orderBy, $limit, $offset);
In other words, once we get EntityManager to create the right UnitOfWork and xxxPersister objects, we will be able to use the find methods in the EntityRepository.
Update 4
I discovered that a new feature is developed for Doctrine: custom persisters (also see this). This should make it easier to use a custom persister class. I don't know yet if it will enable us to create a non-DB persister, but it looks promising. However, the last updates were in August, so I'm not sure if it's still in active development.
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.
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.
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.
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.
I'm not sure, but you can try to use lifecycle callback events for entities to perform persisting logic via REST.
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