PHP面向对象技术(全面讲解)

PHP面向对象技术(全面讲解)

本部分一共包括以下一些技术点:

1.面象对象的概念

2.什么是类, 什么是对象, 类和对象这间的关系

3.什么是面向对象编程呢?

4.如何抽象出一个类?

5.如何实例化对象

6.如何去使用对象中的成员

7.特殊的引用“$this“的使用

8.构造方法与析构方法

9.封装性

10.__set() __get() __isset() __unset()四个方法的应用

11.类的继函

13.重载新的方法

14.访问类型

15.静态成员以及类中常量的使用

16.final关键字的应用

17.__toString()方法

18.克隆对象

19.__call处理调用错误

20.自动加载类

21.把对象串行化

22.抽象方法和抽象类

23.php5接口技术

12.多态的应用

 

1.面象对象的概念

    面向对象编程(Object Oriented Programming, OOP, 面向对象程序设计)是一种计算机编程架构,OOP的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成,OOP达到了软件工程的三个目标:重用性、灵活性和扩展性。为了实现整体运算,每个对象都能够接收信息、处理数据和向其它对象发送信息。面向对象一直是软件开发领域内比较热门的话题,首先,面向对象符合人类看待事物的一般规律。其次,采用面向对象方法可以使系统各部分各司其职、各尽所能。为编程人员敞开了一扇大门,使其编程的代码更简洁、更易于维护,并且具有更强的可重用性。有人说PHP不是一个真正的面向对象的语言,这是事实。PHP 是一个混合型语言,你可以使用OOP,也可以使用传统的过程化编程。然而,对于大型项目,你可能需要在PHP 中使用纯的OOP去声明类,而且在你的项目里只用对象和类。这个概念我先不多说了,因为有很多人朋友远离面向对象编程的主要原因就是一接触面向对象概念的时候就理解不上去, 所以就不想去学下去了. 等读者看完整体内容后再去把概念搞明白吧。

2.什么是类, 什么是对象, 类和对象这间的关系

 

类的概念:类是具有相同属性和服务的一组对象的集合。它为属于该类的所有对象提供了统一的抽象描述,其内部包括属性和服务两个主要部分。在面向对象的编程语言中,类是一个独立的程序单位,它应该有一个类名并包括属性说明和服务说明两个主要部分。

对象的概念:对象是系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位。一个对象由一组属性和对这组属性进行操作的一组服务组成。从更抽象的角度来说,对象是问题域或实现域中某些事物的一个抽象,它反映该事物在系统中需要保存的信息和发挥的作用;它是一组属性和有权对这些属性进行操作的一组服务的封装体。客观世界是由对象和对象之间的联系组成的。

类与对象的关系就如模具和铸件的关系,类的实例化结果就是对象,而对一类对象的抽象就是类.类描述了一组有相同特性(属性)和相同行为(方法)的对象。

 

上面大概就是它们的定义吧, 也许你是刚接触面象对象的朋友, 不要被概念的东西搞晕了, 给你举个列子吧,如果你去中关村想买几台组装的PC机,到了那里你第一步要干什么, 是不是装机的工程师和你坐在一起,按你提供的信息和你一起完成一个装机的配置单呀, 这个配置单就可以想像成是类,它就是一张纸,但是它上面记录了你要买的PC机的信息,如果用这个配置单买10台机器,那么这10台机子,都是按这个配置单组成的,所以说这10台机子是一个类型的,也可以说是一类的。那么什么是对象呢,类的实例化结果就是对象, 用这个配置单配置出来(实例化出来)的机子就是对象, 是我们可以操作的实体, 10台机子, 10个对象。 每台机子都是独立的,只能说明他们是同一类的,对其中一个机做任何动作都不会影响其它9台机器,但是我对类修改, 也就是在这个配置单上加一个或少一个配件, 那么装出来的9个机子都改变了, 这是类和对象的关系(类的实例化结果就是对象).

 

3.什么是面向对象编程呢?

 

就不说他的概念,如果你想建立一个电脑教室,首先要有一个房间, 房间里面要有N台电脑,有N个桌子, N个椅子, 白板, 投影机等等,这些是什么,刚才咱们说了, 这就是对象,能看到的一个个的实体,可以说这个电脑教室的单位就是这一个个的实体对象, 它们共同组成了这个电脑教室,那么我们是做程序,这和面向对象有什么关系呢?开发一个系统程序和建一个电脑教室类似,你把每个独立的功能模块抽象成类形成对象,由多个对象组成这个系统,这些对象之间都能够接收信息、处理数据和向其它对象发送信息等等相互作用。就构成了面向对象的程序。

 

4.如何抽象出一个类?

    上面已经介绍过了, 面向对象程序的单位就是对象,但对象又是通过类的实例化出来的,所以我们首先要做的就是如何来声明类, 做出来一个类很容易,只要掌握基本的程序语法定义规则就可以做的出来,那么难点在那里呢? 一个项目要用到多少个类,用多少个对象, 在那要定义类,定义一个什么样的类,这个类实例化出多少个对象, 类里面有多少个属性, 有多少个方法等等,这就需要读者通过在实际的开发中就实际问题分析设计和总结了。

 

类的定义:

class 类名{

}

使用一个关键字class和后面加上一个你想要的类名以及加上一对大括号, 这样一个类的结构就定义出来了,只要在里面写代码就可以了, 但是里面写什么? 能写什么?怎样写才是一个完整的类呢?上面讲过来,使用类是为了让它实例出对象来给我们用, 这就要知道你想要的是什么样的对象了,像上面我们讲的一个装机配置单上写什么,你装出来的机子就有什么。比如说,一个人就是一个对象,你怎么把一个你看好的人推荐给你们领导呢?当然是越详细越好了:

 首先, 你会介绍这个人姓名、性别、年龄、身高、体重、电话、家庭住址等等。

 然后,你要介绍这个人能做什么, 可以开车, 会说英语, 可以使用电脑等等。

 

    只要你介绍多一点, 别人对这个人就多一点了解, 这就是我们对一个人的描述, 现在我们总结一下,所有的对象我们用类去描述都是类似的, 从上面人的描述可以看到, 做出一个类来, 从定义的角度分两部分, 第一是从静态上描述, 第二是从动态上描述, 静态上的描述就是我们所说的属性, 像上面我们看到的,人的姓名、性别、年龄、身高、体重、电话、家庭住址等等。 动态上也就是人的这个对象的功能,比如这个人可以开车, 会说英语, 可以使用电脑等等,抽象成程序时,我们把动态的写成函数或者说是方法,函数和方法是一样的。所以,所有类都是从属性和方法这两方面去写, 属性又叫做这个类的成员属性,方法叫做这个类的成员方法。

 

class 人{

   成员属性:姓名、性别、年龄、身高、体重、电话、家庭住址

   成员方法:可以开车, 会说英语, 可以使用电脑

}

属性:

通过在类定义中使用关键字" var  "来声明变量,即创建了类的属性,虽然在声明成员属性的时候可以给定初值, 但是在声明类的时候给成员属性初使值是没有必要的,比如说要是把人的姓名赋上“张三”,那么用这个类实例出几十个人,这几十个人都叫张三了,所以没有必要, 我们在实例出对象后给成员属性初使值就可以了。

如: var  $somevar;

方法(成员函数):

通过在类定义中声明函数,即创建了类的方法。

如: function  somefun(参数列表)

{      ... ...     }

 

<?php

     class Person

     {

         //下面是人的成员属性

         var $name;  //人的名子

         var $sex;    //人的性别

         var $age;    //人的年龄

 

         //下面是人的成员方法

         function say()  //这个人可以说话的方法

         {

              echo "这个人在说话";

         }       

 

         function run()  //这个人可以走路的方法

         {

              echo "这个人在走路";

         }       

     }

?>

上面就是一个类的声明, 从属性和方法上声明出来的一个类, 但是成员属性最好在声明的时候不要给初使的值, 因为我们做的人这个类是一个描述信息, 将来用它实例化对象, 比如实例化出来10个人对象, 那么这10个人, 每一个人的名子, 性别, 年龄都是不一样的, 所以最好不要在这个地方给成员属性赋初值, 而是对每个对象分别赋值的。

用同样的办法可以做出你想要的类了, 只要你能用属性和方法能描述出来的实体都可以定义成类, 去实例化对象。

为了加强你对类的理解, 我们再做一个类, 做一个形状的类, 形状的范围广了点, 我们就做个矩形吧, 先分析一下, 想一想从两方面分析,矩形的属性都有什么? 矩形的功能都有什么?

class 矩形

{

     //矩形的属性

     矩形的长;

     矩形的宽;

    

//矩形的方法

     矩形的周长;

     矩形的面积;

}

 

<?php

    class Rect

    {

        var $kuan;

        var $gao;

 

        function zhouChang()

        {

            计算矩形的周长;

        }

 

        function mianJi()

        {

            计算矩形的面积;   

        }

    }

 

?>

如果用这个类来创建出多个矩形对象,每个矩形对象都有自己的长和宽, 都可以求出自己的周长和面积了。

 类的声明我们就到这里吧!!

 

5.如何实例化对象

我们上面说过面向对象程序的单位就是对象,但对象又是通过类的实例化出来的,既然我们类会声明了,下一步就是实例化对象了。

当定义好类后,我们使用new关键字来生成一个对象。

     $对象名称 = new  类名称();

<?php

     class Person

     {

         //下面是人的成员属性

         var $name;  //人的名子

         var $sex;    //人的性别

         var $age;    //人的年龄

 

         //下面是人的成员方法

         function say()  //这个人可以说话的方法

         {

              echo "这个人在说话";

         }       

 

         function run()  //这个人可以走路的方法

         {

              echo "这个人在走路";

         }       

     }

 

     $p1=new Person();

     $p2=new Person();

     $p3=new Person();

?>

$p1=new Person();

这条代码就是通过类产生实例对象的过程,$p1就是我们实例出来的对象名称, 同理,$p2, $p3也是我们实例出来的对象名称,一个类可以实例出多个对象,每个对象都是独立的,上面的代码相当于实例出来3个人来, 每个人之间是没有联系的, 只能说明他们都是人类, 每个人都有自己的姓名, 性别和年龄的属性,每个人都有说话和走路的方法,只要是类里面体现出来的成员属性和成员方法,实例化出来的对象里面就包含了这些属性和方法。

对像在PHP里面和整型、浮点型一样,也是一种数据类,都是存储不同类型数据用的,在运行的时候都要加载到内存中去用, 那么对象在内存里面是怎么体现的呢?内存从罗辑上说大体上是分为4段, 栈空间段, 堆空间段,代码段, 初使化静态段,程序里面不同的声明放在不同的内存段里面,栈空间段是存储占用相同空间长度并且占用空间小的数据类型的地方,比如说整型1, 10, 100, 1000, 10000, 100000等等,在内存里面占用空间是等长的,都是64位4个字节。 那么数据长度不定长,而且占有空间很大的数据类型的数据放在那内存的那个段里面呢?这样的数据是放在堆内存里面的。栈内存是可以直接存取的,而堆内存是不可以直接存取的内存。对于我们的对象来数就是一种大的数据类型而且是占用空间不定长的类型,所以说对象是放在堆里面的,但对象名称是放在栈里面的,这样通过对象名称就可以使用对象了。 

 

$p1=new Person();

 

对于这个条代码, $p1是对象名称在栈内存里面,new Person()是真正的对象是在堆内存里面的,具体的请看下图:

从上图可以看出$p1=new Person();等号右边是真正的对象实例, 在堆内存里面的实体,上图一共有3次new Person(),所以会在堆里面开辟3个空间,产生3个实例对象,每个对象之间都是相互独立的,使用自己的空间,在PHP里面,只要有一个new这个关键字出现就会实例化出来一个对象,在堆里面开辟一块自己的空间.

每个在堆里面的实例对象是存储属性的,比如说,现在堆里面的实例对象里面都存有姓名、性别和年龄。每个属性又都有一个地址。

$p1=new Person();等号的右边$p1是一个引用变量,通过赋值运算符“=”把对象的首地址赋给“$p1“这个引用变量, 所以$p1是存储对象首地址的变量,$p1放在栈内存里边,$p1相当于一个指针指向堆里面的对象, 所以我们可以通过$p1这个引用变量来操作对象, 通常我们也称对象引用为对象。

 

6.如何去使用对象中的成员

上面看到PHP对象中的成员有两种一种是成员属性, 一种是成员方法。对象我们以经可以声明了,$p1=new Person();  怎么去使用对象的成员呢?要想访问对象中的成员就要使用一个特殊的操作符”->”来完成对象成员的访问:

              对象->属性    $p1->name;        $p2->age;      $p3->sex;

              对象->方法      $p1->say();        $p2->run();
