《PHP精粹:编写高效PHP代码》——1.2节OOP简介

1.2 OOP简介
开始冒险吧!在理论知识方面,我们会结合代码示例来讲解,这让你更容易看懂代码的实际意义。

1.2.1 声明类
类相当于蓝图,是表明如何创建对象的一组指令。它还不是一个对象,而仅仅是对象的一个描述。在Web应用程序中,用类来表示各种实体。下面是一个可能用于电子商务应用程序中的Courier类:

以上代码表明了如何声明类,可以将Courier类保存在一个名为courier.php的文件中。这个文件的命名方法是需要牢记的一个要点,其重要性在1.3节中会详细阐述,我们会讲解当需要时如何访问对象。
上面的例子表明Courier类有两个属性:$name和$home_country,以及两种方法:__construct()和ship(),在类中声明方法的方式和我们所熟悉的声明函数的方式完全一样,因此一定要牢记这个语法。当写一个函数的时候,可以用同一种方式向方法中传入参数以及返回值。
你可能已经注意到示例代码中还有一个名为$this的变量,这是一个特别的变量,在对象的范围内它一直是可用的,用于指代当前对象。在本章的示例代码中,会用它从对象内部直接访问变量和调用方法,因此,在阅读本章时要留心这一点。

1.2.2 类的构造
construct()函数名字前面有两条相连的下划线。在PHP中,两条下划线表示一个神奇的方法,表示这是一个具有特殊意义或功能的方法。在本章我们将看到很多这样的方法。construct()方法是一种特殊的函数,在实例化一个对象时会调用它,称其为构造函数(constructor)。
PHP 4构造函数
PHP 4中没有什么神奇的方法。对象都有构造函数,并且在类声明中,构造函数的名字与类名相同。虽然在最新版本的PHP中已不再使用这种规范,但在遗留的代码或者与PHP 4兼容的代码中还可以看到这种规范,不过在PHP 5中已不再使用这种规范。

当实例化一个对象时通常会调用构造函数,当释放构造函数进而在代码中使用之前会用它创建和配置对象。构造函数还有一个和它相匹配的神奇方法,称为析构函数(destructor),它是一个名为__destruct()不带参数的方法。当销毁对象时,会调用析构函数,并且运行对象所需的停止或者清除任务。注意,虽然我们不能保证析构函数何时会运行,但当对象因销毁或超出作用域,或者PHP垃圾收集器开始运行等原因而不再使用时,析构函数才会运行。
当我们阅读本章的示例时,将会发现很多这样的示例或者神奇的方法。现在,让我们实例化一个对象,这将极好地解释构造函数是如何运行的。

1.2.3 对象实例化
要实例化或创建一个对象,要使用新的关键字,如同给一个对象取名,需要声明一个类;然后将预期使用的参数传入构造函数中。要实例化一个courier,应该这样做:

var_dump()的输出告诉我们:
这是一个属于Courier类的对象;
它有两种属性;
每个属性的名称和值。
当实例化对象时可以将参数值传入构造函数。在示例中,构造Courier对象时通过构造函数传入参数给$name属性赋值。

1.2.4 自动加载
到目前为止,上述示例表明了如何声明一个类,然后在需要的地方引用那个文件。在一个大型应用程序里,不同的文件需要包含在不同的脚本里,这一切很快会变得复杂而混乱,令人高兴的是,PHP有一种特性可使这一切变得很容易,称为自动加载。当需要一个类声明而不知道在哪里寻能找到类文件时,PHP自动加载会指引我们。
为自动加载定义规则时,用到了另一个神奇的方法:__autoload()。在前面的示例中,引用了一个文件,但作为一种选择,可以用自动加载方法来替代这种方法:

只有当你用显而易见的方法命名而且保存包含类定义的文件时,自动加载才会发挥作用。到目前为止,示例都是很简单的内容;类文件都具有相同的名字,都带有.php扩展的小写文件名,因此自动加载函数处理的都是这种简单的示例。
如果需要,也可以创建一个复杂的自动加载函数。例如,许多现代应用程序都是以MVC(Model-View-Controller,第4章会深入解释)模式构建的,在为类定义时,模型、视图和控制器往往会存放在不同的目录,为了解决这个问题,通常会用类的类型来为类命名,比如UserController,而自动加载功能会用字符串匹配或正规表达式来解释要寻找的类的特征,以及在哪里可以找到这些类。

1.2.5 使用对象
到目前为止,我们已经知道如何声明类,实例化对象,并且谈到了自动加载,但我们还没有进行更多的面向对象编程。接下来我们将使用所创建对象的属性和方法来工作,让我们用一些示例代码来看看究竟应该怎么做:

在这里,使用了对象运算符,这是用一个连字符和大于号组成的符号:->。它将对象与属性、方法或者你想访问的内容连接起来。连接符后的方法带有圆括号,而属性不带圆括号。

