将过程PHP转换为面向对象的PHP

时间:2013-03-14 22:16:27

标签: php oop static namespaces procedural-programming

我目前有一个相当大的应用程序,完全用程序PHP编写。我希望进一步提高我的PHP体验,并使用面向对象技术重新编写我的大部分应用程序。

在很多方面,OOP可以帮助减少代码量并使其更易于阅读。但是,我有几个问题。

1)我的理解是,一个类用作任意数量对象的蓝图,但任何一个类只代表一个对象,永远不会超过一个。因此,一个班级可以代表一个玩家,但从不代表多个玩家。

2)由于我要包含很多不同的类,我是否使用“Loader”类使用spl_autoload_register加载它们或者我只使用{{1在我的应用程序的程序文件中?

编辑:所以我的自动加载器会是一个类,然后我创建一个启动自动加载的实例,或者只是一个带有该函数和我将包含的spl_autoload_register的php文件,以避免重复相同的操作多个文件中的代码?

3)我的一些课程依赖于其他课程。我以前从未遇到过这个,所以老实说我不知道​​答案。如果我在我的主程序文件中包含所有类,但我的播放器类包含它需要运行的类,那么播放器类是否会起作用,因为主程序包含了哪个播放器所依赖的类上?

编辑:因此即使一个类可以实例化一个类型为Player的对象,并且此类不直接包含Player类,它仍然可以工作,因为控制器类可以< / em>包括Player类?

4)在多种情况下,我需要处理我正在创建的对象。我想知道我应该怎么做。例如,在我的Player类中,我有时需要从一个Player向另一个Player发送一些东西。那么,我是否在Player类中实现一个静态方法,该方法将两个Players作为参数并进行传输或者我还要做其他事情吗?

编辑:好的,所以请避免使用静态方法。现在我遇到了一个严重的问题:我的应用程序中有多次运行的方法,但是我无法将它们作为静态方法实现。我应该将它们作为实例方法实现吗?例如,从一个播放器发送到另一个播放器。我是否会创建一个实例方法来获取Player对象并将发送到它或发送它?

5)我有很多方法并不属于任何一个类的实例,它们也不适合作为静态方法。这些是否应该作为Common或类似的静态方法在自己的类中声明?在这种情况下,在实践中做了什么?

编辑:这些方法是否属于使用它们的特定应用程序文件,或者可能存储在自己的“functions.php”文件中?

6)我想学习如何使用命名空间,但我的代码永远不会被其他人使用,我永远不会在我的应用程序中使用其他人的代码。在我的应用程序中,命名空间是不必要的添加还是学习如何使用它们是个好主意?无论如何,一个应用程序是否有一个命名空间(应用程序名称?)或每个类是否属于它自己的命名空间?

7)最后,是否有一个用于数据库连接的类以及一个用于网络方法的类?我的应用需要两者。我认为将代码转换为使用面向对象技术时遇到的主要问题是确定将哪些方法放在哪里,因为目前它们都在一个整体文件中。

感谢您提供的任何帮助和见解。

3 个答案:

答案 0 :(得分:4)

  

1)据我所知,一个类被用作任意数量对象的蓝图,但任何一个类只代表一个对象,永远不会超过一个。因此,一个班级可以代表一个玩家,但从不代表多个玩家。

一个类不代表任何东西,因为正如你所说的那样,它只是任意数量对象的蓝图。您可以拥有代表多个玩家的同一类的多个实例(对象)。

  

2)由于我要包含很多不同的类,我是否可以使用“Loader”类使用spl_autoload_register加载它们,还是只在我的应用程序的程序文件中使用spl_autoload_register?

我不知道“我的应用程序的程序文件”是什么意思,我说是的。使用自动加载器,因为它只是工作,你不必担心做require_*

  

3)我的一些课程依赖于其他课程。我以前从未遇到过这个,所以老实说我不知道​​答案。如果我在主程序文件中包含所有类,但我的播放器类不包含它需要运行的类,那么播放器类是否可以工作,因为主程序包含了播放器所依赖的类?

您不想加载所有类,而只加载您要使用的类。在使用自动加载器时,您不必再担心这一点。但是,一旦加载了类,它就可以在整个应用程序中实例化。

通常,您需要在bootstrap phase of the application

中启动自动播放器
  

4)在多种情况下,我需要处理我正在创建的对象。我想知道我应该怎么做。例如,在我的Player类中,我有时需要从一个Player向另一个Player发送一些东西。那么,我是否在Player类中实现一个静态方法,该方法将两个Players作为参数并进行传输或者我还要做其他事情吗?

避免在OOP PHP中使用静态方法。它几乎从不需要。你可以考虑让另一个课程像一个玩家池,从一个玩家到另一个玩家“发送数据”。

因此,只要在尝试实例化它之前发生了包含该类的文件,这并不重要。

  

5)我有很多方法并不真正属于任何一个类的实例,也不适合作为静态方法。这些是否应该作为Common或类似的静态方法在自己的类中声明?在这种情况下,在实践中做了什么?

再次请不要使用静态方法。如果您在其他类中使用它们,那么您只需要对类进行单元测试并引入隐藏的依赖项。根据我的经验,几乎从来没有碰巧在某个地方只有一个方法。也许你的方法做得太多了。

但只是阅读你的问题很难说清楚。也许你可以在评论中举一个例子?

  

