数据持久化、单例、重载【添加对不可访问的成员的操作】、魔术方法、类常量、static关键字对self的补充【静态延迟绑定实现$this的效果】、参数类型约束【参数前加类名】、遍历【iterator接口】、快速排序

1.数据持久化过程【传输(例如表单提交或php交互mysql)和保存过程】 使用的是字符串形式的流数据。 数据流就是为了传输【按照序列的形式进行传输】 【http://baike.baidu.com/link?url=0MtUQMhFzc_EwJc09rXZV8KlfOL4jis6XNbRfmGA3rQhDcGwOp8togLVQjXBV34M

所以将其他类型数据转化为字符串的过程也是序列化的过程 【这个概念和图片、视频的流媒体的区别?】

【注意点】 另外mysql中sql语句中的某些关键词为了防止冲突的反引号的使用【养成习惯,因为在做项目中操作数据库确实有这种情况的bug出现】 另外自己对某些项目的模块进行拓展【添加新的方法,例如mysql的操作类,可以综合多种情况来实现】

【重点】 2.单例【场景主要就是针对数据库连接对象的单例实现】

单例的好处【节约资源空间】 【优缺点:http://blog.csdn.net/tayanxunhua/article/details/8250329】 但是mysql本身的连接函数如果同样的参数进行连接,并不会重新创建连接【php与mysql之间的连接其实单例并没有太多作用,只是操作的对象比较全局,oop本身对全局的使用是废止的】

单例实现的机制 (1)限制用户无限制执行实例化对象【构造函数本身都是public,保证了在类外进行实例化的操作(能够调用构造函数),单例中更改为更低的权限,保证构造函数不会在类外实例化时被调用】

【PHP单例模式的创建方法:  【1】、创建一个保存实例的静态化static私有对象【使用静态来实现类名调用,在类外不能使用new进行实例化对象,改为在类外进行类名调用静态方法(在静态方法中实现new实例化对象)创建】  【2】、私有化构造函数__construct();【重点,保证类外不能实例化】  【3】、防止被克隆 将__clone()私有化;  【4】、创建一个能够访问实例公共静态方法(方法内部需要实例化本类,并返回该实例)】

http://blog.csdn.net/shaobaojie/article/details/36475623

