PHP MVC:数据映射器模式:类设计
我有一个带有域对象和数据映射器的Web MVC应用程序。 数据映射器的类方法包含所有数据库查询逻辑。 我试图避免镜像任何数据库结构,因此,在构建sql语句时实现最大的灵活性。 所以,原则上,我试图不使用任何ORM或ActiveRecord结构/模式AT ALL。
让我给你一个例子:通常,我可以有一个抽象类AbstractDataMapper
继承所有特定的数据映射类 - 就像UserDataMapper
类。 然后,我可以定义一个findById()
的方法AbstractDataMapper
,抓取特定表的记录-样users
-通过给定的id
值,例如用户ID。 但是这意味着我总是从单个表中获取记录,而没有可能使用任何左连接从一些其他表中获取与给定的id
- 用户标识相对应的其他一些细节。
所以,我的问题是:在这些条件下 - 我自己有义务应该实现抽象数据映射器类,还是每个数据映射器类都应该包含它自己的完全“专有”数据访问层实现?
我希望我能清楚地表达我的想法。 请告诉我,如果我有点不清楚或者您有任何问题。
非常感谢您的时间和耐心。
如果我明白你的观点......
让所有具体的映射器从一个普通的类继承SQL有几个问题,你已经错过了:
PRIMARY KEY
列的id
作为名称 现在,我要试着解开其中的每一个。
参数和列名称
要创建一个共享的findById()
方法,唯一实用的方法是围绕如下内容构建它:
"SELECT * FROM {$this->tableName} WHERE id = :id"
主要问题实际上是通配符*
符号。
使用数据映射器填充实体有两种主要方法:使用setter或使用反射。 在这两种情况下,参数/设置器的“名称”都是由您选择的列隐含的。
在普通查询中,您可以执行诸如SELECT name AS fullName FROM ...
,这可让您使用查询重新命名字段。 但采用“统一方法”,没有好的选择。
每个映射器都可以通过id
获取数据?
所以,事情是,除非你有一个mapper-per-table结构(在这种情况下,一个活动记录开始看起来像实用选项),那么最终你的映射器只会有很少(非常常见的)“边缘情况”场景:
你最初的想法在小规模项目中可以很好地工作(一个或两个映射器是一个“边缘案例”)。 但是对于一个大型项目, findById()
的使用将成为例外而非常态。
独立父母吗?
要在超类中实际获取此findById()
方法,您需要一种方法将表名与它通信。 这意味着,你在类定义中有类似protected $tableName
东西。
您可以通过在抽象映射器类中使用abstract function getTableName()
来减轻它的影响,该类在实现时返回全局常量的值。
但是,当您的映射器需要使用多个表时会发生什么情况。
这似乎是一种代码味道,因为信息实际上跨越了两个界限(缺乏更好的单词)。 当此代码中断时,将在超类中显示SQL的错误,这不是错误源自的地方(尤其是,如果使用常量)。
命名主键
这是一个更有争议的观点:)
据我所知,调用所有主要列id
的做法来自各种ORM。 这招致的惩罚仅适用于可读性(和代码维护)。 考虑这两个查询:
SELECT ar.id, ac.id
FROM Articles AS ar LEFT JOIN
Accounts AS ac ON ac.id = ar.account_id
WHERE ar.status = 'published'
SELECT ar.article_id, ac.account_id
FROM Articles AS ar LEFT JOIN
Accounts AS ac USING(account_id)
WHERE ar.status = 'published'
随着数据库模式的增长和查询变得越来越复杂,实际上越来越难以追踪,在什么情况下“id”代表什么。
我的建议是尝试使用相同的名称作为列,当它是主要的时候它是一个外键(在可能的情况下,因为在某些情况下,像“关闭表,它是不可行的)基本上,所有存储ID相同的类型,应该有相同的名称。
作为一个小小的奖励,你会得到USING()
语法糖。
TL; DR
馊主意。 你基本上打破了LSP。
链接地址: http://www.djcxy.com/p/56223.html上一篇: PHP MVC: Data Mapper pattern: class design
下一篇: How to load a one