如下面实例:

<?php

     class Person

     {

         //下面是人的成员属性

         var $name;  //人的名子

         var $sex;    //人的性别

         var $age;    //人的年龄

 

         //下面是人的成员方法

         function say()  //这个人可以说话的方法

         {

              echo "这个人在说话";

         }       

 

         function run()  //这个人可以走路的方法

         {

              echo "这个人在走路";

         }       

     }

 

     $p1=new Person();  //创建实例对象$p1

     $p2=new Person();  //创建实例对象$p2

     $p3=new Person();  //创建实例对象$p3

 

    

     //下面三行是给$p1对象属性赋值

     $p1->name=”张三”;  

     $p1->sex=”男”;

     $p1->age=20;

    

     //下面三行是访问$p1对象的属性

     echo “p1对象的名子是:”.$p1->name.”<br>”;

     echo “p1对象的性别是:”.$p1->sex.”<br>”; 

     echo “p1对象的年龄是:”.$p1->age.”<br>”; 

 

     //下面两行访问$p1对象中的方法

     $p1->say();

     $p1->run();

 

//下面三行是给$p2对象属性赋值

     $p2->name=”李四”;

     $p2->sex=”女”;

     $p2->age=30;

 

//下面三行是访问$p2对象的属性

     echo “p2对象的名子是:”.$p2->name.”<br>”;

     echo “p2对象的性别是:”.$p2->sex.”<br>”; 

     echo “p2对象的年龄是:”.$p2->age.”<br>”; 

 

//下面两行访问$p2对象中的方法

     $p2->say();

     $p2->run();

 

     //下面三行是给$p3对象属性赋值

$p3->name=”王五”;

     $p3->sex=”男”;

     $p3->age=40;

 

     //下面三行是访问$p3对象的属性

     echo “p3对象的名子是:”.$p3->name.”<br>”;

     echo “p3对象的性别是:”.$p3->sex.”<br>”; 

     echo “p3对象的年龄是:”.$p3->age.”<br>”; 

    

 

//下面两行访问$p3对象中的方法

     $p3->say();

     $p3->run();

?>

从上例中可以看出只是对象里面的成员就要使用对象->属性 、对象->方法      形式访问,再没有第二种方法来访问对象中的成员了。

 

7.特殊的引用“$this“的使用

现在我们知道了如何访问对象中的成员,是通过”对象->成员”的方式访问的,这是在对象的外部去访问对象中成员的形式, 那么如果我想在对象的内部,让对象里的方法访问本对象的属性, 或是对象中的方法去调用本对象的其它方法这时我们怎么办?因为对象里面的所有的成员都要用对象来调用,包括对象的内部成员之间的调用,所以在PHP里面给我提供了一个本对象的引用$this, 每个对象里面都有一个对象的引用$this来代表这个对象,完成对象内部成员的调用, this的本意就是“这个”的意思, 上面的实例里面,我们实例化三个实例对象$P1、 $P2、 $P3,这三个对象里面各自存在一个$this分别代表对象$p1、$p2、$p3 。

通过上图我们可以看到,$this就是对象内部代表这个对象的引用,在对象内部和调用本对象的成员和对象外部调用对象的成员所使用的方式是一样的。

 

$this->属性    $this->name;              $this->age;     $this->sex;

              $this->方法      $this->say();              $this->run();
修改一下上面的实例,让每个人都说出自己的名字,性别和年龄:

 

<?php

    class Person

    {

        //下面是人的成员属性

        var $name;  //人的名子

        var $sex;    //人的性别

        var $age;    //人的年龄

 

        //下面是人的成员方法

        function say()  //这个人可以说话的方法

        {

        echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."<br>";

        }      

 

        function run()  //这个人可以走路的方法

        {

            echo "这个人在走路";

        }      

    }

 

    $p1=new Person();  //创建实例对象$p1

    $p2=new Person();  //创建实例对象$p2

    $p3=new Person();  //创建实例对象$p3

 

   

    //下面三行是给$p1对象属性赋值

    $p1->name="张三"; 

    $p1->sex="男";

    $p1->age=20;

   

    //下面访问$p1对象中的说话方法

    $p1->say();

   

 

    //下面三行是给$p2对象属性赋值

    $p2->name="李四";

    $p2->sex="女";

    $p2->age=30;

 

    //下面访问$p2对象中的说话方法

    $p2->say();

   

    //下面三行是给$p3对象属性赋值

    $p3->name="王五";

    $p3->sex="男";

    $p3->age=40;

 

    //下面访问$p3对象中的说话方法

    $p3->say();

?>

输出结果为:

 

我的名子叫:张三 性别:男 我的年龄是:20
我的名子叫:李四 性别:女 我的年龄是:30
我的名子叫:王五 性别:男 我的年龄是:40

 

分析一下这个方法:

function say()  //这个人可以说话的方法

{

    echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."<br>";

}      

在$p1、$p2和$p3这三个对象中都有say()这个方法,$this分别代表这三个对象, 调用相应的属性,打印出属性的值,这就是在对象内部访问对象属性的方式, 如果相在say()这个方里调用run()这个方法也是可以的,在say()这个方法中使用$this->run()的方式来完成调用。

 

8.构造方法与析构方法

大多数类都有一种称为构造函数的特殊方法。当创建一个对象时,它将自动调用构造函数,也就是使用new这个关键字来实例化对象的时候自动调用构造方法。

    构造函数的声明与其它操作的声明一样,只是其名称必须是__construct( )。这是PHP5中的变化,以前的版本中,构造函数的名称必须与类名相同,这种在PHP5中仍然可以用,但现在以经很少有人用了,这样做的好处是可以使构造函数独立于类名,当类名发生改变时不需要改相应的构造函数名称了。为了向下兼容,如果一个类中没有名为__construct( )的方法,PHP将搜索一个php4中的写法,与类名相同名的构造方法。

 格式:function __construct ( [参数] ) { ... ... }

在一个类中只能声明一个构造方法,而是只有在每次创建对象的时候都会去调用一次构造方法,不能主动的调用这个方法,所以通常用它执行一些有用的初始化任务。比如对成属性在创建对象的时候赋初值。

<?

       //创建一个人类

class Person

    {

        //下面是人的成员属性

        var $name;  //人的名子

        var $sex;    //人的性别

        var $age;    //人的年龄

 

        //定义一个构造方法参数为姓名$name、性别$sex和年龄$age

        function __construct($name, $sex, $age)

        {

            //通过构造方法传进来的$name给成员属性$this->name赋初使值

            $this->name=$name;

            //通过构造方法传进来的$sex给成员属性$this->sex赋初使值

            $this->sex=$sex;

            //通过构造方法传进来的$age给成员属性$this->age赋初使值

            $this->age=$age;

}

 

//这个人的说话方法

function say()         

{

            echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."<br>";

        }      

}

 

//通过构造方法创建3个对象$p1、p2、$p3,分别传入三个不同的实参为姓名、性别和年龄

$p1=new Person(“张三”,”男”, 20);

$p2=new Person(“李四”,”女”, 30);

$p3=new Person(“王五”,”男”, 40);

 

//下面访问$p1对象中的说话方法

    $p1->say();

    //下面访问$p2对象中的说话方法

    $p2->say();

    //下面访问$p3对象中的说话方法

    $p3->say();

?>

输出结果为:

我的名子叫:张三 性别:男 我的年龄是:20
我的名子叫:李四 性别:女 我的年龄是:30
我的名子叫:王五 性别:男 我的年龄是:40

 

如图:

 

析构函数:

    与构造函数相对的就是析构函数。析构函数是PHP5新添加的内容,在PHP4中没有析构函数。析构函数允许在销毁一个类之前执行的一些操作或完成一些功能,比如说关闭文件, 释放结果集等,析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行,也就是对象在内存中被销毁前调用析构函数。与构造函数的名称类似,一个类的析构函数名称必须是__destruct( )。析构函数不能带有任何参数。

 格式:function __destruct ( ) { ... ... }

 

<?

       //创建一个人类

class Person

       {

              //下面是人的成员属性

              var $name;  //人的名子

              var $sex;    //人的性别

              var $age;    //人的年龄

 

              //定义一个构造方法参数为姓名$name、性别$sex和年龄$age

              function __construct($name, $sex, $age)

              {

                     //通过构造方法传进来的$name给成员属性$this->name赋初使值

                     $this->name=$name;

                     //通过构造方法传进来的$sex给成员属性$this->sex赋初使值

                     $this->sex=$sex;

                     //通过构造方法传进来的$age给成员属性$this->age赋初使值

                     $this->age=$age;

}

 

//这个人的说话方法

function say()             

{

                     echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."<br>";

              }           

             

              //这是一个析构函数,在对象销毁前调用

              function __destruct()

              {

                     echo “再见”.$this->name.”<br>”;

}

}

 

 

//通过构造方法创建3个对象$p1、p2、$p3,分别传入三个不同的实参为姓名、性别和年龄

$p1=new Person(“张三”,”男”, 20);

$p2=new Person(“李四”,”女”, 30);

$p3=new Person(“王五”,”男”, 40);

 

//下面访问$p1对象中的说话方法

       $p1->say();

       //下面访问$p2对象中的说话方法

       $p2->say();

       //下面访问$p3对象中的说话方法

       $p3->say();

?>

输出结果为:

我的名子叫:张三 性别:男 我的年龄是:20
我的名子叫:李四 性别:女 我的年龄是:30
我的名子叫:王五 性别:男 我的年龄是:40

 

再见张三

再见李四

再见王五

9.封装性

封装性是面象对象编程中的三大特性之一,封装性就是把对象的属性和服务结合成一个独立的相同单位,并尽可能隐蔽对象的内部细节,包含两个含义:1.把对象的全部属性和全部服务结合在一起,形成一个不可分割的独立单位(即对象)。2.信息隐蔽,即尽可能隐蔽对象的内部细节,对外形成一个边界〔或者说形成一道屏障〕,只保留有限的对外接口使之与外部发生联系。

    封装的原则在软件上的反映是:要求使对象以外的部分不能随意存取对象的内部数据(属性),从而有效的避免了外部错误对它的"交叉感染",使软件错误能够局部化,大大减少查错和排错的难度。

       用个实例来说明吧, 假如某个人的对象中有年龄和工资等属性,像这样个人隐私的属性是不想让其它人随意就能获得到的,如果你不使用封装,那么别人想知道就能得到,但是如果你封装上之后别人就没有办法获得封装的属性, 除非你自己把它说出去,否则别人没有办法得到。

在比如说,个人电脑都有一个密码,不想让其它人随意的登陆,在你电脑里面拷贝和粘贴。还有就是像人这个对象, 身高和年龄的属性, 只能是自己来增涨,不可以让别人随意的赋值等等。

 

使用private这个关键字来对属性和方法进行封装:

原来的成员:

var $name;                   //声明人的姓名

var $sex;                      //声明人的性别

var $age;                      //声明人的年龄

function run(){…….}

 

改成封装的形式:

private $name;                            //把人的姓名使用private关键字进行封装

private $sex;                                    //把人的性别使用private关键字进行封装

private $age;                                    //把人的年龄使用private关键字进行封装

private function run(){……}          //把人的走路方法使用private关键字进行封装

 

注意:只要是成员属性前面有其它的关键字就要去掉原有的关键字”var”.

 

通过private就可以把人的成员(成员属性和成员方法)封装上了。封装上的成员就不能被类外面直接访问了,只有对象内部自己可以访问;下面的代码会产生错误:

class Person

{

              //下面是人的成员属性

              private $name;  //人的名子,被private封装上了

              private $sex;    //人的性别, 被private封装上了

              private $age;    //人的年龄, 被private封装上了

 

              //这个人可以说话的方法

              function say() 

              {

                     echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."<br>";

              }           

 

              //这个人可以走路的方法, 被private封装上了

              private function run() 

              {

                     echo "这个人在走路";

              }           

       }

       //实例化一个人的实例对象

       $p1=new Person();

      

       //试图去给私有的属性赋值, 结果会发生错误

       $p1->name="张三";

       $p1->sex="男";

       $p1->age=20;

      

       //试图去打印私有的属性, 结果会发生错误

       echo $p1->name.”<br>”;

       echo $p1->sex.”<br>”;

       echo $p1->age.”<br>”

      

       //试图去打印私有的成员方法, 结果会发生错误

       $p1->run();

?>

输出结果为:

Fatal error: Cannot access private property Person::$name

Fatal error: Cannot access private property Person::$sex

Fatal error: Cannot access private property Person::$age

Fatal error: Cannot access private property Person::$name

Fatal error: Call to private method Person::run() from context ''

 

