2009-04-17 64 views
0

今晚有点花时间在PHP学习一些面向对象的操作,并碰到一堵砖墙。我正在创建一本小书库应用程序来跟踪我的书籍收藏,并认为我将使用面向对象的实践。查看一些代码?

我有一个名为library.php的主要php文件,其中包含2个主要的类到目前为止。

  1. 级数据库(连接到MySQL,数据库等)
  2. 类书籍(包含标题,作者,流派信息等和方法将数据插入到数据库)

所以,我的问题:

可以为我的所有类使用一个文件吗?

而下面的代码是将书籍添加到数据库的过程页面,这是好的,还是我会在错误的方向?

另外,我该如何去了解何时在类中创建新方法或创建整个新类?

<?php 
    include 'library.php'; 

    // Connect to Host & DB 
    $database = new database(); 
    $database->mysqlConnect('localhost', 'root', ''); 
    $database->selectDB('books'); 

    // Retrieve Values 
    $book = new books(); 
    $book->retrieveValues(); 
?> 

感谢, 基思

回答

8

在我看来,最好为每个类创建一个文件,其中文件以该类的名字命名。我使用与乍得桦树略有不同的符号,即Classname.class.php。类自动加载是一个很好的功能,但我不经常使用它(只有在某些情况下,如MVC,经常添加或删除相同类型的类)。

关于对象建模:开始为名词创建类。确定应用程序中的角色。这样做的一个方法是记下你的应用程序应该做什么,然后扫描它的名词并在这些之后为你的类建模。因为一个类代表一个单独的对象,所以大部分时候类名都是单数。如果有多个对象,你应该把它命名为ObjectCollection或类似的东西(例如“BookCollection”)。

让我们试试吧:

我想创建一个小本子库的应用程序来跟踪我的藏书。它应该跟踪我拥有的书籍,流派,作者和我借给他们的朋友。另外,对于每个朋友都应该存储电话号码,所以我可以给他打电话。所有的信息都存储在数据库中。

  1. Book:代表一本书( “教父”, “Cryptonomicon”)
  2. Library:代表书籍
  3. 集合
  4. Collection:已经涵盖图书
  5. Genre(“Sci- “”恐怖片“,”...“)
  6. Author(”Neal Stephenson“,”Mario Puzo“)
  7. Friend( “乔”, “吉尔”, “杰克”)
  8. PhoneNumber(朋友的属性)
  9. Database(杜)

然后你建立层次结构。哪些对象包含其他对象,它们之间的关系是怎样的?

  • Library包含0,1或更多Book小号
  • Book属于一个Genre
  • Book被1个或多个Author小号
  • 我可以借一Book为0或1写入Friend并且一次只有一个Friend
  • A Friend有一个PhoneNumber

(这也会告诉你一两件关于你的数据库应该如何)。

并非一切都很明显。你真的需要电话号码课吗?这只是一个字符串。在这种情况下,你应该把它变成财产。此外,电话号码并不是真的在Friend对象之间共享的(如果有几个朋友住在一起,并且它们经常改变,但是现在这会有点矫枉过正)。如果名词可以用一个标量值(一个字符串,整数,浮点数)表示,并且没有其他值连接到它们,那么创建类可能会过度。

因此,随着时间的推移,你扩展你的应用程序。你决定不仅存储电话号码,而且还存储地址。地址和电话号码是非常相似的信息类型,因此您可以为街道,城市,邮政编码等添加其他变量。在某个时候,你会感到沮丧,因为Friend类增长巨大,有很多属性,getters-和setters-方法,其中一些前缀将它们组合在一起(Friend->addressStreet,Friend>addressPostCode等)。因此,您可能决定将其重新定位到自己的类,称为Address(如果您将电话号码保留为Friend)或Contact,只是为了保持代码清洁(没有错误,但要小心)。

类层次结构和对象层次结构如何?不要混淆它们,它们是完全不同的东西!如果类似的类共享某些属性,但是在其他属性上不同,则会出现类层次结构。因此,您可以使用它们共享的属性和方法以及继承父级的属性和方法的子类创建一个类,并添加它们自己来处理差异。

在我们的图书馆例子中,那可能是什么?说实话,除了一件有点无意义的事情之外,我想不出任何东西,但我们不妨去想它... Friend s和Author s都是Person s!都有姓名,电话号码和地址。但他们也不同,因为作者写书和朋友不写(作者通常不借你的书)。因此,您可能会定义和Address - Person类中的对象,但getUnreturnedBooks()明确属于Friend,而getBooksWritten()属于Author

