我们正在重写OOP中的代码,我正在尝试为未来的项目设计一个通用框架(主要是为了遵守DRY并保持代码的纤薄和一致)。
例如,我认为拥有一个基类DatabaseObject
会很好,它将从数据库行中获取其属性。除其他外,它会使用__call()
和property_exists()
来自动化大多数getter。这样我们就不必为数据库行中的每一列写入所有100多个getter(或者在对表进行每次更改时更新类代码)。
Customer
,Car
或Article
等其他类会扩展DatabaseObject
(如果它们来自数据库)并继承这些方法,所以我们不会必须将数据库特定代码分别复制到每个类中(随着时间的推移会越来越不一致)。
这是正确的......在Web项目中使用继承,还是这个糟糕的设计?我的同事辩称,这有点滥用继承,而且来自CSV文件的客户需要一个单独的类定义,这是一个有效的点。
使用Interfaces,我们仍然需要将代码复制到每个类中,并且特性(除了要求PHP 5.4)不适用于我上面的__call()
示例(我认为)。
那么我的DatabaseObject
概念有更好的方法吗?
编辑:有人可以向我解释投票的原因,所以我可以删除并以适当的方式重新提交我的问题吗?
答案 0 :(得分:1)
您正确地将数据库表映射到对象中。实际上,人们在你发明轮子之前。 PHP中有几个ORM可以帮助您完成这项任务,而无需重新发明轮子 - 例如学说,推动...
但是,您在当前架构中可能遇到的问题是对象的状态。您的实体 - Car
或Article
将很难保持其状态,如果它周围的所有逻辑都在抽象中。您需要一个映射到表列的属性,以便保持对象更改,但不会提交更改。只有uppon例如调用save()
方法来提交更改。
此外,如果你需要一个额外的逻辑,比方说,你需要验证文章作者的名字,你需要在任何地方物理写入setAuthor()
方法,以便改变它的内容。
我提到的ORM通过代码生成工具解决了这些问题,该工具检查数据库模式并使用实体中的物理getter和setter创建类。例如,Propel创建一个具有表名的类,其中包含所有getter和setter以及那里的逻辑,但是还创建了一个在公共目录中扩展它的类,因此当您实例化Article
时,实例化扩展ArticleBase
的空类。 ArticleBase
确实有setAuthor()
方法对作者执行更改,例如UPDATE / INSERT。但是当您需要在setAuthor()
中执行其他逻辑时,只需在Article
中覆盖它,执行逻辑并调用parent::setArticle()
。
这也解决了自动完成的问题。现代开发者世界让我过分依赖汽车完成。我不能也不会记得我正在使用的每个模块的公共API,也不记得应用程序下的整个数据库。因此,我可能不知道您的articles
表格中是否有user_id
列,或author_id
。因此,我希望写$article->
来建议我能够使用的方法。使用__call()
的方案将导致缺少自动填充建议,因为不会生成任何方法,也不会生成任何注释。