从上面的实例可以看到, 私有的成员是不能被外部访问的, 因为私有成员只能在本对象内部自己访问,比如,$p1这个对象自己想把他的私有属性说出去,在say()这个方法里面访问了私有属性,这样是可以。(没有加任何访问控制,默认的是public的,任何地方都可以访问)

 

//这个人可以说话的方法, 说出自己的私有属性,在这里也可以访问私有方法

function say() 

{

       echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."<br>";

//在这里也可以访问私有方法

//$this->run();

}           

 

因为成员方法say()是公有的, 所以我们在类的外部调用say()方法是可以的,改变上面的代码;

class Person

{

              //下面是人的成员属性

              private $name;  //人的名子,被private封装上了

              private $sex;    //人的性别, 被private封装上了

              private $age;    //人的年龄, 被private封装上了

             

//定义一个构造方法参数为私有的属性姓名$name、性别$sex和年龄$age进行赋值

              function __construct($name, $sex, $age)

              {

                     //通过构造方法传进来的$name给私有成员属性$this->name赋初使值

                     $this->name=$name;

                     //通过构造方法传进来的$sex给私有成员属性$this->sex赋初使值

                     $this->sex=$sex;

                     //通过构造方法传进来的$age给私有成员属性$this->age赋初使值

                     $this->age=$age;

}

 

              //这个人可以说话的方法, 说出自己的私有属性,在这里也可以访问私有方法

              function say() 

              {

                     echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."<br>";

              }           

       }

//通过构造方法创建3个对象$p1、p2、$p3,分别传入三个不同的实参为姓名、性别和年龄

$p1=new Person(“张三”,”男”, 20);

$p2=new Person(“李四”,”女”, 30);

$p3=new Person(“王五”,”男”, 40);

 

//下面访问$p1对象中的说话方法

       $p1->say();

       //下面访问$p2对象中的说话方法

       $p2->say();

       //下面访问$p3对象中的说话方法

       $p3->say();

?>

输出结果为:

我的名子叫:张三 性别:男 我的年龄是:20
我的名子叫:李四 性别:女 我的年龄是:30
我的名子叫:王五 性别:男 我的年龄是:40

 

因为构造方法是默认的公有方法(构造方法不要设置成私有的),所以在类的外面可以访问到,这样就可以使用构造方法创建对象, 另外构造方法也是类里面的函数,所以可以用构造方法给私有的属性赋初值。Say()的方法是默认公有的, 所以在外面也可以访问的到, 说出他自己的私有属性。

 

从上面的例子中我们可以看到, 私有的成员只能在类的内部使用, 不能被类外部直接来存取, 但是在类的内部是有权限访问的, 所以有时候我们需要在类的外面给私有属性赋值和读取出来,也就是给类的外部提供一些可以存取的接口,上例中构造方法就是一种赋值的形式, 但是构造方法只是在创建对象的时候赋值,如果我们已经有一个存在的对象了,想对这个存在的对象赋值, 这个时候,如果你还使用构造方法传值的形式传值, 那么就创建了一个新的对象,并不是这个已存在的对象了。所以我们要对私有的属性做一些可以被外部存取的接口,目的就是可以在对象存在的情况下,改变和存取属性的值,但要注意,只有需要让外部改变的属性才这样做,不想让外面访问的属性是不做这样的接口的,这样就能达到封装的目的,所有的功能都是对象自己来完成,给外面提供尽量少的操作。

       如果给类外部提供接口,可以为私有属性在类外部提供设置方法和获取方法,来操作私有属性.例如:

       prvate $age;   //私有的属性年龄

       function setAge($age)  //为外部提供一个公有设置年龄的方法

       {

              if($age<0 || $age>130) //在给属性赋值的时候,为了避免非法值设置给属性

                     return;

              $this->age=$age;

}

function getAge()             //为外部提供一个公有获取年龄的方法

{

       return($this->age);

}

 

       上面的方法是为一个成员属性设置和获取值, 当然你也可以为每个属性用同样的方法对其进行赋值和取值的操作,完成在类外部的存取工作。

 

10.__set() __get() __isset() __unset()四个方法的应用

一般来说,总是把类的属性定义为private,这更符合现实的逻辑。但是, 对属性的读取和赋值操作是非常频繁的,因此在PHP5中,预定义了两个函数”__get()”和”__set()”来获取和赋值其属性,以及检查属性的”__isset()”和删除属性的方法”__unset()”。

上一节中,我们为每个属性做了设置和获取的方法,在PHP5中给我们提供了专门为属性设置值和获取值的方法,”__set()”和“__get()”这两个方法,这两个方法不是默认存在的, 而是我们手工添加到类里面去的,像构造方法(__construct())一样, 类里面添加了才会存在,可以按下面的方式来添加这两个方法,当然也可以按个人的风格来添加:

//__get()方法用来获取私有属性

function __get($property_name)

        if(isset($this->$property_name)) {

                     return($this->$property_name);

        }else {

                     return(NULL);

        }

}

 

//__set()方法用来设置私有属性

function __set($property_name, $value)

{

              $this->$property_name = $value;

}

 

__get()方法:这个方法用来获取私有成员属性值的,有一个参数, 参数传入你要获取的成员属性的名称,返回获取的属性值, 这个方法不用我们手工的去调用, 是在直接获取私有属性的时候自动调用的。因为私有属性已经被封装上了,是不能直接获取值的(比如:”echo $p1->name” 这样直接获取是错误的),但是如果你在类里面加上了这个方法,在使用”echo $p1->name” 这样的语句直接获取值的时候就会自动调用__get($property_name)方法,将属性name传给参数$property_name,通过这个方法的内部执行,返回我们传入的私有属性的值。 

__set()方法:这个方法用来为私有成员属性设置值的,有两个参数,第一个参数为你要为设置值的属性名,第二个参数是要给属性设置的值,没有返回值。这个方法同样不用我们手工去调用,是在直接设置私有属性值的时候自动调用的,同样属性私有的已经被封装上了, 如果没有__set()这个方法,是不允许的, 比如:”$this->name=’zhangsan’ , 这样会出错,但是如果你在类里面加上了__set($property_name, $value)这个方法,在直接给私有属性赋值的时候,就会自动调用它,把属性比如name传给$property_name, 把要赋的值”zhangsan”传给$value,通过这个方法的执行,达到赋值的目的, 为了不传入非法的值, 还可以在这个方法给做一下判断。代码如下:

 

<?php

       class Person

       {

              //下面是人的成员属性, 都是封装的私有成员

              private $name;  //人的名子

              private $sex;    //人的性别

              private $age;    //人的年龄

 

              //__get()方法用来获取私有属性

              function __get($property_name)

              { 

                      echo "在直接获取私有属性值的时候,自动调用了这个__get()方法<br>";

 if(isset($this->$property_name)) {

                            return($this->$property_name);

                      }else {

                            return(NULL);

                     }

              }

 

              //__set()方法用来设置私有属性

              function __set($property_name, $value)

              {

                     echo "在直接设置私有属性值的时候,自动调用了这个__set()方法为私有属性赋值<br>";

                     $this->$property_name = $value;

              }

 

       }

 

       $p1=new Person();

      

       //直接为私有属性赋值的操作, 会自动调用__set()方法进行赋值

       $p1->name="张三";

       $p1->sex="男";

       $p1->age=20;

      

       //直接获取私有属性的值, 会自动调用__get()方法,返回成员属性的值

       echo "姓名:".$p1->name."<br>";

       echo "性别:".$p1->sex."<br>";

       echo "年龄:".$p1->age."<br>"; 

?>

程序执行结果:

在直接设置私有属性值的时候, 自动调用了这个__set()方法为私有属性赋值
在直接设置私有属性值的时候, 自动调用了这个__set()方法为私有属性赋值
在直接设置私有属性值的时候, 自动调用了这个__set()方法为私有属性赋值
在直接获取私有属性值的时候,自动调用了这个__get()方法
姓名:张三
在直接获取私有属性值的时候,自动调用了这个__get()方法
性别:男
在直接获取私有属性值的时候,自动调用了这个__get()方法
年龄:20

      

以上代码如果不加上__get()和__set()方法,程序就会出错,因为不能在类的外部操作私有成员,而上面的代码是通过自动调用__get()和__set()方法来帮助我们直接存取封装的私有成员的。

 

__isset() 方法:

__unset()方法:

 

11.类的继承

继承作为面向对象的三个重要特性的一个方面,在面向对象的领域有着及其重要的作用,好像没听说哪个面向对象的语言不支持继承。 继承是php5面象对象程序设计的重要特性之一,它是指建立一个新的派生类,从一个或多个先前定义的类中继承数据和函数,而且可以重新定义或加进新数据和函数,从而建立了类的层次或等级。说的简单点就是,继承性是子类自动共享父类数据结构和方法的机制,这是类之间的一种关系。在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并加入若干新的内容。比如你现在已经有一个“人”这个类了,这个类里面有两个成员属性“姓名和年龄”以及还有两个成员方法“说话的方法和走路的方法“, 如果现在程序需要一个学生的类, 因为学生的也是人, 所以学生也有成员属性“姓名和年龄”以及成员方法“说话的方法和走路的方法“,这个时候你就可以让学生类来继承人这个类, 继承之后,学生类就会把人类里面的所有的属性都继承过来, 就不用你再去重新声明一遍这些成员属性和方法了, 因为学生类里面还有所在学校的属性和学习的方法,所以在你做的学生类里面有继承自人类里面的属性和方法之外在加上学生特有的”所在学校属性“和”学习的方法“, 这样一个学生类就声明完成了, 继函我们也可以叫作“扩展”, 从上面我们就可以看出,学生类对人类进行了扩展, 在人类里原有两个属性和两个方法的基础上加上一个属性和一个方法扩展出来一个新的学生类。  

通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。我们称已存在的用来派生新类的类为基类,又称为父类以及超类。由已存在的类派生出的新类称为派生类,又称为子类。

 在软件开发中,类的继承性使所建立的软件具有开放性、可扩充性,这是信息组织与分类的行之有效的方法,它简化了对象、类的创建工作量,增加了代码的可重性。采用继承性,提供了类的规范的等级结构。通过类的继承关系,使公共的特性能够共享,提高了软件的重用性。

在C++语言中,一个派生类可以从一个基类派生,也可以从多个基类派生。从一个基类派生的继承称为单继承;从多个基类派生的继承称为多继承。

             

 

 

    但是在PHP和Java语言里面没有多继承,只有单继承,也就是说,一个类只能直接从一个类中继承数据, 这就是我们所说的单继承。

 

                

   

例如:

下面是“人”类的抽象

 

//定义一个“人”类做为父类

class Person

{

              //下面是人的成员属性

              var $name;  //人的名子

              var $sex;    //人的性别

              var $age;    //人的年龄

             

//定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值

              function __construct($name, $sex, $age)

              {

                     $this->name=$name;

                     $this->sex=$sex;

                     $this->age=$age;

}

 

              //这个人可以说话的方法, 说出自己的属性

              function say() 

              {

                     echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."<br>";

              }           

}

 

下面我们做一个”学生类”,如果不是用继承如下:

//定义一个“人”类做为父类

class Student

{

              //下面是人的成员属性

              var $name;  //人的名子

              var $sex;    //人的性别

              var $age;    //人的年龄

              var $school;  //学生所在学校的属性

 

             

//定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值

              function __construct($name=””, $sex=””, $age=””, $school=””)

              {

                     $this->name=$name;

                     $this->sex=$sex;

                     $this->age=$age;

                     $this->school=$school;

}

 

              //这个人可以说话的方法, 说出自己的属性

              function say() 

              {

                     echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."<br>";

              }           

 

                     //这个学生学习的方法

              function study() 

              {

                     echo "我的名子叫:".$this->name." 我正在”.$this->school.” 学习<br>";

              }           

 

}

 

 

 

 

//定义一个子类“学生类“使用”extends”关键字来继承”人”类

class Student extends Person

{

             

              var $school;  //学生所在学校的属性

      

              //这个学生学习的方法

              function study() 

              {

                     echo "我的名子叫:".$this->name." 我正在”.$this->school.” 学习<br>";

              }           

}

 

       通过上面“Student“类的定义, Student类通过使用”extends”这个关键字把Person 类里的所有成员属性和成员方法都继承过来了, 并扩展了一个所在学校成员属性”school”,和一个学习方法“study()”.  现在子类”Student”里面和使用这个类实例出来的对象都具有如下的属性和方法:

 

学生类”Student”里面的成员属性有:

姓名:name;

年龄:age;

性别:sex;

学校:school;

学生类”Student”里面的成员方法有:

说话方法:say();

