在我的 zend Framework 2 项目中,我更喜欢双层模型(映射器和模型)而不是教义,并试图使它们像教义一样工作,这样我就可以从模型(实体)访问关系数据。以下示例演示了我想要实现的目标。
class User
{
protected $userTable;
public $id;
public $name;
public function __construct($userTable)
{
$this->userTable = $userTable
}
public function getUserArticles()
{
return $this->userTable->getUserArticles($this->id);
}
}
问题是我无法在我的用户模型中注入我的用户表,因为表网关使用模型类作为数组对象原型,稍后注入该原型以创建用户表网关(映射器)。
我不想在我的模型中注入服务管理器,因为这被认为是一种不好的做法。如何在用户模型中注入用户表?可能吗?实现我想要做的事情的最佳方式是什么
您要做的是混合两种设计模式:Active Record 和 Data Mapper。
如果您看一下数据映射器模式,您将拥有同时访问模型和数据库的映射器。该模型是被动的 - 通常不调用外部资源(它是一个POPO - 普通的旧PHP对象)。
您的问题的解决方案是将相关信息注入模型,从而仅将模型保留为数据结构。
下面是 MVC 应用程序的工作方案:
控制器 - 用于输入验证和从服务检索数据
<?php
...
public function viewAction()
{
$id = (int) $this->params()->fromQuery('id');
$service = $this->getServiceLocator()->get('your-user-service-name');
$user = $service->getUser($id);
...
}
服务 - 用于执行业务逻辑;调用多个数据映射器
<?php
...
public function getUser($id)
{
// get user
$mapper = $this->getServiceLocator()->get('your-user-mapper');
$user = $mapper->getUserById($id);
// get articles
$article_mapper = $this->getServiceLocator()->get('your-article-mapper');
$user->articles = $article_mapper->getArticlesByUser($id);
return $user;
}
数据映射器 - 用于操作一种类型的域实体 - 如果您正在访问数据库,它应该与 tableGateway 组成
<?php
...
public function getUserById($id)
{
$select = $this->tableGateway->getSql()->select();
$select = $select->where(array('id' => $value));
$row = $this->tableGateway->selectWith($select)->current();
return $row;
}
域模型 - 用于数据表示
<?php
...
class User
{
public $name; // user name
...
public $articles; // holds the user articles
}
优势
- 被动模型易于阅读 - 了解数据结构及其关系。
- 被动模型易于测试 - 您不需要外部依赖项。
- 将持久性层与域层分开。
希望这有帮助!
您不应该将映射器注入到模型中,这正是相反的方式。对于您来说,重要的是要了解关系的工作方式,并且模型不应知道其数据如何映射到持久性框架。
你提到教义,所以我建议你也看看教义是如何解决这个问题的。他们这样做的方式是通过代理。代理是一个生成的类(你需要编写自己的生成器或自己编写所有代理),它扩展了模型并注入了映射器:
class Foo
{
protected $id;
protected $name;
public function getId()
{
return $this->id;
}
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
}
class ProxyFoo extends Foo
{
protected $mapper;
public function __construct(FooMapper $mapper)
{
$this->mapper = $mapper;
}
public function getName()
{
if (null === $this->name) {
$this->load();
}
return parent::getName();
}
protected function load()
{
$data = $this->mapper->findById($this->id);
// Populate this model with $data
}
}
我的建议:要么查看Zend Framework 2应用的默认映射器模式,忘记延迟加载,要么只使用Doctrine。这是太多的工作,无法正确完成这项工作。