6)我想学习如何使用命名空间,但我的代码永远不会被其他人使用,我永远不会在我的应用程序中使用其他人的代码。名称空间是我的应用程序中不必要的补充,还是学习如何使用它们是个好主意?

PHP中的命名空间是关于结构化的。虽然没有其他人会使用您的代码,但您不必担心在某个地方使用相同的名称。一旦应用程序变得越来越大,将会发生这种情况。

  

无论如何,一个应用程序是否有一个命名空间(应用程序名称?)或每个类是否属于它自己的命名空间?

在名称空间方面,我经常关注PSR-0

  

7)最后,有一个类用于数据库连接,还有一个用于网络方法的类是常见的吗?我的应用需要两者。我认为将代码转换为使用面向对象技术时遇到的主要问题是确定将哪些方法放在哪里,因为目前它们都在一个整体文件中。

请牢记Single Reponsibility Principle,一般SOLID

另外,我强烈建议您观看these并继续观看它们直到您理解为止。

答案 1 :(得分:2)

  

1)据我所知,一个类被用作任意数量对象的蓝图,但任何一个类只代表一个对象,永远不会超过一个。因此,一个班级可以代表一个玩家,但从不代表多个玩家。

通常,您还将拥有代表集合对象的类,例如一个“玩家”类,可用于从所有玩家的集合中检索单个玩家:

$players = new Players();
$john = $players->findByName("john");
  

2)由于我要包含很多不同的类,我是否可以使用“Loader”类使用spl_autoload_register加载它们,还是只在我的应用程序的程序文件中使用spl_autoload_register?

这很大程度上取决于项目的复杂程度。简单的自动加载器功能通常足够好,但您可以查看Zend Framework Autoloader class

  

3)我的一些课程依赖于其他课程。我以前从未遇到过这个,所以老实说我不知道​​答案。如果我在主程序文件中包含所有类,但我的播放器类不包含它需要运行的类,那么播放器类是否可以工作,因为主程序包含了播放器所依赖的类?

是。但是,通过自动加载,您根本不需要担心这一点。如果您不使用自动加载,最好在定义类的文件中包含所需的类(使用require_once()以避免多次包含同一文件)。

  

4)在多种情况下,我需要处理我正在创建的对象。我想知道我应该怎么做。例如,在我的Player类中,我有时需要从一个Player向另一个Player发送一些东西。那么,我是否在Player类中实现一个静态方法,该方法将两个Players作为参数并进行传输或者我还要做其他事情吗?

静态方法几乎总是错误的方法。普通方法属于一个实例(即特定玩家),静态方法属于该类,即玩家的一般“想法”。如果你需要将东西从一个玩家转移到另一个玩家,为什么不这样实现:

class Player {
    public function transferMoney(Player $recipient, $amount) { ... }
}

$tom = new Player("tom");
$marc = new Player("marc");

$tom->transferMoney($marc, 500);
  

5)我有很多方法并不真正属于任何一个类的实例,也不适合作为静态方法。这些是否应该作为Common或类似的静态方法在自己的类中声明?在这种情况下,在实践中做了什么?

我无法合理地回答这个问题。但是,PHP中仍然存在普通函数,这些函数似乎是这种情况的最佳方法。然而,如果你正确地做OOP,你很可能永远不会遇到这样的问题。这通常是您的类设计的一个问题,这使您认为这些方法不属于任何对象。

  

6)我想学习如何使用命名空间,但我的代码永远不会被其他人使用,我永远不会在我的应用程序中使用其他人的代码。在我的应用程序中,命名空间是不必要的添加还是学习如何使用它们是个好主意?无论如何,一个应用程序是否有一个命名空间(应用程序名称?)或每个类是否属于它自己的命名空间?

命名空间很棒但是如果没有它们,你的代码可能会很好。由于命名空间可以嵌套,因此每个组件通常都有一个顶级命名空间和子命名空间。

  

7)最后,有一个类用于数据库连接,还有一个用于网络方法的类是常见的吗?我的应用需要两者。我认为将代码转换为使用面向对象技术时遇到的主要问题是确定将哪些方法放在哪里,因为目前它们都在一个整体文件中。

这取决于您对实际情况的建模方式。如果数据库连接和“网络”是两个不同的东西,那么可以选择两个类。

答案 2 :(得分:1)

  1. PlayerCollection是有效的类。当然,它的一个对象是一个多个玩家的集合。

  2. 使用spl_autoload_register,句号。最好遵循PSR-0标准并使用任何符合PSR-0标准的现有自动加载器(即Symfony Loader

  3. 它会起作用。但是,既然你使用了自动加载器(见2.),你根本不必关心包括类

  4. 在播放器1中调用播放器2的方法时,可以轻松地将播放器1中的消息发送到播放器2.然而,“发送内容”和“处理对象”可能意味着许多事情,所以答案是: 这取决于。但总的来说,建议避免使用静态方法

  5. 这听起来很像程序性思维。对不起,但我不能在这里给你一个银弹答案,你必须学习和理解面向对象设计的原理来应用它们。网上有一些标准文献和许多有用的资源。通过示例学习可能很有用(查看其他开源的OO应用程序和框架)

  6. “一个应用程序是否有一个命名空间(应用程序名称?)或每个类属于它自己的命名空间?” - 答案介于两者之间。命名空间对于将一起工作的内容组合在一起很有用,无论谁将使用或查看代码,它们都很有用。

  7. 面向对象设计的第一条规则:一类,一类责任。