【单例的代码】 <?php class MySQLDB {

 private static $instance;

 private function __construct($p1) {//防止被直接实例化对象  }

 public static function getInstance($p1) {   if(  ! (self::$instance instanceof self) ) {//注意这里的instanceof关键字判断是否是类的实例对象    //没实例化过    self::$instance = new self($p1);//将实例化后的对象存入静态属性中,用来判断是否被实例化过。这里的new self【self表示的就是自身的类,在实例化自身调用自己的构造函数】   }

  return self::$instance;  }

 private function __clone() {//防止被克隆对象【php获取对象只有两个途径:实例化和克隆】  } }

$db1 = MySQLDB::getInstance($a);//通过类名调用静态方法,在静态方法中对是否实例化进行判断 $db2 = MySQLDB::getInstance($a); var_dump($db1, $db2);

?>

【注意】 单例模式【保证一个类有且只有一个对象,这种设计模式就是单例模式】 【作用:保证一个类只有一个对象,从而保证节约空间】 【但是要适合的场景就是使用一个对象能够完成所有的业务逻辑类:一个用户启用一个脚本用来连接数据库时,因为数据库的连接只需要一次,就可以使用该数据库连接进行数据库操作】 【这里理解应该是说,一个请求的处理过程是一个线程处理,在该线程上,脚本实现数据库操作只需要一次连接的对象,然后使用该对象进行数据库操作即可。这才是数据库操作类要设计成单例的原因】 【在php脚本中创建的连接都保存在变量里,这个变量本身就是临时的,但是其对象占用的引用却是现实存在的,其实单例就相当于将创建出的对象持续的保存在内存中,直到所有引用它的变量全部销毁之后,才会被销毁】

【单例的总结】【需要结合对象的生命周期进行讨论:就是对象究竟在哪个层面上,线程上还是整体空间内?(实例化后的对象,什么时候被销毁。这是单例中对象重用的关键)】 【http://www.cnblogs.com/yangjinjin/archive/2013/01/31/2887492.html】 【http://www.cnblogs.com/wangtao_20/p/3593076.html】 【对单例进行测试,实现数据库的连接类之后,在两个脚本中分别进行实例化,查看该对象即可】 【经过查看,两个脚本同样实例化该单例类,获得的对象是同一个,但是存在一个问题就是可能因为脚本执行结束,该对象被销毁并且再创建(原理就是因为销毁了对象)】 【对象以及对象变量之间的差别】 【现在就剩下一个问题就是不同脚本之间的单例对象是否能够实现共享?】

【单例类不使用继承(并不是语法上不能实现继承),因为一旦继承,子类中的对象也是父类的对象和单例的业务逻辑要求冲突】

【将mysqldb数据库操作类改造为单例的类:找一个完整的数据库操作类】

3.重载【overload】 【都是针对不可访问的成员进行的操作(在类中使用魔术方法进行设置),从而能够实现对属性不可访问的更好控制】 php的重载直接在对象,通过调用(魔术)方法来增加属性【这就叫做重载】 php对当前不可以访问成员的处理方式【这里的不可访问指的是不存在或者受到访问修饰限定符限制的属性】 (1)【针对不存在的成员,自动增加为公共的成员】 (2)【针对访问修饰限定符限制的成员,提示错误】【这是默认的,但是使用重载的方法之后就能进行访问修饰限定符受限的成员】 <?php class test{ private $school; } $school = new test; $school->class = '重载';//此时$school对象的属性添加一个public成员 var_dump($school); ?>

有四个魔术方法,用于处理: __set:当给不可访问属性(不存在或成员不可访问)赋值时,被自动调用 __get:访问不可访问属性时,被自动调用 __unset:在删除一个不可访问的属性时,被自动调用【用的不多】 __isset:对某个不可访问的属性进行判断是否存在时,被自动调用

方法重载:【只要方法不可访问,那么就回调__call这样的魔术方法】 利用魔术方法进行方法重载: __call __callstatic【暂时没有对静态属性的处理方法】 区别在于静态方法的调用【传入参数:方法名,参数】

以上是php的重载【六个魔术方法保证了不可访问的成员进行类内的操作:php机制实现判断是否不可访问,并且调用该魔术方法】

这里的魔术方法就是为了简化外部修改内部的更窄的权限的属性的更改【这是我们为了封装属性但开set接口进行类内更改属性的方法的最统一的方法】 【为了加强我们设置系统的封装性,但也不影响灵活性】

现在对魔术方法有一个更好的理解:在对象中出现用于php的机制来调用的改方法 自动加载不是魔术方法【唯一例外】

4.魔术方法总结 已经学习的魔术方法有: __construct __destruct __sleep:对象序列化时使用 __wakeup 针对不可访问成员的魔术方法 __set __get __isset __unset __call __callStatic 另外还有 __clone【克隆时进行调用】

此外 __autoload是一个魔术函数【不在对象中进行调用】

需要补充的魔术方法 __incoke():将一个对象当做一个函数进行调用时会触发 class school{

} $s = new school; $s();//将对象当做函数进行调用【这样就实现了一个匿名函数的效果】

__toString():将对象当做字符串使用时,就会自动调用该魔术方法 class school{

} $s = new school; echo $s;//此时就会触发该魔术方法【因为echo需要输出的是字符串】

【魔术方法只是针对特定情况进行遇到该情景下php自动进行调用的机制,具体调用的函数的执行过程需要自己进行定义】

5.关于关键字的总结: (1)$this永远代表所在类的对象?【不是,php也有所在环境延生的问题(继承中会出现)】 (2)self用于代表所在类的对象?【是,永远代表】 【self是编译时就已经确定当前类,使用static关键字用来调用时进行确定】【这种情况就叫做静态延迟绑定】

<?php class P { public static $where = "p"; public static function sayWhere(){ echo self::$where; } }

class C extends P { public static $where = "c"; }

echo P::sayWhere();//p echo C::sayWhere();//p【这个是关键,self只能显示P类的对象】

因为这样的问题,决定了我们需要将self能够在调用中指定对象【$this的效果,但是$this只能针对对象访问,self针对的是类访问,但是有一定缺陷】

6.静态延迟绑定【php>=5.3】 【也就是类调用中动态确定】 static关键字【与self进行区别】

例子: <?php class P { public static $where = "p"; public static function sayWhere(){ echo self::$where; } public static function sayW(){ //这里实现静态延迟绑定 echo static::$where; }

}

class C extends P { public static $where = "c"; }

echo P::sayWhere();//p echo C::sayWhere();//p

//实现静态延迟绑定 echo P::sayW(); echo C::sayW();//c。实现在调用时确定方法中的对象【实现延迟绑定调用】

总结: static关键字: (1)声明静态局部变量【function中使用】 (2)声明静态成员【面向对象中用于使用类调用】 (3)当前类,运行时的当前类【静态延时绑定】

在类中表示类的关键字: self:所在类【在编译之处便确定】 static:调用时的当前类 parent:父类

以上就是关键字

7.参数类型约束 【因为php是弱类型,所以希望构建健壮系统需要使用参数类型约束】

在参数前进行一个类【这个类通过定义,实现对类型的限制】

【这是自己进行数据参数控制的方法,但是需要自己写类来限制数据传入的类型】 【另外可以直接使用Array关键字做类型约束】【只有这种能够直接用来限制,不需要自己自定义类】

8.对象的遍历 使用foreach实现对复合型数据的遍历【对象和数组】 使用foreach只能遍历属性

也可以自定义遍历对象的方式 【通过类实现iterator接口的判断来对遍历过程加一些自定义的方法:实现对对象中的属性的针对性访问。而不是全部属性进行访问】 【自定义遍历】 需要使用接口interface编程 【iterator接口:迭代器接口】

foreach实现遍历是: 首先判断遍历的对象是否是实现过iterator接口,如果没有,直接遍历对象的属性【默认】 如果是实现iterator接口,则按照该接口内声明的那些方法进行遍历

iterator接口中五个方法是实现自定义遍历过程的关键【需要对这个接口进行学习】 这就是iterator接口的五个关键的方法【需要在类中将这五个方法进行实现】 remind:初始化 valid:判断是否合法 current:给值变量赋值 key:给键变量赋值 next:移动

例子: <?php

class Student {  public $stu_name;  public $stu_age;  private $stu_gender='secret'; }

$o = new Student; $o->stu_name = '李世民'; $o->stu_age = 50; //$o->stu_gender = 'male';

foreach($o as $p_name => $p_value) {

 var_dump($p_name, $p_value);  echo '<br>'; }

echo '<hr>';

/**  * 班级类  */ class Team implements Iterator {  public $name;  public $stu_count;  public $stu_infos;

 //1  public function rewind() {   reset($this->stu_infos);  }  //N+1  public function valid() {   return key($this->stu_infos) !== null;  }  //N  public function current() { //  return 'itcast';   return current($this->stu_infos);  }  //N  public function key() { //  return mt_rand(10, 20);   return key($this->stu_infos);  }  //N  public function next() { //  next($this->stu_infos);   next($this->stu_infos);  } } $t = new Team; $t->name = 'PHP1016'; $t->stu_count = 3; $t->stu_infos = array(  array('id'=>'10', 'name'=>'司马懿'),  array('id'=>'15', 'name'=>'司马昭'),  array('id'=>'34', 'name'=>'司马炎') );

//遍历班级! foreach($t as $p_name=>$p_value) {  var_dump($p_name, $p_value);  echo '<br>';

}

9.常见的类对象函数和魔术常量【了解这些内容的使用】 is_object() class_exists() interface_exists() get_class() get_parent_class()

get_class_vars():得到类的属性 get_class_method():得到类的方法

需要结合手册进行这些函数和魔术常量的学习 魔术常量: __CLASS__:当前类名 __METHOD__:当前方法名 __FILE__:当前文件名 __DIR__:当前文件夹 __LINE__:当前行【用来做error系统】 __FUNCTION__:当前函数【在全局效果上,与方法对应的对象进行区别】

另外一些php本身的预定义的类也需要深入学习【xml处理类等】

10.面向对象的特征: 用对象来映射现实的实体,实现业务逻辑

特征: 封装【使用很好的类模块将复杂的业务进行分离】【实现模块化】 继承【类之间处理关系,实现代码的重用】 多态【类继承之后也能表现各自的特性。抽象类中的各自继承的子类实现的内容可以是多种的】

11.快速排序【实际使用中比较多】【也叫分治算法】 【冒泡排序的效率并不高,复杂度非常大】

【排序问题上】解决一个难度为n的问题,比解决两个n/2的问题难度要大。

快速排序: 挑出一个参考元【寻找参考元本身也比较难找。取中间】,将比它大(或相等)的放在右侧,将比它小的放左侧【实现一次分开】 然后再实现剩余两部分的递归 知道分割的元素的行为停止【这个是关键:迭代的关键就是停止递归的条件(待排序的序列中,元素个数为0,便停止递归)】 从而实现排序

编程实现: (1)首先判断是否需要递归【递归出口】 (2)进行递归【选择参考元,进行分割。将分割的两部分数据,进行递归,传值分割后的数据即可.】

function quicksort($array){ $count = count($array); if($count<=1){ return $array;//递归的出口 } $cankao = $array[0];//写死的第一个 $small = $big = array(); for($k=1;$k<$count;$k++){ if($array[$k]>$cankao){ $big[] = $array[$k]; }else{ $small[] = $array[$k]; } //这样实现了对参考元左右的元素的判断

} //接着实现递归调用 $sort_small = quicksort($small);//这里的$sort_small变量本身就是里层的merge之后的结果 $sort_big = quicksort($big); //重点理解递归的原理就在这里【因为只有递归的里层结束才会执行外层的代码,因为合并的代码本身就在函数内,肯定会被执行】 //【这里的合并每一次递归的时候都被执行】 //接着实现对结果的合并 return array_merge($sort_small, array($cankao), $sort_big); }

$list = array(24, 11, 67, 10, 9, 23, 45); $sort_list = quickSort($list); var_dump($sort_list);

【重点】 递归调用的执行流程是关键: 里层的函数一层层完成才会执行外层的代码 【这一点是关键,将一个个函数嵌入到内部(因为是内部调用,所以相当于实现一层层的函数代码的嵌套。这样理解递归会对代码执行的顺序有一个深刻理解)】

【问题】 【对php内核进行研究:例如进程这块】 【一个请求的开始到结束时的php模块的作用:http://www.nowamagic.net/librarys/veda/detail/1286】 【php中对象的生命周期:http://www.nowamagic.net/librarys/veda/detail/1521