学习方法:study();

 

通过上面类继承的使用简化了对象、类的创建工作量,增加了代码的可重性。但是从上面这一个例子上中“可重用性”以及其它的继承性所带来的影响,我们看的还不是特别的明显,你扩展的去想一下,人有无数个岗位,比如上面的学生还有老师,工程师, 医生,工人等,很多很多,如果每个类都定义“人“都共同具有的属性和方法, 想一想会有很大的工作量, 这些属性和方法都可以从“Person”人类里面继承过来。

12.重载新的方法

在学习PHP 这种语言中你会发现, PHP中的方法是不能重载的, 所谓的方法重载就是定义相同的方法名,通过“参数的个数“不同或“参数的类型“不同,来访问我们的相同方法名的不同方法。但是因为PHP是弱类型的语言, 所以在方法的参数中本身就可以接收不同类型的数据,又因为PHP的方法可以接收不定个数的参数,所以通过传递不同个数的参数调用不相同方法名的不同方法也是不成立的。所以在PHP里面没有方法重载。不能重载也就是在你的项目中不能定义相同方法名的方法。另外,因为PHP没有名子空间的概念,在同一个页面和被包含的页面中不能定义相同名称的方法, 也不能定义和PHP给我提供的方法的方法重名,当然在同一个类中也不能定义相同名称的方法。

我们这里所指的重载新的方法所指的是什么呢?其实我们所说的重载新的方法就是子类覆盖父类的已有的方法,那为什么要这么做呢?父类的方法不是可以继承过来直接用吗?但有一些情况是我们必须要覆盖的,比如说我们前面提到过的例子里面, “Person”这个人类里面有一个“说话”的方法,所有继承“Person”类的子类都是可以“说话”的,我们“Student”类就是“Person”类的子类,所以“Student”的实例就可以“说话“了, 但是人类里面“说话”的方法里面说出的是“Person”类里面的属性, 而“Student”类对“Person”类进行了扩展,又扩展出了几个新的属性,如果使用继承过来的“say()”说话方法的话,只能说出从“Person”类继承过来的那些属性,那么新扩展的那些属性使用这个继承过来的“say()”的方法就说不出来了,那有的人就问了,我在“Student”这个子类中再定义一个新的方法用于说话,说出子类里面所有的属性不就行了吗?一定不要这么做, 从抽象的角度来讲, 一个“学生”不能有两种“说话”的方法,就算你定义了两个不同的说话的方法,可以实现你想要的功能,被继承过来的那个“说话“方法可能没有机会用到了,而且是继承过来的你也删不掉。这个时候我们就要用到覆盖了。

虽然说在PHP里面不能定义同名的方法, 但是在父子关系的两个类中,我们可以在子类中定义和父类同名的方法,这样就把父类中继承过来的方法覆盖掉了。

  <?

//定义一个“人”类做为父类

class Person

{

              //下面是人的成员属性

              var $name;  //人的名子

              var $sex;    //人的性别

              var $age;    //人的年龄

             

              //定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值

              function __construct($name, $sex, $age)

              {

                     $this->name=$name;

                     $this->sex=$sex;

                     $this->age=$age;

              }

 

              //这个人可以说话的方法, 说出自己的属性

              function say() 

              {

                     echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."<br>";

              }           

}

 

class Student extends Person

{

             

              var $school;  //学生所在学校的属性

      

              //这个学生学习的方法

              function study() 

              {

                     echo "我的名子叫:".$this->name." 我正在”.$this->school.” 学习<br>";

              }

 

              //这个学性可以说话的方法, 说出自己所有的属性,覆盖了父类的同名方法

              function say() 

              {

                     echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."我在".$this->school."上学.<br>";

              }    

                           

}

?>
上面的例子, 我们就在“Student”子类里覆盖了继承父类里面的”say()”的方法,通过覆盖我们就实现了对“方法”扩展。

但是,像这样做虽然解决了我们上面说的问题,但是在实际开发中,一个方法不可能就一条代码或是几条代码,比如说“Person”类里面的“say()”方法有里面有100条代码,如果我们想对这个方法覆盖保留原有的功能外加上一点点功能,就要把原有的100条代码重写一次, 再加上扩展的几条代码,这还算是好的,而有的情况,父类中的方法是看不见原代码的,这个时候你怎么去重写原有的代码呢?我们也有解决的办法,就是在子类这个方法中可以调用到父类中被覆盖的方法, 也就是把被覆盖的方法原有的功能拿过来再加上自己的一点功能,可以通过两种方法实现在子类的方法中调用父类被覆盖的方法:

一种是使用父类的“类名::“来调用父类中被覆盖的方法;

一种是使用“parent::”的方试来调用父类中被覆盖的方法;

class Student extends Person

{

              var $school;  //学生所在学校的属性

      

              //这个学生学习的方法

              function study() 

              {

                     echo "我的名子叫:".$this->name." 我正在”.$this->school.” 学习<br>";

              }

 

              //这个学性可以说话的方法, 说出自己所有的属性,覆盖了父类的同名方法

              function say() 

              {

                     //使用父类的“类名::“来调用父类中被覆盖的方法;

                     // Person::say();

                    

             

                     //或者使用“parent::”的方试来调用父类中被覆盖的方法;

                     parent::say();

 

                     //加上一点自己的功能

                     echo “我的年龄是:".$this->age."我在".$this->school."上学.<br>";

              }                                

}

现在用两种方式都可以访问到父类中被覆盖的方法,我们选那种方式最好呢?用户可能会发现自己写的代码访问了父类的变量和函数。如果子类非常精炼或者父类非常专业化的时候尤其是这样。 不要用代码中父类文字上的名字,应该用特殊的名字 parent,它指的就是子类在 extends 声明中所指的父类的名字。这样做可以避免在多个地方使用父类的名字。如果继承树在实现的过程中要修改,只要简单地修改类中 extends 声明的部分。

       同样,构造方法在子类中如果没有声明的话,也可以使用父类中的构造方法,如果子类中重新定义了一个构造方法也会覆盖掉父类中的构造方法,如果想使用新的构造方法为所有属性赋值也可以用同样的方式。

class Student extends Person

{

             

              var $school;  //学生所在学校的属性

 

              function __construct($name, $sex, $age, $school)

              {

                     //使用父类中的方法为原有的属性赋值

                     parent::__construct($name, $sex, $age);

                     $this->school=$school;

              }

      

              //这个学生学习的方法

              function study() 

              {

                     echo "我的名子叫:".$this->name." 我正在”.$this->school.” 学习<br>";

              }

 

              //这个人可以说话的方法, 说出自己的属性

              function say() 

              {

                     parent::say();

              //加上一点自己的功能

              echo “我的年龄是:".$this->age."我在".$this->school."上学.<br>";

       }    

                           

}

 

 

13.访问类型

类型的访问修饰符允许开发人员对类成员的访问进行限制,这是PHP5的新特性,但却是OOP语言的一个好的特性。而且大多数OOP语言都已支持此特性。PHP5支持如下3种访问修饰符

public (公有的、默认的),private (私有的)和protected (受保护的)三种.

 

public 公有修饰符,类中的成员将没有访问限制,所有的外部成员都可以访问(读和写)这个类成员(包括成员属性和成员方法),在PHP5之前的所有版本中,PHP中类的成员都是public的, 而且在PHP5中如果类的成员没有指定成员访问修饰符,将被视为public 。
例:public $name;

    public function say(){};

 

private 私有修改符,被定义为private的成员,对于同一个类里的所有成员是可见的,即是没有访问限制;但对于该类的外部代码是不允许改变甚至读操作,对于该类的子类,也不能访问private修饰的成员。
例:  private $var1 = ‘A’;    //属性
     private function getValue(){} //函数

protected保护成员修饰符,被修饰为protected的成员不能被该类的外部代码访问。但是对于该类的子类有访问权限,可以进行属性、方法的读及写操作,该子类的外部代码包括其的子类都不具有访问其属性和方法的权限。

例:protected $name;

    protected function say(){};

 

 

private

protected

public

同一个类中

类的子类中

 

所有的外部成员

 

 

 

<?php
/**
* Define MyClass
*/
class MyClass
{
    public $public = 'Public';
    protected $protected = 'Protected';
    private $private = 'Private';

    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj = new MyClass();
echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private


/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
    // We can redeclare the public and protected method, but not private
    protected $protected = 'Protected2';

    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj2 = new MyClass2();
echo $obj->public; // Works
echo $obj2->private; // Undefined
echo $obj2->protected; // Fatal Error
$obj2->printHello(); // Shows Public, Protected2, not Private

?>

 

 

<?php
/**
* Define MyClass
*/
class MyClass
{
    // Contructors must be public
    public function __construct() { }

    // Declare a public method
    public function MyPublic() { }

    // Declare a protected method
    protected function MyProtected() { }

    // Declare a private method
    private function MyPrivate() { }

    // This is public
    function Foo()
    {
        $this->MyPublic();
        $this->MyProtected();
        $this->MyPrivate();
    }
}

$myclass = new MyClass;
$myclass->MyPublic(); // Works
$myclass->MyProtected(); // Fatal Error
$myclass->MyPrivate(); // Fatal Error
$myclass->Foo(); // Public, Protected and Private work


/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
    // This is public
    function Foo2()
    {
        $this->MyPublic();
        $this->MyProtected();
        $this->MyPrivate(); // Fatal Error
    }
}

$myclass2 = new MyClass2;
$myclass2->MyPublic(); // Works
$myclass2->Foo2(); // Public and Protected work, not Private
?>

      

另外在子类覆盖父类的方法时也要注意一点,子类中方法的访问权限一定不能低于父类被覆盖方法的访问权限,也就是一定要高于或等于父类方法的访问权限。

例如,如果父类方法的访问权限是protected那么子类中要覆盖的权限就要是protected和public,如果父类的方法是public那么子类中要覆盖的方法只能也是public,总之子类中的方法总是要高于或等于父类被覆盖方法的访问权限。

 

 

14.final关键字的应用

       这个关键字只能用来定义类和定义方法, 不能使用final这个关键字来定义成员属性,因为final是常量的意思,我们在PHP里定义常量使用的是define()函数,所以不能使用final来定义成员属性。

       使用final关键标记的类不能被继承;

       final class Person

{

       ……

}

class Student extends Person

{

}    

会出现下面错误:

Fatal error: Class Student may not inherit from final class (Person)

 

使用final关键标记的方法不能被子类覆盖,是最终版本;

 

class Person

{

              final function say() 

              {

                                  

}           

}

 

class Student extends Person

{

              function say() 

              {

                    

              }    

                           

}    

会出现下面错误:

Fatal error: Cannot override final method Person::say()

 

15.static和const关键字的使用

       Static关键字是在类中描述成员属性和成员方法是静态的;静态的成员好处在那里呢?前面我们声明了“Person”的人类,在”Person”这个类里如果我们加上一个“人所属国家”的属性,这样用”Person”这个类实例化出几百个或者更多个实例对象,每个对象里面就都有“所属国家”的属性了,如果开发的项目就是为中国人而开发的,那么每个对象里面就都有一个国家的属性是“中国“其它的属性是不同的,如果我们把“国家”的属性做成静态的成员,这样国家的属性在内存中就只有一个,而让这几百个或更多的对象共用这一个属性,static成员能够限制外部的访问,因为static的成员是属于类的,是不属于任何对象实例,是在类第一次被加载的时候分配的空间,其他类是无法访问的,只对类的实例共享,能一定程度对类该成员形成保护;

       从内存的角度我们来分析一下,内存从逻辑上被分为四段,其中对象是放在“堆内存”里面,对象的引用被放到了“栈内存“里,而静态成员则放到了“初始化静态段”,在类第一次被加载的时候放入的,可以让堆内存里面的每个对象所共享,如下图;

       

类的静态变量,非常类似全局变量,能够被所有类的实例共享,类的静态方法也是一样的,类似于全局函数。

<?

class Person

{

              //下面是人的静态成员属性

              public static $myCountry="中国";

              // var $name;  //人的名子

      

              //这是人的静态成员方法

              public static function say()

              {

                     echo "我是中国人<br>";

              }     

             

}

//输出静态属性

echo Person::$myCountry;

 

//访问静态方法

Person::say();

 

//重新给静态属性赋值

Person::$myCountry="美国";

echo Person::$myCountry;

 

