【发布时间】:2012-05-08 16:54:02
【问题描述】:
我们最近开始使用 Doctrine 2.2 和 Zend Framework 2 的部分内容,以改进组织、减少重复等。今天,我开始提出实现服务层以充当我们的控制器和 Doctrine 实体之间的中介的想法。
目前,我们的大部分逻辑都驻留在控制器中。此外,我们使用操作助手来测试某些权限;然而,在实现 Zend\Di 之后,我想出了一个新方法。我开始创建实体特定的服务模型,它使用 Zend\Di 注入一个 EntityManager 实例,以及当前用户的权限。
控制器代码如下:
class Project_DeleteController extends Webjawns_Controller_Action
{
public function init()
{
$this->_initJsonContext();
}
public function indexAction()
{
$response = $this->_getAjaxResponse();
$auditId = (int) $this->_getParam('audit_id');
if (!$auditId) {
throw new DomainException('Audit ID required');
}
/* @var $auditService Service\Audit */
$auditService = $this->getDependencyInjector()->get('Service\Audit');
try {
$auditService->delete($auditId);
$response->setStatusSuccess();
} catch (Webjawns\Exception\SecurityException $e) {
$this->_noAuth();
} catch (Webjawns\Exception\Exception $e) {
$response->setStatusFailure($e->getMessage());
}
$response->sendResponse();
}
}
以及我们的服务层之一的示例。构造函数有两个参数——一个是 EntityManager,另一个是 Entity\UserAccess 对象——由 Zend\Di 注入。
namespace Service;
use Webjawns\Service\Doctrine,
Webjawns\Exception;
class Audit extends AbstractService
{
public function delete($auditId)
{
// Only account admins can delete audits
if (\Webjawns_Acl::ROLE_ACCT_ADMIN != $this->getUserAccess()->getAccessRole()) {
throw new Exception\SecurityException('Only account administrators can delete audits');
}
$audit = $this->get($auditId);
if ($audit->getAuditStatus() !== \Entity\Audit::STATUS_IN_PROGRESS) {
throw new Exception\DomainException('Audits cannot be deleted once submitted for review');
}
$em = $this->getEntityManager();
$em->remove($audit);
$em->flush();
}
/**
* @param integer $auditId
* @return \Entity\Audit
*/
public function get($auditId)
{
/* @var $audit \Entity\Audit */
$audit = $this->getEntityManager()->find('Entity\Audit', $auditId);
if (null === $audit) {
throw new Exception\DomainException('Audit not found');
}
if ($audit->getAccount()->getAccountId() != $this->getUserAccess()->getAccount()->getAccountId()) {
throw new Exception\SecurityException('User and audit accounts do not match');
}
return $audit;
}
}
- 这是否适合用于我们要完成的任务?
- 在发布的服务层中进行权限验证是一种好的做法吗?
- 据我了解,视图逻辑仍然驻留在控制器中,从而使模型可以灵活地用于各种上下文(JSON、XML、HTML 等)。想法?
到目前为止,我对这种工作方式感到满意,但如果有人看到我们这样做的任何缺点,请发表您的想法。
【问题讨论】:
-
只是我的两便士认证。我不相信有正确的方法和错误的方法,但是,我开始将身份验证放入服务层,然后将其移至我的控制器中。我的理由是服务层是我的内部 API,我应该使用我的控制器层向世界公开它,因此它应该决定谁可以访问什么。此外,如果我想构建任何内部工具/脚本等,我不需要在它们中构建身份验证来使用我的服务层。
-
注意不要混淆身份验证和访问控制。在将任何域类带入图片之前,身份验证可以(应该?)进入模块。只有在您建立了用户身份之后。示例:如果 (!$authService->hasIdentity()) 在您的域服务模型中。
-
@JamieSutherland:我不同意。服务定义业务逻辑;控制器是请求和相应业务逻辑之间的桥梁。例如,您可能只有一个用于订购产品的服务,但您可能有多个用于 HTTP 请求、API 请求等的控制器。如果您担心 ACL 会请求特定(例如,通过 HTTP,您可能期望用户会话,而您期望 API 请求的密钥),请概括您的 ACL 实现以允许这样做。跨度>
标签: php model-view-controller doctrine-orm zend-framework2 service-layer