PHP对象 - 模式和正确用法

时间:2012-10-07 11:41:57

标签: php oop class object application-design

我只是想知道是否有人可以帮助我了解如何在PHP中充分利用对象。

我对PHP对象的理解是应该代表一个实体,提供获取和改变该实体属性的方法。例如,名为Post的对象将保存单个帖子的所有属性,可以根据需要进行访问和修改。

让我感到困惑的是,像CodeIgniter这样的库在这个庄园中不使用对象。他们将类更像是一组函数的包装器。所以CodeIgniter中的'Posts'类不会保存一个帖子的属性,它会提供获取,编辑和删除帖子的功能。

那么如果我想从数据库中获取每个帖子并将其放入Post对象,会发生什么?我对它的理解是我实际上需要两个类'Posts'和'Post',一个定义Post对象,一个处理从数据库中获取Posts并将它们放入Post对象。

这两种类都有一个名字('正确'对象/函数集合)?有两个类这样一起工作,或者我完全误解了如何使用对象,这是常见的吗?

在我的Posts类中有一个名为getSinglePost($ id)的方法只返回一个数组,而不是拥有一个Post对象会更有意义吗?

希望这个问题有意义,期待得到一些反馈。

3 个答案:

答案 0 :(得分:5)

有关简介,请参阅What is a class in PHP?

对于答案,我将特别提出您的问题。搜索粗体中的字词,以了解有关其含义的更多信息。

  

我对PHP对象的理解是应该代表一个实体,提供获取和改变该实体属性的方法。

实体只是对象的一种可能用途。但是还有值对象服务对象数据访问对象等 - 当你走OO路线时,一切都将是一个对象有一定的责任。

  

让我感到困惑的是,像CodeIgniter这样的库在这个庄园中不使用对象。

是的,Code Igniter并不真正拥抱OOP。他们正在使用更多基于类的编程方法,这更像是使用类编写程序和少量OOP。

  

他们将类更像是一组函数的包装器。所以CodeIgniter中的'Posts'类不会保存一个帖子的属性,它会提供获取,编辑和删除帖子的功能。

虽然这很好。帖子类可以是存储库,例如邮件实体的内存集合,其附加责任是在后台检索和保留这些实体。我会对设计模式和Code Igniter保持谨慎,因为他们知道使用他们自己对模式的解释(例如他们的 Active Record 更像是查询对象)。

  

如果我想从数据库中获取每个帖子并将其放入Post对象,会发生什么?

这里有很多选择。一种常见的方法是使用 Data Mapper ,但您也可以使用PDO并直接将数据行提取到Post对象等。

  

我对它的理解是我实际上需要两个类'Posts'和'Post',一个定义Post对象,一个处理从数据库中获取Posts并将它们放入Post对象。

这将是前面提到的存储库数据映射器方法。您通常将这些与表数据网关组合在一起。但是,另一种选择也可能是没有Posts类并使用 Active Record 模式,该模式将数据库中的一行表示为附加了业务和持久性逻辑的对象。

  

这两种类都有一个名字('正确'对象/函数集合)?有两个类这样一起工作,或者我完全误解了如何使用对象,这是常见的吗?

是的,他们一起工作。 OOP就是对象协作。

  

在我的Posts类中有一个名为getSinglePost($ id)的方法只返回一个数组,而不是拥有一个Post对象会更有意义吗?

这将是表数据网关返回记录集。如果你没有很多业务逻辑并且可以省去域模型,就像 CRUD 应用程序

那样没关系

答案 1 :(得分:0)

您对物体的理解是正确的。帖子是类Post的单个对象。但是当然你需要一个函数,它从数据库中检索帖子或从其他地方收集它们。因此,您有所谓的工厂类。这可能会导致一些混乱。

工厂可以是单身人士,这通常意味着您拥有此类的一个实例。但是您根本不需要实例化工厂(而是使用静态函数来访问功能):

$posts = PostFactory::getPosts();

然后功能:

static function getPosts() {
  $list = array();
  $sql = "select ID from posts order by datetime desc"; // example, ID is the primary key
  // run your sql query and iterate over the retrieved IDs as $id
  {
  ...
    $post = new Post($id);
    array_push($list, $post);
  }
  return $list;
}

在这个工厂里面,你有一组“访问”功能,它们不适合其他地方,比如对象创建(数据库)和对象检索。对于第二部分(检索),只需要将函数放入工厂,如果没有“父”对象(就关系而言)。因此,您可以拥有类Blog的实体,您可以实例化博客,然后通过博客实例检索博客的帖子,而不需要单独的工厂。

命名只是为了帮助您理解。我不建议拨打课程Post并且它是工厂Posts,因为它们很容易混淆并且代码难以阅读(您需要注意细节)。我通常在类名中加入“factory”这个词,所以我知道它实际上是一个工厂类,其他人也看到它。

此外,您还可以拥有 Helper 类,这些类与任何特定的实体类都没有关系。所以你可以有一个PostHelper单例,它可以保存功能,既不适合对象类也不适合工厂。虽然我想不出Post对象的任何有用功能。一个例子是一些计算东西的软件,你有Helper,它使用不同类型的对象执行实际计算。

答案 2 :(得分:0)

理想情况下,类应该与PHP中的任何其他地方具有相同的解释。类从抽象开始,精炼掉你不需要的东西。所以完全取决于你以你想要的方式定义类。 Codeigniter确实有一种启动和访问对象的奇怪方式。主要是因为它们被加载一次并在之后使用,因此阻止它具有围绕数据的功能。有很多方法可以解决类的正常处理问题。我通常使用自动加载器并使用普通类。 “那么如果我想从数据库中获取每个帖子并将其放入Post对象会发生什么呢?我对它的理解是我实际上需要两个类'Posts'和'Post',” 您实际上是指用于访问数据的MODEL(“帖子”)和用于表示“帖子”的实体。因此,您可以加载模型一次,并使用它来加载任意数量的实体。

$this->load->model("posts");
$this->posts->get_all(); // <- This can then initiate set of objects of type "Post" and return. Or even standard classes straight out from DB.