?>

       因为静态成员是在类第一次加载的时候就创建的,所以在类的外部不需要对象而使用类名就可以访问的到静态的成员;上面说过,静态成员被这个类的每个实例对象所共享,那么我们使用对象可不可以访问类中的静态成员呢?从上图中我们可以看到,静态的成员不是在每个对象内部存在的,但是每个对象都可以共享,所以我们如果使用对象访问成员的话就会出现没有这个属性定义,使用对象访问不到静态成员的,在其它的面向对象的语言中,比如Java是可以使用对象的方式访问静态成员的,如果PHP中可以使用对象访问静态成员的话,我们也尽量不要去使用,因为静态的成员我们在做项目的时候目的就是使用类名去访问。

       类里面的静态方法只能访问类的静态的属性,在类里面的静态方法是不能访问类的非静态成员的,原因很简单,我们要想在本类的方法中访问本类的其它成员,我们需要使用$this这个引用,而$this这个引用指针是代表调用此方法的对象,我们说了静态的方法是不用对象调用的,而是使用类名来访问,所以根本就没有对象存在,也就没有$this这个引用了,没有了$this这个引用就不能访问类里面的非静态成员,又因为类里面的静态成员是可以不用对象来访问的,所以类里面的静态方法只能访问类的静态的属性,即然$this不存在,在静态方法中访其它静态成员我们使用的是一个特殊的类”self”; self和$this相似,只不过self是代表这个静态方法所在的类。所以在静态方法里,可以使用这个方法所在的类的“类名“,也可以使用“self“来访问其它静态成员,如果没有特殊情况的话,我们通常使用后者,即”self::成员属性”的方式。

<?

class Person

{

              //下面是人的静态成员属性

              public static $myCountry="中国";

      

              //这是人的静态成员方法, 通过self访问其它静态成员

              public static function say()

              {

                     echo "我是".self::$myCountry."<br>";

              }     

             

}

//访问静态方法

Person::say();

?>

       在非静态方法里可不可以访问静态成员呢,当然也是可以的了,但是也不能使用”$this”引用也要使用类名或是”self::成员属性的形式”。

       const是一个定义常量的关键字,在PHP中定义常量使用的是”define()”这个函数,但是在类里面定义常量使用的是”const”这个关键字,类似于C中的#define如果在程序中改变了它的值,那么会出现错误,用”const”修饰的成员属性的访问方式和”static”修饰的成员访问的方式差不多,也是使用”类名”,在方法里面使用”self”关键字。但是不用使用”$”符号,也不能使用对象来访问。

<?php
class MyClass
{

//定义一个常量constant
    const constant = 'constant value';

    function showConstant() {
        echo  self::constant . "/n";  //使用self访问,不要加”$”
    }
}

echo MyClass::constant . "/n";  //使用类名来访问,也不加”$”

$class = new MyClass();
$class->showConstant();
// echo $class::constant;  是不允许的

?>

 

16.__toString()方法

       我们前面说过在类里面声明“--”开始的方法名的方法(PHP给我们提供的),都是在某一时刻不同情况下自动调用执行的方法,“__toString()”方法也是一样自动被调用的,是在直接输出对象引用时自动调用的, 前面我们讲过对象引用是一个指针,比如说:“$p=new Person()“中,$p就是一个引用,我们不能使用echo 直接输出$p, 这样会输出”Catchable fatal error: Object of class Person could not be converted to string“这样的错误,如果你在类里面定义了“__toString()”方法,在直接输出对象引用的时候,就不会产生错误,而是自动调用了”__toString()”方法, 输出“__toString()”方法中返回的字符,所以“__toString()”方法一定要有个返回值(return 语句).

 

<?php
// Declare a simple class
class TestClass
{
    public $foo;

    public function __construct($foo) {
        $this->foo = $foo;
    }
  //定义一个__toString方法,返加一个成员属性$foo
    public function __toString() {
        return $this->foo;
    }
}

$class = new TestClass('Hello');

//直接输出对象
echo $class;
?>

上例输出:Hello

17.克隆对象

       有的时候我们需要在一个项目里面,使用两个或多个一样的对象,如果你使用“new”关键字重新创建对象的话,再赋值上相同的属性,这样做比较烦琐而且也容易出错,所以要根据一个对象完全克隆出一个一模一样的对象,是非常有必要的,而且克隆以后,两个对象互不干扰。

 

在PHP5中我们使用”clone”这个关键字克隆对象;

<?

class Person

{

              //下面是人的成员属性

              var $name;  //人的名子

              var $sex;    //人的性别

              var $age;    //人的年龄

             

              //定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值

              function __construct($name="", $sex="", $age="")

              {

                     $this->name=$name;

                     $this->sex=$sex;

                     $this->age=$age;

              }

 

              //这个人可以说话的方法, 说出自己的属性

              function say() 

              {

                     echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."<br>";

              }

}

 

$p1=new Person("张三", "男", 20);

//使用“clone”克隆新对象p2,和p1对象具有相同的属性和方法。

$p2=clone $p1;

 

$p2->say();

 

?>

 

PHP5定义了一个特殊的方法名“__clone()”方法,是在对象克隆时自动调用的方法,用“__clone()”方法将建立一个与原对象拥有相同属性和方法的对象,如果想在克隆后改变原对象的内容,需要在__clone()中重写原本的属性和方法, ”__clone()”方法可以没有参数,它自动包含$this和$that两个指针,$this指向复本,而$that指向原本;

 

class Person

{

              //下面是人的成员属性

              var $name;  //人的名子

              var $sex;    //人的性别

              var $age;    //人的年龄

             

              //定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值

              function __construct($name="", $sex="", $age="")

              {

                     $this->name=$name;

                     $this->sex=$sex;

                     $this->age=$age;

              }

 

              //这个人可以说话的方法, 说出自己的属性

              function say() 

              {

                     echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."<br>";

              }

             

              //对象克隆时自动调用的方法, 如果想在克隆后改变原对象的内容,需要在__clone()中重写原本的属性和方法

              function __clone()

              {

                     //$this指的复本p2, 而$that是指向原本p1,这样就在本方法里,改变了复本的属性。

                     $this->name="我是假的$that->name";

                     $this->age=30;

              }           

}

 

$p1=new Person("张三", "男", 20);

 

$p2=clone $p1;

$p1->say();

$p2->say();

?>

上例输出:

我的名子叫:张三 性别:男 我的年龄是:20
我的名子叫:我是假的张三 性别:男 我的年龄是:30

 

18.__call处理调用错误

       在程序开发中,如果在使用对象调用对象内部方法时候,调用的这个方法不存在那么程序就会出错,然后程序退出不能继续执行。那么可不可以在程序调用对象内部不存在的方法时,提示我们调用的方法及使用的参数不存在,但程序还可以继续执行,这个时候我们就要使用在调用不存在的方法时自动调用的方法”__call()”.

 

<?php

//这是一个测试的类,里面没有属性和方法

class Test

{

 

}

 

//产生一个Test类的对象

$test=new Test();

 

//调用对象里不存在的方法

$test->demo("one", "two", "three");

 

//程序不会执行到这里

echo "this is a test<br>";

 

?>

 

上例出现如下错误,程序通出不能继续执行;

Fatal error: Call to undefined method Test::demo()

 

下面我们加上“__call()”方法,这个方法有2个参数,第一个参数为调用不存在的方法过程中,自动调用__call()方法时,把这个不存在的方法的方法名传给第一个参数,第二个参数则是把这个方法的多个参数以数组的形式传进来。

<?php

//这是一个测试的类,里面没有属性和方法

class Test

{

       //调用不存的方法时自动调用的方法,第一个参数为方法名,第二个参数是数组参数

       function __call($function_name, $args)

       {

print "你所调用的函数:$function_name(参数:";

              print_r($args);

              print ")不存在!<br>/n";

       }

}

 

//产生一个Test类的对象

$test=new Test();

 

//调用对象里不存在的方法

$test->demo("one", "two", "three");

 

//程序不会退出可以执行到这里

echo "this is a test<br>";

?>

上例输出结果为:

你所调用的函数: demo(参数:Array ( [0] => one [1] => two [2] => three ) )不存在!
this is a test.

 

19.抽象方法和抽象类

在OOP语言中,一个类可以有一个或多个子类,而每个类都有至少一个公有方法做为外部代码访问其的接口。而抽象方法就是为了方便继承而引入的,我们先来看一下抽象类和抽象方法的定义再说明它的用途.

 什么是抽象方法?我们在类里面定义的没有方法体的方法就是抽象方法,所谓的没有方法体指的是,在方法声明的时候没有大括号以及其中的内容,而是直接在声明时在方法名后加上分号结束,另外在声明抽象方法时还要加一个关键字“abstract”来修饰;

例如:

abstract function fun1();

abstract function fun2();

    上例是就是“abstract”修饰的没有方法体的抽象方法“fun1()”和“fun2()”,不要忘记抽象方法后面还要有一个分号;那么什么是抽象类呢?只要一个类里面有一个方法是抽象方法,那么这个类就要定义为抽象类,抽象类也要使用“abstract”关键字来修饰;在抽象类里面可以有不是抽象的方法和成员属性,但只要有一个方法是抽象的方法,这个类就必须声明为抽象类,使用”abstract”来修饰。

    例如:

    abstract class Demo

    {

           var $test;

 

       abstract function fun1();

abstract function fun2();

function fun3()

{

    ….

}

}

    上例中定义了一个抽象类“Demo”使用了”abstract”来修饰, 在这个类里面定义了一个成员属性“$test”,和两个抽象方法“fun1”和“fun2”还有一个非抽象的方法fun3();那么抽象类我们怎么使用呢?最重要的一点就是抽象类不能产生实例对象,所以也不能直接使用,前面我们多次提到过类不能直接使用,我们使用的是通过类实例化出来的对象,那么抽象类不能产生实例对象我们声明抽象类有什么用呢?我们是将抽象方法是做为子类重载的模板使用的,定义抽象类就相当于定义了一种规范,这种规范要求子类去遵守,子类继函抽象类之后,把抽象类里面的抽象方法按照子类的需要实现。子类必须把父类中的抽象方法全部都实现,否则子类中还存在抽象方法,那么子类还是抽象类,还是不能实例化对;为什么我们非要从抽象类中继承呢?因为有的时候我们要实现一些功能就必须从抽象类中继承,否则这些功能你就实现不了,如果继承了抽象类,就要实现类其中的抽象方法;

<?

abstract class Demo

    {

           var $test;

 

        abstract function fun1();

abstract function fun2();

function fun3()

{

    ….

}

}

 

$demo=new Demo();  //抽象类为能产生实例对象,所以这样做是错的,实例化对象交给子类

 

class Test extends Demo

{

    function fun1()

    {

       …

}

function fun2()

{

    …

}

}

 

$test=new Test(); //子类可以实例化对象,因为实现了父类中所有抽象方法

?>

 

 

20. php5接口技术

       PHP与大多数面向对象编程语言一样,不支持多重继承.也就是说每个类只能继承一个父类.为了解决这个问题,PHP引入了接口,接口的思想是指定了一个实现了该接口的类必须实现的一系列方法.接口是一种特殊的抽象类,抽象类又是一种特殊的类,所以接口也是一种特殊的类,为什么说接口是一种特殊的抽象类呢?如果一个抽象类里面的所有的方法都是抽象方法,那么我们就换一种声明方法使用“接口“;也就是说接口里面所有的方法必须都是声明为抽象方法,另外接口里面不能声明变量,而且接口里面所有的成员都是public权限的。所以子类在实现的时候也一定要使用public权限实限。

声明一个类的时候我们使用的关键字是”class”,而接口一种特殊的类,使用的关键字是“interface”;

类的定义:  class 类名{ … } ,接口的声明:interface 接口名{ …}

<?php

       //定义一个接口使用interface关键字,“One”为接口名称

      

interface One

       {

               //定义一个常量

const constant = 'constant value';

 

              //定义了一个抽象方法”fun1”

              public function fun1();

      

              //定义了抽象方法”fun2”

              public function fun2();

       }

?>

上例中定义了一个接口”one”,里面声明了两个抽象方法“fun1”和”fun2”,因为接口里面所有的方法都是抽象方法,所以在声明抽象方法的时候就不用像抽象类那样使用”abstract”这个关键字了,默认的已经加上这个关键字,另外在接口里边的”public”这个访问权限也可以去掉,因为默认就是public的,因为接口里所有成员都要是公有的,所在对于接口里面的成员我们就不能使用“private”的和”protected”的权限了,都要用public或是默认的。另外在接口里面我们也声明了一个常量“constant“, 因为在接口里面不能用变量成员,所以我们要使用const这个关键字声明。

因为接口是一种特殊的抽象类,里面所有的方法都是抽象方法,所以接口也不能产生实例对象; 它也做为一种规范,所有抽象方法需要子类去实现。
      

我们可以使用”extends”关键字让一个接口去继承另一个接口;

<?php

       //使用”extends”继承另外一个接口

interface Two extends One

       {

              function fun3();

              function fun4();

       }

