1

在我的 zend 框架 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);
    }
}

问题是我无法在我的用户模型中注入我的用户表,因为表网关使用模型类作为数组对象原型,稍后注入以创建用户表网关(映射器)。

我不想在我的模型中注入服务管理器,因为这被认为是一种不好的做法。如何在我的用户模型中注入我的用户表?可能吗?实现我想要做的最好的方法是什么

4

2 回答 2

6

您要做的是混合两种设计模式:Active RecordData Mapper

如果您查看 Data Mapper 模式,您将拥有同时访问模型和数据库的 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
}

优点

  1. 被动模型易于阅读 - 了解数据结构及其关系。
  2. 被动模型很容易测试——你不需要外部依赖。
  3. 您将持久层与域层分开。

希望这可以帮助!

于 2013-09-10T08:14:30.780 回答
2

你不应该将你的映射器注入到你的模型中,这恰恰相反。对您来说重要的是要了解关系的工作方式,并且模型不应该知道它们的数据如何映射到持久性框架。

你指的是 Doctrine,所以我建议你也看看 Doctrine 如何解决这个问题。他们这样做的方式是通过代理。代理是一个生成的类(您需要编写自己的生成器或自己编写所有代理),它扩展了模型并注入了映射器:

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。要正确完成这项工作,工作量太大。

于 2013-09-10T08:02:06.340 回答