3

I am working on a web application implemented with the Zend framework 2 that is accessible both for human users through a browser and for apis.

At the start, I planned to write an extra Rest controller for the api access, but as both the apis and the human users use the same function in the controller, my apis currently just send their messages (as POST requests) to the non-rest controller used also by the humans.

I would like to know whether the implementation of a real rest controller would have any advantages over my current approach. Thank you.

2 Answers 2

3

Sounds like you are just making remote calls to form actions, making them cater to both form submissions and API calls. Here are some considerations:

  1. Security (authentication, validation, etc)

    If you are securing your website properly, those form actions should be behind some authentication service in which access are granted by session/cookie data created upon user login (the authentication is persistent). Therefore, you would require API calls to handle cookies as well. It would be easier to maintain your application if you simply have separate endpoint for API calls. Then you could use a separate authentication service, like stateless authentication methods like using tokens, which are pretty common in RESTful APIs out there.

    Also this way, it is easier to enforce which operations are allowed through API calls and which operations are not. It is best to always secure form submissions against CSRF attacks. On the contrary, API calls necessitate the ability to access your endpoints from a remote origin. Therefore its much better to create a separate interface for API calls to avoid making compromises in security.

  2. Representation of your data

    Some of your form submissions might necessitate certain things to happen, like redirections. You might need to write data into the user session during these operations (for example, setting a flash message which will be displayed after redirection). These doesn't make sense when operating via API calls.

    You will also be needing your website to represent data into a certain format for API calls as well (XML, JSON, etc.) Again, this would be easier to maintain when you have two interfaces, one for humans, and the other for API clients.

This is why its always wise to move as much logic away from controllers and into services. This way all your domain logic is all in one place and you can spawn new interfaces to your website, like RESTful controllers, without code duplication.

Sign up to request clarification or add additional context in comments.

Comments

2

I wouldn't use a controller to be used as a service layer, as it couples to different interfaces to each other. There are two ways you can solve this. First is to make a client-side frontend using your RESTful interface, another is offloading controller logic to reusable services.

If you go with the first option, you "just" have a RESTful controller and no "human" controller. Your api uses the REST interface and for the html version you use something like angular.js, backbone.js or ember.js. These tools work well with REST api backends to load pages and it saves you development time on the backend as you need to write your controllers once.

A second option is to offload most of the logic to service layers. This helps to make your controllers slim. This is the method I use mostly. I have a subnamespace "Api" and "Web" (as MyModule\Controller\Api\FooController) and there are totally decoupled. The routing is different and the interface is different. The RESTful controllers apply the REST parameters with methods like get(), getList() and create(), the web controllers are 1:1 mapped to pages (viewAction(), editAction() and so on).

Both use the same services, so the code reuse is maximised. An example of such service for a blog post controller is this (using Doctrine):

<?php

namespace Blog\Service;

use Doctrine\Common\Persistence\ObjectManager;
use Blog\Entity\Post as PostEntity;

class Post
{
    protected $objectManager;
    protected $objectRepository;

    public function __construct(ObjectManager $objectManager)
    {
        $this->objectManager    = $objectManager;
        $this->objectRepository = $objectManager->getRepository('Blog\Entity\Post');
    }

    public function find($id)
    {
        return $this->objectRepository->find($id);
    }

    public function store(array $data)
    {
        $post = new PostEntity;
        $post->fromArray($data);

        $objectManager = $this->objectManager;
        $objectManager->persist($post);
        $objectManager->flush();
    }

    public function update(array $data, PostEntity $post)
    {
        //
    }

    public function delete(PostEntity $post)
    {
        //
    }
}

These kind of services can both be used for your "human" controllers and your RESTful controllers. Yes, you might have a little bit of code duplication, but with services you mostly remove this duplication. If you have left some duplicated code, you always have to consider:

  1. A slight amount of code duplication isn't worrisome if it decouples both objects
  2. Code used in multiple places serving a common goal can be abstracted into a controller plugin

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.