PHP MVC:数据映射器模式:类设计
我有一个带有域对象和数据映射器的web MVC应用程序。数据映射器的类方法包含所有数据库查询逻辑。我试图避免镜像任何数据库结构,从而在构造sql语句时实现最大的灵活性。因此,原则上,我尽量不使用任何ORM或ActiveRecord结构/模式 让我举个例子: 通常,我可以让所有特定的数据映射器类继承一个抽象类PHP MVC:数据映射器模式:类设计,php,oop,design-patterns,model-view-controller,data-mapping,Php,Oop,Design Patterns,Model View Controller,Data Mapping,我有一个带有域对象和数据映射器的web MVC应用程序。数据映射器的类方法包含所有数据库查询逻辑。我试图避免镜像任何数据库结构,从而在构造sql语句时实现最大的灵活性。因此,原则上,我尽量不使用任何ORM或ActiveRecord结构/模式 让我举个例子: 通常,我可以让所有特定的数据映射器类继承一个抽象类AbstractDataMapper,比如UserDataMapper类。然后我可以在AbstractDataMapper中定义一个findById()方法,通过给定的id值,例如用户id,来
AbstractDataMapper
,比如UserDataMapper
类。然后我可以在AbstractDataMapper
中定义一个findById()
方法,通过给定的id
值,例如用户id,来获取特定表的记录,比如users
。但这意味着我总是从单个表中获取记录,不可能使用任何左连接也从与给定的id
-user id相对应的一些其他表中获取一些其他详细信息
所以,我的问题是:
在这些条件下——我自己也有义务这么做——我应该实现一个抽象的数据映射器类,还是每个数据映射器类都应该包含自己完全“专有”的数据访问层实现
我希望我能把我的想法表达清楚。如果我不清楚或者你有任何问题,请告诉我
非常感谢您的时间和耐心。如果我理解您的观点 让所有具体的映射程序从一个公共类继承SQL有几个问题您没有注意到:
- 域对象中的参数名取决于列的名称
- 映射器中有一种“获取方法”,它没有相应的表
- 您仍然具有超类所期望的配置(表名)
- DB架构必须将
作为所有id
列的名称主键
findById()
方法,唯一实用的方法是围绕以下内容构建它:
"SELECT * FROM {$this->tableName} WHERE id = :id"
主要问题实际上是通配符*
符号
使用数据映射器填充实体有两种主要方法:使用setter或使用反射。在这两种情况下,参数/设置器的“名称”都由您选择的列暗示
在普通查询中,您可以执行类似以下操作:从…
选择名称作为全名,这允许您使用查询来重新命名字段。但如果采用“统一方法”,就没有好的选择
每个映射器都可以通过id
?
因此,问题是,除非您有一个mapper表结构(在这种情况下,活动记录开始时看起来像是一个实用选项),否则您最终将为您的mapper提供几个(非常常见的)“边缘情况”场景:
- 仅用于保存数据
- 处理集合而非单一实体
- 从多个表聚合数据
- 使用具有复合键的表
- 它实际上不是一个表,而是一个SQL视图
- 。。。或以上两者的组合
findById()
将是一个例外,而不是常态
独立育儿?
要在超类中实际获取这个findById()
方法,您需要一种与之通信表名的方法。这意味着,在类定义中有类似于protected$tableName
的内容
您可以通过在抽象映射器类中使用抽象函数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的所有列都应该具有相同的名称
作为一个小奖励,您可以使用()获得
语法
太长,读不下去了
坏主意。你基本上是在破釜沉舟。作为一个自己提供了500份赏金的人,这里有一个免费的建议:不要。我不得不要求mods稍后删除那篇帖子,因为我收到的答案都是废话。这会吓跑那些不太自信的人。而且,如果问题不是尽快解决的,你会得到更好的结果在两周内拿到100分的悬赏。见鬼,有了500分的预算,你可以在“悬赏”上贴个帖子“一个多月的时间。”tereško感谢您的评论和善意建议。我不知道。因此,我重新编辑了赏金部分。最后,我的目标是吸引好的答案。我刚刚读了你的答案,我发现我需要更多的时间——现在有点累了。我只想说:非常感谢你,特雷斯科。我以后一定会深入阅读的。我读了你的答案,实际上读了很多遍。哇:-)我想要一个