1.2.6 使用静态属性和方法
在举例说明了如何使用类,并解释了如何实例化对象之后,接下来要介绍的内容在概念上发生了转变。和初始化对象一样,将类的属性和方法定义为静态的(static)。静态属性或方法在使用时无需事先实例化对象。在任何一种情况下,可以标记一个元素为静态,将静态的关键字放在public之后(或其他可视性修饰符—本章后面会讲到很多这样的情况)。通过双冒号操作符::就可以访问它们。
范围解析操作符
在PHP中,使用双冒号操作符访问静态属性或方法,双冒号操作符在技术上称为范围解析操作符(scope resolution operator)。如果包含::操作符的代码发生问题,你常常会看到一个包含有T_PAAMAYIM_NEKUDOTAYIM内容的错误提示。虽然一眼看上去颇令人恐惧,但这只是一个简单的::引用。“Paamayim Nekudotayim”在希伯来语中的意思是“二点,二次”的意思。

静态属性是仅属于类的变量,而不属于对象。它完全孤立于任何属性,甚至于在类的对象中具有相同名字的属性。
静态方法是不需要访问类的其他部分的方法。因为没有创建用于引用的对象,所以在静态方法里不能引用$this关键字。你经常在库中看到的静态属性,其功能独立于任何对象的属性。它常常用来作为一种命名空间(直到5.3版本PHP才有命名空间;相关内容在下一节中介绍),并且静态属性对于检索对象集合的函数也是非常有用的,可以像这样在Courier类中增加函数:

如果你想用这种方式调用方法,那么必须将该方法标记为静态方法;否则,你将会看到一个错误提示。这是因为设计一个用于调用的方法时,不论使用静态或是动态的方法,都应该像这样先声明。如果没有必要访问$this,并且这个方法是静态的,那么像示例一样声明和调用它。如果不是这样,那么应该首先实例化对象,这是因为这个方法不是静态的方法。
何时使用静态方法是学习重点。一些类库和框架频繁地使用它们;但在没有严格要求使用的地方,其他类库和框架通常会使用动态函数。

1.2.7 对象和命名空间
从PHP 5.3开始,PHP开始提供对命名空间(namespace)的支持。这一新功能有两个主要目的,第一个目的是为了避免给类取像这样的名字:Zend_InfoCard_Xml_Security_Transform_Exception,这样长达47个字符的名字在代码中使用非常不方便(这里没有任何对Zend Framework的不敬,我们只是随机抽取一个具有描述性的名字);第二个目的是提供简单的方法将类和函数从各种类库中分离出来。每个框架都有不同的优势,可以仔细挑选几个最好的框架在应用程序中使用。然而,当两个类在不同的框架中具有相同的名字时,问题就出现了;在声明两个类时不能取相同的名字。
幸运的是,使用命名空间能解决这个问题,可以用很短的名字为类取名,但要加上前缀。命名空间在文件的顶部声明,并适用于所有在该文件中声明的类、方法和常数。我们将重点关注命名空间对类的影响,但我们要牢记的是,这些原则也可用于其他项目。例如,将代码放入一个名为shipping的命名空间里:

因为Courier类嵌套了两个层次的深度,所以用命名空间声明顶部的shop/shipping并将其类定义放进一个文件中。加上这些适当的前缀,你可能想知道这将如何帮助解决长类名的问题;到目前为止,我们似乎只能使用通过命名空间运算符替代下划线的方法!事实上,可以用简写来指代命名空间,甚至包括在一个文件中使用多个命名空间的情况。
下面的示例使用了我们刚才所见列表结构中的一系列类:

因为有shipping,所以可以在嵌套命名空间中的最低一层使用缩写,并且因为有user,所以可以创建昵称或缩写来使用这个类。这对于我们逐步解决多数特定元素的同名问题大有裨益。你可以为这些同名元素各取一个有特色的名字以便区分。
命名空间越来越多地应用于自动加载功能,你很容易想象目录分隔符和命名空间分隔符如何相互代表。相对于PHP而言,命名空间是一个新增加的内容,你一定要在类库和框架中理解它们。现在你知道该如何有效使用命名空间了。

时间: 2024-10-22 01:45:20

《PHP精粹:编写高效PHP代码》——1.2节OOP简介的相关文章

《PHP精粹:编写高效PHP代码》——2.8节数据库—排序

2.8 数据库-排序 在本章,我们全面讲述了与PHP开发者息息相关的数据库主题.了解了PDO扩展并利用它在你的应用程序中建立稳定高效的代码. 除PHP外,我们还研究了一连串的数据库技术,这些技术以不同的方式在表中建立SQL查询.我们还使用索引,设计了经受住时间和可扩展性考验的数据库架构.

《PHP精粹:编写高效PHP代码》——3.3节数据格式

3.3 数据格式 在许多方面,Web服务仅仅只是一个网页,它提供机器可读的内容,而不是人类可读的内容.我们与其在一个浏览器的HTML网页标记标签,不如返回内容到JSON或XML中(我们马上将论及上述内容). 健壮性Web服务的强大特征之一便是它的设计可使其以不同的格式返回信息.因此,如果一个服务消费者更喜欢另一种数据格式,它可以轻易请求到最好的格式.这表明,当我们创建的服务公开后,解释请求和构成响应的方式是独立于代码中其他部分的. 接下来的两节将详细讲解JSON和XML,并举例说明如何以这种方式