它没有意义,因为你永远不会在同一运行中处理Author s和Friend s。但让我们说你需要存储在你的图书馆中的所有地址列表,你可以循环你的收藏人员,并致电getAddress()。说实话,即使PHP是一个不好的例子,因为你可以将任何你想要的类型一起存储在一个数组中,并以任何你想要的方式访问它们,但是在强类型语言中是不可能的。在Java中,你必须为一个数组定义一个数据类型,如果它们有一个公共继承(但你仅限于原始类的方法),则可以存储不同的类型。足够的那个类继承巫术。

对象层次结构只是说明哪些对象应该包含其他对象。 A library包含book对象。 A book包含一个author对象。

的其他建议:

  • 尝试是描述性的。不要使用像Library->retrieveValues()这样的名称,将它命名为Library->getBooks(),因为Book对象就是您所得到的。

  • 有时最好在数据类型返回后命名方法。如果他们返回布尔值,这很常见。良好的命名约定可能是hasis,如Friend->hasBook($book)Book->isInLibraryCurrently()

  • 对于某个类的所有对象来说总是相同的值可能是类常量。比方说,如果一个Person可以是男性或女性,并且您将其存储为数据库中的“m”或“f”,则可以定义类常量Person::GENDER_MALE = 'm'Person::GENDER_FEMALE = 'f',因此您没有“m”s和“f”分散在你遍历的SQL查询中。

  • 只生成单个实例的类可以建模为单例。一个很好的例子可能是数据库类 - 它不太可能需要一次打开多个事务。阅读更多关于维基百科的单身人士(http://en.wikipedia.org/wiki/Singleton_pattern),但可能有点早。

更新:有些人认为单身人士一个坏主意,因为他们或多或少“刻在石头上,”一旦他们实现这种方式。因此,如果您将Database类作为单例建模,但后来决定需要多个数据库连接(不太可能,但可能),则会出现问题。如果你冒险,单身人士可能会很方便。

1

我认为面向对象编程的思想,部分是类和逻辑分离,因此可能会更好每个等级达到拆分成单独的文件。至于何时在类或新类中创建新方法,我认为如果您使用的方法与该特定类的主要操作有关,则应该添加它。只有在执行例程或重要功能时才能创建新类,并将正确的逻辑保存在正确的类中。

+0

类和逻辑是分开的吗?你什么意思? – 2009-04-17 09:30:46

3

对不起,我没有时间来解决你所有的问题在此刻(我会回来这个明天早上),但我可以快速回答第一个:

是否确定为我的所有课程使用一个文件?

它在技术上是“OK”,因为在语言允许你这样做,但你不应该这样做。除了改进代码组织的好处之外,它还允许您使用称为Autoloading Objects的PHP的一个很好的功能。

如果按照例如页面所显示,您可以如下定义__autoload功能:

function __autoload($class_name) 
{ 
    require_once $class_name . '.php'; 
} 

这使得它,这样你就不必明确地包括所有与你的类定​​义的文件。相反,只要将它们放入与类名称相同的文件中,自动加载将自动包含所需的文件。也就是说,在你的代码中,你显示你有一个名为“books”的类。如果这个类的定义保存到一个名为“books.php”文件,当你有这样一行代码:

$book = new books(); 

PHP将自动包含在该点books.php。这非常方便,并且绝对是将每个课程保存在自己的文件中的好动力。

+0

我从来没有发现__autoload可读。事实上,当我认为自己有东西是自动加载的时候,它一直是令人困惑的原因,但我最终没有。最好是明确的。 – 2009-04-17 05:56:56

+0

非常感谢你 – 2009-04-17 07:43:50

2

一个类是一个函数和属性的集合。如果你需要完成一个特定的动作,那么你创建一个新的功能。如果您需要一种可以对其执行一组不同操作的数据,则可以创建一个新类。

而且由于我看到您使用的是MySQL,因此您应该检查预准备语句(http://us2.php.net/pdo.prepared-statements)以避免不安全的代码。 PS:我会命名类“书”而不是“书”。想想它宣布的方式 - new books()?您正在创建一本新书,因此new book()似乎更合适。

+0

欢呼,k感谢你的反馈 – 2009-04-17 07:44:43

1

您可能会考虑的另一件事是使用已编写的数据库库。关于编程,特别是面向对象的最好的事情之一就是能够重复使用各个部分来创建不同的整体。就个人而言,我用ADODB以优异的成绩。我同意将这些课程放在单独的文件中,既可以用于自动加载,也可以让您将它们分开放置在头脑中。您是否介意在这里发布您的课程副本,以便我们更好地了解他们的内部工作方式,而不仅仅是方法名称?