【问题标题】:PHP how to implement the Data Mapper pattern in MVCPHP如何在MVC中实现Data Mapper模式
【发布时间】:2016-10-01 00:51:52
【问题描述】:

我正在尝试在我的 MVC 项目中实现并掌握数据映射器模式。我知道以前有人问过这个问题,但我仍然不确定我是否朝着正确的方向前进。我在下面粘贴了我的控制器、数据映射器和域对象/实体代码:

控制器

用户登陆 mywebsite.com/dashboard/index 并从事件日志数据库表中查看事件列表。 index() 函数创建一个 Datamapper 实例并传递一个数据库包装器。然后使用从数据映射器获取的数据动态生成 HTML 表。

class DashboardController extends BaseController { 
    public function index() {
        require_once '../app/domain/mappers/EventMapper.php';
        require_once '../app/include/HTMLTableCreator.php';

        try {
            $eventMapper = new EventMapper(new Database('db'));
            $table = new HTMLTableCreator($eventMapper->findByLimit(20));
        } catch (DatabaseException $e) {

        }

        $this->view('/home/dashboard', ['table' => $table->toString()]);
    }   
}

数据映射器

此类包含用于从数据库中检索最近 20 个日志事件的 findByLimit() 方法。 fetchCollection() 方法填充域实体并将它们收集到一个数组中以返回给控制器。

当 SQL 查询返回多行(= 多个域对象)时,我应该创建一个供多个数据映射器使用的通用集合函数吗?数据映射器可以使用任何类型的数据源吗?

require_once '../app/domain/entities/Event.php';
require_once '../app/domain/interfaces/EventMapperInterface.php';

/**
 * EventMapper class
 */
class EventMapper implements EventMapperInterface {

    protected $dbh;
    protected $elements;

    public function __construct(Database $dbh) {
        $this->dbh = $dbh;
    }

    public function fetchCollection($objects) {
        foreach($objects as $object) {
            $event = new Event();
            $event->setId($object['id']);
            $event->setDateTime($object['datetime']);
            $event->setMessage($object['message']);
            $event->setHostname($object['hostname']);

            $this->elements[] = $event;
        }

        return $this->elements;
    }

    public function findByLimit($limit = 20) {
        $events = $this->dbh->sql_select('SELECT * FROM eventlog LIMIT ' . $limit, []);

        return $this->fetchCollection($events);
    }   
}

域对象/实体

最后是带有一些简单 getter 和 setter 的域对象。这是对域对象的属性进行验证的地方吗?

class Event {

    protected $id;
    protected $dateTime;
    protected $message;
    protected $hostname;

    public function setId($id) {
        $this->id = $id;
    }

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

    public function setDateTime($dateTime) {
        $this->dateTime = $dateTime;
    }

    public function getDateTime() {
        return $this->dateTime;
    }  

    // rest omitted for clarity
}

我是否在我的实现中遗漏了什么?

【问题讨论】:

  • 规格未知。很难说你错过了什么。我会看一些现有的 ORM 实现,而不是自己动手 :)
  • @ЯрославРахматуллин 我不同意 .. 大多数 ORM 实现已经成为一种矫枉过正,太多人想要很多不同的东西。 ORM 不能把它们都做得一样好,只有几件事..
  • 是的,我不需要复杂的 ORM 实现。通过从其他框架/实现中学习并编写一些我自己的东西,我学到了最多的东西。

标签: php oop design-patterns datamapper


【解决方案1】:

当 SQL 查询返回多行(= 多个域对象)时,我应该创建一个供多个数据映射器使用的通用集合函数吗?

没有。如果您的对象具有 1=1 的属性和 db 表列,则使用现有方法;例如PDO-FETCH 类。无论如何,每个实体有一个映射器会更干净。如果它们非常通用,则使用“超级”映射器。

数据映射器可以使用任何类型的数据源吗?

假设DataSource 是某种集合-读写接口,那么肯定。你有__construct(Database $dbh),可以用__construct(DataSource $ds)代替。

其他注意事项:尝试将数据库和映射器服务注入控制器。

【讨论】:

  • 我使用的是 mysqli 而不是 PDO,但我或许应该研究一下。我会使用控制器的构造函数来注入数据库和映射器服务吗?然后我必须假设该控制器中的所有操作方法都需要该映射器,这适用于单一职责原则。
  • 您是否建议查看现有的 IoC 容器?我一直在环顾四周,发现了几个实现。我不确定我会在哪里初始化这样的容器,但我认为这是另一个问题。
猜你喜欢
  • 2011-01-31
  • 2011-11-30
  • 1970-01-01
  • 2016-09-30
  • 2023-03-13
  • 2020-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多