?>

而我们定义一接口的子类去实现接口中全部抽象方法使用的关键字是”implements”,而不是我们前面所说的”extends”;

 

<?php

       //使用“implements”这个关键字去实现接口中的抽象方法

       class Three implements One

       {

              function fun1()

              {

                     ….

              }

 

              function fun2()

              {

                     ….

              }

       }

       //实现了全部方法,我们去可以使用子类去实例化对象了

       $three=new Three();

?>

 

我们也可以使用抽象类,去实现接口中的部分抽象方法,但要想实例化对象,这个抽象类还要有子类把它所有的抽象方法都实现才行;

在前面我们说过,PHP是单继承的,一个类只能有一父类,但是一个类可以实现多个接口,就相当于一个类要遵守多个规范,就像我们不仅要遵守国家的法律,如果是在学校的话,还要遵守学校的校规一样;

<?php

       //使用implements实现多个接口

       class Four implemtns 接口一, 接口二, ….

       {

              //必须把所有接口中的方法都要实现才可以实例化对象。

}

?>

 

PHP中不仅一个类可以实现多个接口,也可以在继承一个类的同时实现多个接口, 一定要先继承类再去实现接口;

<?php

       //使用extends继承一个类,使用implements实现多个接口

       class Four extends 类名一 implemtns 接口一, 接口二, ….

       {

              //所有接口中的方法都要实现才可以实例化对象

………..

}

?>

 

 

21.多态的应用

       多态是除封装和继承之外的另一个面象对象的三大特性之一,我个人看来PHP中虽然可以实现多态,但和c++还有Java这些面向对象的语言相比,多态性并不是那么突出,因为PHP本身就是一种弱类型的语言,不存在父类对象转化为子类对象或者是子类对象转化为父类对象的问题,所以多态的应用并不是那么的明显;所谓多态性是指一段程序能够处理多种类型对象的能力,比如说在公司上班,每个月财务发放工资,同一个发工资的方法,在公司内不同的员工或是不同职位的员工,都是通过这个方法发放的,但是所发的工资都是不相同的。所以同一个发工资的方法就出现了多种形态。对于面向对象的程序来说,多态就是把子类对象赋值给父类引用,然后调用父类的方法,去执行子类覆盖父类的那个方法,但在PHP里是弱类型的,对象引用都是一样的不分父类引用,还是子类引用。

我们现在来看一个例子,首先还是要使用多态就要有父类对象和子类对象的关系。做一个形状的接口或是抽象类做为父类,里面有两个抽象方法,一个求周长的方法,另一个是求面积的方法;这接口的子类是多种不同的形状,每个形状又都有周长和面积,又因为父类是一个接口,所以子类里面就必须要实现父类的这两个周长和面积的抽象方法,这样做的目的是每种不同形状的子类都遵守父类接口的规范,都要有求周长和求面积的方法。

<?

       //定义了一个形状的接口,里面有两个抽象方法让子类去实现

       interface Shape

       {

              function area();

              function  perimeter();

       }

 

       //定义了一个矩形子类实现了形状接口中的周长和面积

       class Rect implements Shape

       {

              private $width;

              private $height;

 

              function __construct($width, $height)

              {

                     $this->width=$width;

                     $this->height=$height;

              }

 

              function area()

              {

                     return "矩形的面积是:".($this->width*$this->height);

              }

      

              function perimeter()

              {

                     return "矩形的周长是:".(2*($this->width+$this->height));

              }

       }

       //定义了一个圆形子类实现了形状接口中的周长和面积

       class  Circular implements Shape

       {

              private $radius;

 

              function __construct($radius)

              {

                     $this->radius=$radius;

              }

 

              function area()

              {

                     return "圆形的面积是:".(3.14*$this->radius*$this->radius);

              }

      

              function perimeter()

              {

                     return "圆形的周长是:".(2*3.14*$this->radius);

              }

 

             

       }     

      

       //把子类矩形对象赋给形状的一个引用

       $shape=new Rect(5, 10);

      

       echo $shape->area()."<br>";

       echo $shape->perimeter()."<br>";

 

       //把子类圆形对象赋给形状的一个引用

       $shape=new Circular(10);

      

       echo $shape->area()."<br>";

       echo $shape->perimeter()."<br>";

?>

上例执行结果:

矩形的面积是:50
矩形的周长是:30
圆形的面积是:314
圆形的周长是:62.8

 

       通过上例我们看到,把矩形对象和圆形对象分别赋给了变量$shape, 调用$shape引用中的面积和周长的方法,出现了不同的结果,这就是一种多态的应用,其实在我们PHP这种弱类形的面向对象的语言里面,多态的特性并不是特别的明显,其实就是对象类型变量的变项应用。

 

 

 

22.把对象串行化

有时候需要把一个对象在网络上传输,为了方便传输,可以把整个对象转化为二进制串,等到达另一端时,再还原为原来的对象,这个过程称之为串行化, 就像我们现在想把一辆汽车通过轮船运到美国去,因为汽车的体积比较大,我们可以把汽车拆开成小的部件,然后我们把这些部件通过轮般运到美国去,到了美国再把这些部件组装回汽车。

有两种情况我们必须把对象串行化,第一种情况就是把一个对象在网络中传输的时候要将对象串行化,第二种情况就是把对象写入文件或是数据库的时候用到串行化。

串行化有两个过程,一个是串行化,就是把对象转化为二进制的字符串,我们使用serialize()函数来串行化一个对象,另一个是反串行化,就是把对象转化的二进制字符串再转化为对象, 我们使用unserialize()函数来反串行化一个对象.

PHP中serialize()函数的参数为对象名,返回值为一个字符串,Serialize()返回的字符串含义模糊,一般我们不会解析这个串来得到对象的信息,我们只要把返回来的这个字符串传到网络另一端或是保存到方件中即可。

PHP中unserialize()函数来反串行化对象,这个函数的参数即为serialize()函数的返回值,输出当然是重新组织好的对象.

<?

class Person

{

        //下面是人的成员属性

        var $name;  //人的名子

        var $sex;    //人的性别

        var $age;    //人的年龄

       

        //定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值

        function __construct($name="", $sex="", $age="")

        {

            $this->name=$name;

            $this->sex=$sex;

            $this->age=$age;

        }

 

        //这个人可以说话的方法, 说出自己的属性

        function say() 

        {

            echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."<br>";

        }

 

}

 

 

$p1=new Person("张三", "男", 20);

 

$p1_string=serialize($p1); //把一个对象串行化,返一个字符串

 

echo $p1_string."<br>";  //串行化的字符串我们通常不去解析

 

$p2=unserialize($p1_string);  //把一个串行化的字符串反串行化形成对象$p2

 

$p2->say();

 

?>

上例输出结果:

O:6:"Person":3:{s:4:"name";s:4:"张三";s:3:"sex";s:2:"男";s:3:"age";i:20;}
我的名子叫:张三 性别:男 我的年龄是:20

 

在php5中有两个魔术方法__sleep()方法和__wakeup()方法,在对象串行化的时候,会调用一个__sleep()方法来完成一些睡前的事情;而在重新醒来,即由二进制串重新组成一个对象的时候,则会自动调用PHP的另一个函数__wakeup(),做一些对象醒来就要做的动作。

__sleep()函数不接受任何参数, 但返回一个数组,其中包含需要串行化的属性。末被包含的属性将在串行化时被忽略,如果没有__sleep()方法,PHP将保存所有属性。

 

<?

class Person

{

        //下面是人的成员属性

        var $name;  //人的名子

        var $sex;    //人的性别

        var $age;    //人的年龄

       

        //定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值

        function __construct($name="", $sex="", $age="")

        {

            $this->name=$name;

            $this->sex=$sex;

            $this->age=$age;

        }

 

        //这个人可以说话的方法, 说出自己的属性

        function say() 

        {

            echo "我的名子叫:".$this->name." 性别:".$this->sex." 我的年龄是:".$this->age."<br>";

        }

 

        //指定串行化时把返回的数组中$name和$age值串行化,忽略没在数组中的属性$sex

        function __sleep() {

            $arr=array("name", "age");

            return($arr);

        }

        //重新生成对象时,并重新赋值$age为40

        function __wakeup() {

             $this->age = 40;

        }

 

}

 

 

$p1=new Person("张三", "男", 20);

 

//把一个对象串行化,返一个字符串,调用了__sleep()方法,忽略没在数组中的属性$sex

$p1_string=serialize($p1);

echo $p1_string."<br>";  //串行化的字符串我们通常不去解析

 

$p2=unserialize($p1_string); //反串行化形成对象$p2重新赋值$age为40

 

$p2->say();

?>

上例输出值为:

O:6:"Person":2:{s:4:"name";s:4:"张三";s:3:"age";i:20;}
我的名子叫:张三 性别: 我的年龄是:40

 

 

23.自动加载类

很多开发者写面向对象的应用程序时,对每个类的定义建立一个 PHP 源文件。一个很大的烦恼是不得不在每个脚本(每个类一个文件)开头写一个长长的包含文件的列表。

在软件开发的系统中,不可能把所有的类都写在一个PHP文件中,当在一个PHP文件中需要调用另一个文件中声明的类时,就需要通过include把这个文件引入。不过有的时候,在文件众多的项目中,要一一将所需类的文件都include进来,是一个很让人头疼的事,所以我们能不能在用到什么类的时候,再把这个类所在的php文件导入呢?这就是我们这里我们要讲的自动加载类。

在 PHP 5 中,可以定义一个 __autoload()函数,它会在试图使用尚未被定义的类时自动调用,通过调用此函数,脚本引擎在 PHP 出错失败前有了最后一个机会加载所需的类, __autoload()函数接收的一个参数,就是你想加载的类的类名,所以你做项目时,在组织定义类的文件名时,需要按照一定的规则,最好以类名为中心,也可以加上统一的前缀或后缀形成文件名,比如xxx_classname.php、classname_xxx.php以及就是classname.php等等.

 

本例尝试分别从 MyClass1.php 和 MyClass2.php 文件中加载 MyClass1 和 MyClass2 类

<?php


function __autoload($classname)

{
    require_once $classname . '.php';
}


//MyClass1类不存在自动调用__autoload()函数,传入参数”MyClass1”
$obj  = new MyClass1();

 

//MyClass2类不存在自动调用__autoload()函数,传入参数”MyClass2”
$obj2 = new MyClass2();
?>

