Zend框架中的其他应用程序2

时间:2014-01-15 07:34:50

标签: rest zend-framework2

我正在开发一个使用Zend框架2实现的Web应用程序,可以通过浏览器和apis访问人类用户。

一开始,我计划为api访问编写一个额外的Rest控制器,但由于apis和人类用户在控制器中使用相同的功能,我的apis目前只是发送他们的消息(作为POST请求)非静止控制器也被人类使用。

我想知道真正的休息控制器的实现是否比我目前的方法有任何优势。谢谢。

2 个答案:

答案 0 :(得分:3)

听起来您只是进行远程调用以形成操作,使它们同时满足提交和API调用。以下是一些注意事项:

  1. 安全性(身份验证,验证等)

    如果您正确保护您的网站,那些表单操作应该在某些身份验证服务的后面,其中访问由用户登录时创建的会话/ cookie数据授予(身份验证是持久的)。因此,您还需要API调用来处理cookie。如果您只是为API调用提供单独的端点,那么维护您的应用程序会更容易。然后,您可以使用单独的身份验证服务,例如使用令牌等无状态身份验证方法,这在RESTful API中非常常见。

    同样,通过API调用以及哪些操作不允许执行哪些操作更容易。最好始终确保提交针对CSRF攻击的表单提交。相反,API调用需要能够从远程源访问您的端点。因此,为API调用创建单独的接口要好得多,以避免在安全性方面做出妥协。

  2. 您的数据的表示

    您提交的某些表单可能需要执行某些操作,例如重定向。在这些操作期间,您可能需要将数据写入用户会话(例如,设置将在重定向后显示的Flash消息)。通过API调用操作时,这些没有意义。

    您还需要您的网站将数据表示为特定的API调用格式(XML,JSON等)。同样,当您有两个接口时,这将更容易维护,一个用于人类,并且其他用于API客户。

  3. 这就是为什么从控制器和服务中移除尽可能多的逻辑总是明智的。这样,您的所有域逻辑都集中在一个地方,您可以为您的网站生成新的接口,如RESTful控制器,而无需重复代码。

答案 1 :(得分:2)

我不会将控制器用作服务层,因为它会相互耦合到不同的接口。有两种方法可以解决这个问题。首先是使用RESTful接口创建客户端前端,另一个是将控制器逻辑卸载到可重用服务。

如果你选择第一个选项,你“只”拥有一个RESTful控制器而没有“人类”控制器。你的api使用REST接口,对于html版本你使用的是angular.js,backbone.js或ember.js。这些工具可以很好地与REST api后端一起加载页面,并且可以节省开发时间,因为您需要编写一次控制器。

第二种选择是将大部分逻辑卸载到服务层。这有助于使您的控制器变得苗条。这是我主要使用的方法。我有一个子名称空间“Api”和“Web”(如MyModule\Controller\Api\FooController)并且完全分离。路由不同,界面不同。 RESTful控制器将REST参数应用于get(),getList()和create()等方法,Web控制器按1:1映射到页面(viewAction(),editAction()等)。

两者都使用相同的服务,因此代码重用最大化。博客文章控制器的这种服务的一个例子就是这个(使用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)
    {
        //
    }
}

这些服务既可以用于“人”控制器,也可以用于RESTful控制器。是的,您可能会有一些代码重复,但对于服务,您大多删除此重复。如果你留下了一些重复的代码,你总是要考虑:

  1. 如果将两个对象分离,那么轻微的代码重复并不令人担忧
  2. 用于共同目标的多个地方使用的代码可以抽象为控制器插件