我知道在OOP中你希望每个对象(来自一个类)都是一个“东西”,例如。用户,验证器等。
我了解MVC的基础知识,以及它们不同部分如何相互作用。
但是,我想知道MVC中的模型是否应该按照传统的OOP设计进行设计,也就是说,每个模型都应该是数据库/表/行(解决方案2)吗?
或者更倾向于收集影响同一个表或一堆相关表的方法(解决方案1)。
CodeIgniter中的地址簿模块的示例,其中我希望能够“CRUD”一个联系人并将其添加到一个可以接触CRUD的联系人组/从中删除。
模型解决方案1:将所有相关方法聚集在一起(不是真实对象,而是“包”)
class Contacts extends Model {
function create_contact() {)
function read_contact() {}
function update_contact() {}
function delete_contact() {}
function add_contact_to_group() {}
function delete_contact_from_group() {}
function create_group() {}
function read_group() {}
function update_group() {}
function delete_group() {}
}
模型解决方案2:OOP方式(每个文件一个类)
class Contact extends Model {
private $name = '';
private $id = '';
function create_contact() {)
function read_contact() {}
function update_contact() {}
function delete_contact() {}
}
class ContactGroup extends Model {
private $name = '';
private $id = '';
function add_contact_to_group() {}
function delete_contact_from_group() {}
function create_group() {}
function read_group() {}
function update_group() {}
function delete_group() {}
}
当我想创建模型时,我不知道如何思考。以上示例是我创建地址簿的真正任务。我应该把所有功能集中在一个类中。然后该类包含不同的逻辑(联系人和组),因此它不能保存特定于其中任何一个的属性。
解决方案2根据OOP工作。但我不知道为什么我应该这样划分。例如,有一个Contact对象会带来什么好处。它肯定不是User对象,那么为什么Contact应该“拥有”自己的状态(属性和方法)。因为我倾向于这样思考:如果某些东西需要一个状态,那么我创建一个OOP类,以便这些方法可以根据状态影响状态或其他事物。
模特也应该是“有状态的”吗?如果它们不需要状态,我为什么要根据OOP模式创建它。那么我可以像“包”解决方案一样将它们全部捆绑在一起。
你经历过OOP / MVC的人,请详细说明在这个非常具体的任务中应该如何思考(通常在创建模型时)
编辑:来考虑MVC中的控制器。它们是根据“包”解决方案创建的。这让我很奇怪......答案 0 :(得分:2)
我不知道是否有最佳方式,但我将分享我的方式......
我有一个表网关,例如ContactTableGateway,包含用于处理联系人的所有sql。我喜欢所有的sql都在一个地方。
class ContactTableGateway extends Model {
function saveContact( Contact $contact )
function getContact ( $contact_id )
function createContact ( Contact $contact )
}
然后我有一个联系人类,基本上只有getter和setter(或公共属性)。此类的对象用作表网关的保存/创建
的参数class Contact extends Model {
function getName()
function getAddress()
function getEmail()
....
}
这是一个简化的例子
if ( isset( $_POST ) ) {
// some validation here
$contact = new Contact;
$contact->name = $_POST['name'];
$contact->email = $_POST['email']
$contactTableGateway = new ContactTableGateway;
if ( $contactTableGateway->createContact( $contact ) ) {
echo "YAY";
}
}
答案 1 :(得分:2)
每个模特应该是一个 数据库/表/行(解决方案2)?
没有。不要将模型的定义与其持久性方法联系起来。虽然对于简单的应用程序,您可以从数据库行对象扩展模型,但您应该至少在心理上将它们分开。
模型只是您域中实体的表示,因此必要时它们具有状态。在谈论Contact模型时,您实际上是在谈论映射器或网关,即从数据存储中检索模型的对象。令人遗憾的是,如此多的Active Record临时实施已经在这方面陷入困境。
Mappers可以作为静态函数的集合或作为对象实现 - 但是,如果您因任何原因(例如模拟单元测试)而需要扩展或更改行为,则集合的灵活性会降低。
模型本身应该只是一个数据集合,或者存储为公共属性,或者最好是适当的 setter和getter(请不要只为每个变量定义一个get / set函数对或者你不妨将它们公之于众,以及对数据进行操作的其他方法。它应该没有数据存储的概念或依赖于数据存储。映射器负责通过其接口实例化和初始化模型。这样做可以灵活地创建和保存模型。您可以从数据库,XML文件,代码内,通过网络发送的序列化流中执行此操作,无论您的船是什么漂浮,都可以通过替换不同的映射器,并且模型仍然完全不知道。
答案 2 :(得分:1)
我认为您的解决方案#2更优越,因为它更具分子/模块性,因此更容易理解,更灵活和可扩展(在OOP域中)。它也更加资源友好,因为它可以让你只需要在不需要联系人组功能时加载Contact类,反之亦然。这是分裂的好处。
如果模型不需要状态,那并不意味着OOP / MVC不适用。表模型可能在一个设计中没有状态,但这就是为什么我们有静态方法/成员,即Contact :: read($ id)。