申明:本资源来源于互联网,如有侵权,请联系本人或者CSDN进行删除,谢谢!细说PHP》开发Web应用程序PHP是最理想的工具,易于使用、功能强大、成本低廉、高安全性、开发速度快且执行灵活。《细说PHP》以实用为目标设计,包含PHP开发最主流的各项技术,对每一个知识点都进行了深入详细的讲解,并附有大量的实例代码,图文并茂。系统地介绍了PHP的相关技术及其在实际Web开发中的应用。 《细说PHP》共17章,每一章都是PHP独立知识点的总结。内容涵盖了PHP的运行环境搭建、Web服务器Apache的配置与应用、动态网站开发的前台技术PHP编程语言的语法、PHP的常用功能模块和实用技巧、MySQL数据库的设计与应用、PHP 5面向对象的程序设计思想、Web开发的设计模式,以及包含DIV+CSS、mysqli扩展模块、数据库抽象层PDO、Smarty模板技术等目前PHP开发中最主流的技术。每一章中都有大量的实用示例,以及详尽的注释,加速读者的理解和学习,也为每章的技术点设置了大量的自测试题。最后以一个比较完整的、采用面向对象思想,以及通过MVC模式设计,并结合Smarty模板的CMS系统为案例,详细介绍了Web系统开发从设计到部署的各个细节,更好地进行开发实践。 申明:本资源来源于互联网,如有侵权,请联系本人或者CSDN进行删除,谢谢!
php和mysql web开发(原书第4版)》:开发人员专业技术丛书。 目录 读者反馈 译者序 前言 作者简介 第一篇 使用PHP 第1章 PHP快速入门教程 1.1 开始之前:了解PHP 1.2 创建一个示例应用:Bob汽车零部件商店 1.2.1 创建订单表单 1.2.2 表单处理 1.3 在HTML中嵌入PHP 1.3.1 使用PHP标记 1.3.2 PHP语句 1.3.3 空格 1.3.4 注释 1.4 添加动态内容 1.4.1 调用函数 1.4.2 使用date()函数 1.5 访问表单变量 1.5.1 简短、中等以及长风格的表单变量 1.5.2 字符串的连接 1.5.3 变量和文本 1.6 理解标识符 1.7 检查变量类型 1.7.1 PHP的数据类型 1.7.2 类型强度 1.7.3 类型转换 1.7.4 可变变量 1.8 声明和使用常量 1.9 理解变量的作用域 1.10 使用操作符 1.10.1 算术操作符 1.10.2 字符串操作符 1.10.3 赋值操作符 1.10.4 比较操作符 1.10.5 逻辑操作符 1.10.6 位操作符 1.10.7 其他操作符 1.11 计算表单总金额 1.12 理解操作符的优先级和结合性: 1.13 使用可变函数 1.13.1 测试和设置变量类型 1.13.2 测试变量状态 1.13.3 变量的重解释 1.14 根据条件进行决策 1.14.1 if语句 1.14.2 代码块 1.14.3 else语句 1.14.4 elseif语句 1.14.5 switch语句 1.14.6 比较不同的条件 1.15 通过迭代实现重复动作 1.15.1 while循环 1.15.2 for和foreach循环 1.15.3 do...while循环 1.16 从控制结构或脚本中跳出 1.17 使用可替换的控制结构语法 1.18 使用declare 1.19 下一章 第2章 数据的存储与检索 2.1 保存数据以便后期使用 2.2 存储和检索Bob的订单 2.3 文件处理 2.4 打开文件 2.4.1 选择文件模式 2.4.2 使用fopen()打开文件 2.4.3 通过FTP或HTTP打开文件 2.4.4 解决打开文件时可能遇到的问题 2.5 写文件 2.5.1 fwrite()的参数 2.5.2 文件格式 2.6 关闭文件 2.7 读文件 2.7.1 以只读模式打开文件:fopen() 2.7.2 知道何时读完文件:feof() 2.7.3 每次读取一行数据:fgets()、fgetss()和fgetcsv() 2.7.4 读取整个文件:readfile()、fpassthru()和file() 2.7.5 读取一个字符:fgetc() 2.7.6 读取任意长度:fread() 2.8 使用其他有用的文件函数 2.8.1 查看文件是否存在:file_exists() 2.8.2 确定文件大小:filesize() 2.8.3 删除一个文件:unlink() 2.8.4 在文件中定位:rewind()、fseek()和ftell() 2.9 文件锁定 2.10 更好的方式:数据库管理系统 2.10.1 使用普通文件的几个问题 2.10.2 RDBMS是如何解决这些问题的 2.11 进一步学习 2.12 下一章 第3章 使用数组 3.1 什么是数组 3.2 数字索引数组 3.2.1 数字索引数组的初始化 3.2.2 访问数组的内容 3.2.3 使用循环访问数组 3.3 使用不同索引的数组 3.3.1 初始化相关数组 3.3.2 访问数组元素 3.3.3 使用循环语句 3.4 数组操作符 3.5 多维数组 3.6 数组排序 3.6.1 使用sort()函数 3.6.2 使用asort()函数和ksort()函数对相关数组排序 3.6.3 反向排序 3.7 多维数组的排序 3.7.1 用户定义排序 3.7.2 反向用户排序 3.8 对数组进行重新排序 3.8.1 使用shuffle()函数 3.8.2 使用array_reverse()函数 3.9 从文件载入数组 3.10 执行其他的数组操作 3.10.1 在数组中浏览:each()、current()、reset()、end()、next()、pos()和prev() 3.10.2 对数组的每一个元素应用任何函数:array_walk() 3.10.3 统计数组元素个数:count()、sizeof()和array_count_values() 3.10.4 将数组转换成标量变量:extract() 3.11 进一步学习 3.12 下一章 第4章 字符串操作与正则表达式 4.1 创建一个示例应用程序:智能表单邮件 4.2 字符串的格式化 4.2.1 字符串的整理:chop()、ltrim()和trim() 4.2.2 格式化字符串以便显示 4.2.3 格式化字符串以便存储:addslashes()和stripslashes() 4.3 用字符串函数连接和分割字符串 4.3.1 使用函数explode()、implode()和join() 4.3.2 使用strtok()函数 4.3.3 使用substr()函数 4.4 字符串的比较 4.4.1 字符串的排序:strcmp()、strcasecmp()和strnatcmp() 4.4.2 使用strlen()函数测试字符串的长度 4.5 使用字符串函数匹配和替换子字符串 4.5.1 在字符串中查找字符串:strstr()、strchr()、strrchr()和stristr() 4.5.2 查找子字符串的位置:strpos()、strrpos() 4.5.3 替换子字符串:str_replace()、substr_replace() 4.6 正则表达式的介绍 4.6.1 基础知识 4.6.2 字符集和类 4.6.3 重复 4.6.4 子表达式 4.6.5 子表达式计数 4.6.6 定位到字符串的开始或末尾 4.6.7 分支 4.6.8 匹配特殊字符 4.6.9 特殊字符一览 4.6.10 在智能表单中应用 4.7 用正则表达式查找子字符串 4.8 使用正则表达式分割字符串 4.9 比较字符串函数和正则表达式函数 4.10 进一步学习 4.11 下一章 第5章 代码重用与函数编写 5.1 代码重用的好处 5.1.1 成本 5.1.2 可靠性 5.1.3 一致性 5.2 使用require()和include()函数 5.2.1 文件扩展名和require()语句 5.2.2 使用require()制作Web站点的模版 5.2.3 使用auto_prepend_file和auto_append_file 5.3 在PHP中使用函数 5.3.1 调用函数 5.3.2 调用未定义的函数 5.3.3 理解字母大小写和函数名称 5.4 理解为什么要定义自己的函数 5.5 了解基本的函数结构 5.5.1 函数命名 5.6 使用参数 5.7 理解作用域 5.8 参数的引用传递和值传递 5.9 使用Return关键字 5.9.1 从函数返回一个值 5.10 实现递归 5.10.1 名称空间 5.11 进一步学习 5.12 下一章 第6章 面向对象PHP 6.1 理解面向对象的概念 6.1.1 类和对象 6.1.2 多态性 6.1.3 继承 6.2 在PHP中创建类、属性和操作 6.2.1 类的结构 6.2.2 构造函数 6.2.3 析构函数 6.3 类的实例化 6.4 使用类的属性 6.5 使用private和public关键字控制访问 6.6 类操作的调用 6.7 在PHP中实现继承 6.7.1 通过继承使用private和protected访问修饰符控制可见性 6.7.2 重载 6.7.3 使用final关键字禁止继承和重载 6.7.4 理解多重继承 6.7.5 实现接口 6.8 类的设计 6.9 编写类代码 6.10 理解PHP面向对象新的高级功能 6.10.1 使用Per-Class常量 6.10.2 实现静态方法 6.10.3 检查类的类型和类型提示 6.10.4 克隆对象 6.10.5 使用抽象类 6.10.6 使用__call()重载方法 6.10.7 使用__autoload()方法 6.10.8 实现迭代器和迭代 6.10.9 将类转换成字符串 6.10.10 使用Reflection(反射)API 6.11 下一章 第7章 错误和 异常处理 7.1 异常处理的概念 7.2 Exception类 7.3 用户自定义异常 7.4 Bob的汽车零部件商店应用程序的异常 7.5 异常和PHP的其他错误处理机制 7.6 进一步学习 7.7 下一章 第二篇 使用MySQL 第8章 设计Web数据库 8.1 关系数据库的概念 8.1.1 表格 8.1.2 列 8.1.3 行 8.1.4 值 8.1.5 键 8.1.6 模式 8.1.7 关系 8.2 如何设计Web数据库 8.2.1 考虑要建模的实际对象 8.2.2 避免保存冗余数据 8.2.3 使用原子列值 8.2.4 选择有意义的键 8.2.5 考虑需要询问数据库的问题 8.2.6 避免多个空属性的设计 8.2.7 表格类型的总结 8.3 Web数据库架构 8.4 进一步学习 8.5 下一章 第9章 创建Web数据库 9.1 使用MySQL监视程序 9.2 登录到MySQL 9.3 创建数据库和用户 9.4 设置用户与权限 9.5 MySQL权限系统的介绍 9.5.1 最少权限原则 9.5.2 创建用户:GRANT命令 9.5.3 权限的类型和级别 9.5.4 REVOKE命令 9.5.5 使用GRANT和REVOKE的例子 9.6 创建一个Web用户 9.7 使用正确的数据库 9.8 创建数据库表 9.8.1 理解其他关键字的意思 9.8.2 理解列的类型 9.8.3 用SHOW和DESCRIBE来查看数据库 9.8.4 创建索引 9.9 理解MySQL的标识符 9.10 选择列数据类型 9.10.1 数字类型 9.10.2 日期和时间类型 9.10.3 字符串类型 9.11 进一步学习 9.12 下一章 第10章 使用MySQL数据库 10.1 SQL是什么 10.2 在数据库中插入数据 10.3 从数据库中获取数据 10.3.1 获取满足特定条件的数据 10.3.2 从多个表中获取数据 10.3.3 以特定的顺序获取数据 10.3.4 分组与合计数据 10.3.5 选择要返回的行 10.3.6 使用子查询 10.4 更新数据库记录 10.5 创建后修改表 10.6 删除数据库中的记录 10.7 表的删除 10.8 删除整个数据库 10.9 进一步学习 10.10 下一章 第11章 使用PHP从Web访问MySQL数据库 11.1 Web数据库架构的工作原理 11.2 从Web查询数据库的基本步骤 11.2.1 检查与过滤用户输入数据 11.2.2 建立一个连接 11.2.3 选择使用的数据库 11.2.4 查询数据库 11.2.5 检索查询结果 11.2.6 从数据库断开连接 11.3 将新信息放入数据库 11.4 使用Prepared语句 11.5 使用PHP与数据库交互的其他接口 11.5.1 使用常规的数据库接口:PEAR MDB2 11.6 进一步学习 11.7 下一章 第12章 MySQL高级管理 12.1 深入理解权限系统 12.1.1 user表 12.1.2 db表和host表 12.1.3 tables_priv表,columns_priv表和procs_priv表 12.1.4 访问控制:MySQL如何使用Grant表 12.1.5 更新权限:修改什么时候生效 12.2 提高MySQL数据库的安全性 12.2.1 从操作系统角度来保护MySQL 12.2.2 密码 12.2.3 用户权限 12.2.4 Web问题 12.3 获取更多关于数据库的信息 12.3.1 使用SHOW获取信息 12.3.2 使用DESCRIBE获取关于列的信息 12.3.3 用EXPLAIN理解查询操作的工作过程 12.4 数据库的优化 12.4.1 设计优化 12.4.2 权限 12.4.3 表的优化 12.4.4 使用索引 12.4.5 使用默认值 12.4.6 其他技巧 12.5 备份MySQL数据库 12.6 恢复MySQL数据库 12.7 实现复制 12.7.1 设置主服务器 12.7.2 执行初始的数据传输 12.7.3 设置一个/多个从服务器 12.8 进一步学习 12.9 下一章 第13章 MySQL高级编程 13.1 LOAD DATA INFILE语句 13.2 存储引擎 13.3 事务 13.3.1 理解事务的定义 13.3.2 通过InnoDB使用事务 13.4 外键 13.5 存储过程 13.5.1 基本示例 13.5.2 局部变量 13.5.3 游标和控制结构 13.6 进一步学习 13.7 下一章 第三篇 电子商务与安全性 第14章 运营一个电子商务网站 14.1 我们要实现什么目标 14.2 考虑电子商务网站的类型 14.2.1 使用在线说明书公布信息 14.2.2 接收产品或服务的订单 14.2.3 提供服务和数字产品 14.2.4 为产品或服务增值 14.2.5 减少成本 14.3 理解风险和威胁 14.3.1 网络黑客 14.3.2 不能招揽足够的生意 14.3.3 计算机硬件故障 14.3.4 电力、通信、网络或运输故障 14.3.5 广泛的竞争 14.3.6 软件错误 14.3.7 不断变化的政府政策和税收 14.3.8 系统容量限制 14.4 选择一个策略 14.5 下一章 第15章 电子商务的安全问题 15.1 信息的重要程度 15.2 安全威胁 15.2.1 机密数据的泄露 15.2.2 数据丢失和数据破坏 15.2.3 数据修改 15.2.4 拒绝服务 15.2.5 软件错误 15.2.6 否认 15.3 易用性,性能、成本和安全性 15.4 建立一个安全政策 15.5 身份验证原则 15.6 加密技术基础 15.6.1 私有密钥加密 15.6.2 公有密钥加密 15.6.3 数字签名 15.7 数字证书 15.8 安全的Web服务器 15.9 审计与日志记录 15.10 防火墙 15.11 备份数据 15.11.1 备份常规文件 15.11.2 备份与恢复MySQL数据库 15.12 自然环境安全 15.13 下一章 第16章 Web应用的安全 16.1处理安全性问题的策略 16.1.1 以正确心态为开始 16.1.2 安全性和可用性之间的平衡 16.1.3 安全监视 16.1.4 基本方法 16.2 识别所面临的威胁 16.2.1 访问或修改敏感数据 16.2.2 数据丢失或破坏 16.2.3 拒绝服务 16.2.4 恶意代码注入 16.2.5 服务器被攻破 16.3了解与我们“打交道”的用户 16.3.1 破解人员 16.3.2 受影响机器的未知情用户 16.3.3 对公司不满的员工 16.3.4 硬件被盗 16.3.5 我们自身 16.4 代码的安全性 16.4.1 过滤用户输入 16.4.2 转义输出 16.4.3 代码组织 16.4.4 代码自身的问题 16.4.5 文件系统因素 16.4.6 代码稳定性和缺陷 16.4.7 执行引号和exec 16.5 Web服务器和PHP的安全性 16.5.1 保持软件的更新 16.5.2 查看php.ini文件 16.5.3 Web服务器配置 16.5.4 Web应用的商业主机服务 16.6 数据库服务器的安全性 16.6.1 用户和权限系统 16.6.2发送数据至服务器 16.6.3 连接服务器 16.6.4 运行服务器 16.7 保护网络 16.7.1 安装防火墙 16.7.2使用隔离区域(DMZ) 16.7.3应对DoS和DDoS攻击 16.8 计算机和操作系统的安全性 16.8.1 保持操作系统的更新 16.8.2只运行必须的软件 16.8.3 服务器的物理安全性 16.9 灾难计划 16.10 下一章 第17章 使用PHP和MySQL实现身份验证 17.1 识别访问者 17.2 实现访问控制 17.2.1 保存密码 17.2.2 密码的加密 17.2.3 保护多个网页 17.3 使用基本身份验证 17.4 在PHP中使用基本身份验证 17.5 在Apache的.htaccess文件中使用基本身份验证 17.6 使用mod_auth_mysql身份验证 17.6.1 安装mod_auth_mysql 17.6.2 使用mod_auth_mysql 17.7 创建自定义身份验证 17.8 进一步学习 17.9 下一章 第18章 使用PHP和MySQL实现安全事务 18.1 提供安全的事务处理 18.1.1 用户机器 18.1.2 Internet 18.1.3 我们的系统 18.2 使用加密套接字层(SSL) 18.3 屏蔽用户的输入 18.4 提供安全存储 18.5 存储信用卡号码 18.6 在PHP中使用加密技术 18.6.1 安装GPG 18.6.2 测试GPG 18.7 进一步学习 18.8 下一章 第四篇 PHP的高级技术 第19章 与文件系统和服务器的交互 19.1 文件上载 19.1.1 文件上载的HTML代码 19.1.2 编写处理文件的PHP 19.1.3 避免常见上载问题 19.2 使用目录函数 19.2.1 从目录读取 19.2.2 获得当前目录的信息 19.2.3 创建和删除目录 19.3 与文件系统的交互 19.3.1 获取文件信息 19.3.2 更改文件属性 19.3.3 创建、删除和移动文件 19.4 使用程序执行函数 19.5 与环境变量交互:getenv()和putenv() 19.6 进一步学习 19.7 下一章 第20章 使用网络函数和协议函数 20.1 了解可供使用的协议 20.2 发送和读取电子邮件 20.3 使用其他Web站点的数据 20.4 使用网络查找函数 20.5 备份或镜像一个文件 20.5.1 使用FTP备份或镜像一个文件 20.5.2 上传文件 20.5.3 避免超时 20.5.4 使用其他的FTP函数 20.6 进一步学习 20.7 下一章 第21章 日期和时间的管理 21.1 在PHP中获取日期和时间 21.1.1 使用date()函数 21.1.2 使用UNIX时间戳 21.1.3 使用getdate()函数 21.1.4 使用checkdate()函数检验日期有效性 21.1.5 格式化时间戳 21.2 在PHP日期格式和MySQL日期格式之间进行转换 21.3 在PHP中计算日期 21.4 在MySQL中计算日期 21.5 使用微秒 21.6 使用日历函数 21.7 进一步学习 21.8 下一章 第22章 创建图像 22.1 在PHP中设置图像支持 22.2 理解图像格式 22.2.1 JPEG 22.2.2 PNG 22.2.3 WBMP 22.2.4 GIF 22.3 创建图像 22.3.1 创建一个背景图像 22.3.2 在图像上绘图或打印文本 22.3.3 输出最终图形 22.3.4 清理 22.4 在其他页面中使用自动生成的图像 22.5 使用文本和字体创建图像 22.5.1 创建基本画布 22.5.2 将文本调整到适合按钮 22.5.3 放置文本 22.5.4 将文本写到按钮上 22.5.5 完成 22.6 绘制图像与用图表描绘数据 22.7 使用其他的图像函数 22.8 进一步学习 22.9 下一章 第23章 在PHP中使用会话控制 23.1 什么是会话控制 23.2 理解基本的会话功能 23.2.1 什么是cookie 23.2.2 通过PHP设置cookie 23.2.3 在会话中使用cookie 23.2.4 存储会话 ID 23.3 实现简单的会话 23.3.1 开始一个会话 23.3.2 注册一个会话变量 23.3.3 使用会话变量 23.3.4 注销变量与销毁会话 23.4 创建一个简单的会话例子 23.5 配置会话控制 23.6 通过会话控制实现身份验证 23.7 进一步学习 23.8 下一章 第24章 其他有用的特性 24.1 使用eval()函数对字符串求值 24.2 终止执行:die和exit 24.3 序列化变量和对象 24.4 获取PHP环境信息 24.4.1 找到所加载的PHP扩展部件 24.4.2 识别脚本所有者 24.4.3 确定脚本最近修改时间 24.5 暂时改变运行时环境 24.6 源代码加亮 24.7 在命令行中使用PHP 24.8 下一章 第五篇 创建实用的PHP和MySQL项目 第25章 在大型项目中使用PHP和MySQL 25.1 在Web开发中应用软件工程 25.2 规划和运行Web应用程序项目 25.3 重用代码 25.4 编写可维护代码 25.4.1 编码标准 25.4.2 分解代码 25.4.3 使用标准的目录结构 25.4.4 文档化和共享内部函数 25.5 实现版本控制 25.6 选择一个开发环境 25.7 项目的文档化 25.8 建立原型 25.9 将逻辑和内容分离 25.10 优化代码 25.10.1 使用简单优化 25.10.2 使用Zend产品 25.11 测试 25.12 进一步学习 25.13 下一章 第26章 调试 26.1 编程错误 26.1.1 语法错误 26.1.2 运行时错误 26.1.3 逻辑错误 26.2 使用变量帮助调试 26.3 错误报告级别 26.4 改变错误报告设置 26.5 触发自定义错误 26.6 巧妙地处理错误 26.7 下一章 第27章 建立用户身份验证机制和个性化设置 27.1 解决方案的组成 27.1.1 用户识别和个性化设置 27.1.2 保存书签 27.1.3 推荐书签 27.2 解决方案概述 27.3 实现数据库 27.4 实现基本的网站 27.5 实现用户身份验证 27.5.1 注册 27.5.2 登录 27.5.3 登出 27.5.4 修改密码 27.5.5 重设遗忘的密码 27.6 实现书签的存储和检索 27.6.1 添加书签 27.6.2 显示书签 27.6.3 删除书签 27.7 实现书签推荐 27.8 考虑可能的扩展 27.9 下一章 第28章 创建一个购物车 28.1 解决方案的组成 28.1.1 创建一个在线目录 28.1.2 在用户购买商品的时候记录购买行为 28.1.3 实现一个付款系统 28.1.4 创建一个管理界面 28.2 解决方案概述 28.3 实现数据库 28.4 实现在线目录 28.4.1 列出目录 28.4.2 列出一个目录中的所有图书 28.4.3 显示图书详细信息 28.5 实现购物车 28.5.1 使用show_cart.php脚本 28.5.2 浏览购物车 28.5.3 将物品添加到购物库 28.5.4 保存更新后的购物车 28.5.5 打印标题栏摘要 28.5.6 结账 28.6 实现付款 28.7 实现一个管理界面 28.8 扩展该项目 28.9 使用一个已有系统 28.10 下一章 第29章 创建一个基于Web的电子邮件服务系统 29.1 解决方案的组成 29.1.1 电子邮件协议:POP3和IMAP 29.1.2 PHP对POP3和IMAP的支持 29.2 解决方案概述 29.3 建立数据库 29.4 了解脚本架构 29.5 登录与登出 29.6 建立账户 29.6.1 创建一个新账户 29.6.2 修改已有账户 29.6.3 删除账户 29.7 阅读邮件 29.7.1 选择账户 29.7.2 查看邮箱内容 29.7.3 阅读邮件消息 29.7.4 查看消息标题 29.7.5 删除邮件 29.8 发送邮件 29.8.1 发送一则新消息 29.8.2 回复或转发邮件 29.9 扩展这个项目 29.10 下一章 第30章 创建一个邮件列表管理器 30.1 解决方案的组成 30.1.1 建立列表和订阅者数据库 30.1.2 上载新闻信件 30.1.3 发送带附件的邮件 30.2 解决方案概述 30.3 建立数据库 30.4 定义脚本架构 30.5 实现登录 30.5.1 新账户的创建 30.5.2 登录 30.6 用户函数的实现 30.6.1 查看列表 30.6.2 查看邮件列表信息 30.6.3 查看邮件列表存档 30.6.4 订阅与取消订阅 30.6.5 更改账户设置 30.6.6 更改密码 30.6.7 登出 30.7 管理功能的实现 30.7.1 创建新的邮件列表 30.7.2 上载新的新闻信件 30.7.3 多文件上载的处理 30.7.4 预览新闻信件 30.7.5 发送邮件 30.8 扩展这个项目 30.9 下一章 第31章 创建一个Web论坛 31.1 理解流程 31.2 解决方案的组成 31.3 解决方案概述 31.4 数据库的设计 31.5 查看文章的树型结构 31.5.1 展开和折迭 31.5.2 显示文章 31.5.3 使用treenode类 31.6 查看单个的文章 31.7 添加新文章 31.8 添加扩充 31.9 使用一个已有的系统 31.10 下一章 第32章 生成PDF格式的个性化文档 32.1 项目概述 32.1.1 评估文档格式 32.2 解决方案的组成 32.2.1 问题与回答系统 32.2.2 文档生成软件 32.3 解决方案概述 32.3.1 提问 32.3.2 给答题评分 32.3.3 生成RTF证书 32.3.4 从模板生成PDF证书 32.3.5 使用PDFlib生成PDF文档 32.3.6 使用PDFlib的一个“Hello World”程序 32.3.7 用PDFlib生成证书 32.4 处理标题的问题 32.5 扩展该项目 32.6 下一章 第33章 使用XML和SOAP来连接Web服务 33.1 项目概述:使用XML和Web服务 33.1.1 理解XML 33.1.2 理解Web服务 33.2 解决方案的组成 33.2.1 使用Amazon的Web服务接口 33.2.2 XML的解析:REST响应 33.2.3 在PHP中使用SOAP 33.2.4 缓存 33.3 解决方案概述 33.3.1 核心应用程序 33.3.2 显示特定种类的图书 33.3.3 获得一个AmazonResultSet类 33.3.4 使用REST发送和接收请求 33.3.5 使用SOAP发送和接收请求 33.3.6 缓存请求返回的数据 33.3.7 创建购物车 33.3.8 到Amazon付账 33.4 安装项目代码 33.5 扩展这个项目 33.6 进一步学习 第34 章使用Ajax构建Web 2.0应用 34.1 Ajax 是什么? 34.1.1 HTTP请求和响应 34.1. 2 DHTML和XHTML 34.1.3 级联样式单(CSS) 34.1.4 客户端编程 34.1.5 服务器端编程 34.1.6 XML和XSLT 34.2 Ajax基础 34.2.1 XMLHTTPRequest对象 34.2.2 与服务器通信 34.2.3 处理服务器响应 34.2.4 整合应用 34.3 在以前的项目添加Ajax元素 34.3.1在PHPBookmark应用中添加Ajax元素 34.4 进一步学习 34.4.1 进一步了解文档对象模型(DOM) 34.4.2 Ajax应用可用的JavaScript函数库 34.4.3 Ajax开发人员网站 第六篇 附录 附录A 安装PHP及MySQL 附录B Web资源 第1章 PHP快速入门教程 第2章 数据的存储与检索 第3章 使用数组 第4章 字符串操作与正则表达式 第5章 代码重用与函数编写 第6章 面向对象PHP 第7章 错误和异常处理 ……
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值