《PHP精粹:编写高效PHP代码》——1.8节更多神奇的方法

1.8 更多神奇的方法 本章已介绍了一些神奇方法.在表1.1中快速回顾一下这些方法. 当在一个类中定义这些函数时,可以定义当这些事件发生时会引发什么.没有这些函数的话,类将显现为默认行为,而这些常常都是需要的.PHP另外还有一些神奇方法,在本节中我们将看到一些使用最频繁的方法. 1.8.1 使用__call()和__callStatic()方法 在关于访问修饰符的内容里,我们看到,对于__get()和__set()方法而言,__call()方法是一个天生的搭档.使用__get()和__set()

《PHP精粹:编写高效PHP代码》——3.4节HTTP:超文本传输协议

3.4 HTTP:超文本传输协议HTTP(HyperText Transfer Protocol)是通过导线来传送Web请求和响应的数据传输格式.它包含了很多请求和响应的元数据,除了这些请求或响应的实体之外,我们也可以利用它来使用Web服务.我们也将看到其他的协议,例如XML-RPC和SOAP,它们也都是建立在HTTP基础上的.当我们在本章快结尾构建RESTful服务时,便可以广泛使用HTTP的功能了.当我们开发一个简单的Web应用程序时,可能不会那么重视HTTP.但是如果你想了解缓存.不同文件

学习PHP精粹,编写高效PHP代码之质量保证

一.使用静态分析工具测量质量   我们用静态分析测量代码而不运行它.实际上,我们将这些工具用于评估代码.读取文件.衡量它所写的要素.使用这些工具,可以帮助我们对代码库有一个完整的层次化的认识,甚至在代码库变得更大.更复杂的时候也能掌握.   静态分析工具是项目过程中的一个关键组成部分,但是,只有定期使用它们,并以理想的方式进行每一次提交,静态分析工具才真正显示出价值.这些工具涵盖了代码的所有方面,从计数类和计算行数,到识别哪里有提示使用复制和粘贴的类似代码段.然后我们来看看静态分析工具在代码质量

《PHP精粹:编写高效PHP代码》——1.7节异常

1.7 异常 异常(exception)是一个处理错误的面向对象方法.一些PHP扩展像往常一样仍会报错:很多最新的扩展(例如PDO)将代替抛出异常.异常也是对象,而且Exception是PHP的一个内置类.一个Exception对象将包含发生错误的位置(文件名或代码行).一条错误消息和(可选)一个错误代码等信息. 1.7.1 处理异常 首先我们看看如何处理可能会抛出异常的函数.我们会使用一个PDO示例,因为PDO扩展抛出异常.在这里代码会试图创建一个数据库连接,但是会失败,因为nonsense主

《PHP精粹:编写高效PHP代码》——2.4节PHP数据库对象

2.4 PHP数据库对象 如果之前你使用过PHP和MySQL,你可能用过mysql或mysqli类库连接到数据库,如使用mysql_connect()函数.多年来,这是连接到MySQL数据库的标准方式,并且对于其他数据库平台也使用同样的方式. 这些类库可以直接使用,并形成了无数PHP应用程序类库和框架的基础.这种方式的缺点是每个扩展都与其他稍有不同,因此使得代码在数据库平台之间轻松转移变得复杂.虽然这些数据库特定类库依然活跃并且运转良好,但是本章中仍将专注讲解更先进的PDO扩展.创建的PDO扩展

《PHP精粹:编写高效PHP代码》——2.6节处理PDO中的错误

2.5 处理PDO中的错误 当你刚开始使用PDO时,它的某个方面是令人惊讶或让人沮丧的(视你的态度而定),即当它出现问题时,并不总是显而易见的.当我们第一次连接到数据库时,就会看到一个失败的连接会导致抛出一个异常.这里有一个提醒的代码: 一般来说,当某些引人注目的事情发生时PDO会抛出异常,但是如果你的查询由于某些原因而未能运行时,你也不必为此大惊小怪.这表明我们要仔细检查一切是否按照我们所预期的那样运行. 让我们复习一下迄今为止所学到的相关内容,看看我们如何对出现的问题进行识别和反应. 2.5

《PHP精粹:编写高效PHP代码》——2.6节高级PDO特征

2.6 高级PDO特征 我们已经看到PDO功能构成了以数据库驱动的PHP应用程序的主体.然而, PDO还有几个锦囊妙计需要我们好好研究.下面两节将显示我们如何利用数据库的事务,以及如何在PHP代码中调用存储过程. 2.6.1 事务和PDO 在数据库术语中事务(transaction)是一组必须执行的语句的集合.这组语句要么必须全部顺利完成,要么一个也不运行.不是所有的数据库都支持事务,有些支持,有些不支持,有些经过配置以后才会支持.对于MySQL,有些表的类型难以获得事务支持. 如果数据库不支持