深入php(第三版) 读书笔记一

最近在看《深入php:面向对象、模式与实践》这本书,php里专门讲解面向对象的书籍不多,讲解设计模式和实际代码实践的书籍就更少了,但是少不代表质量不好,本书就是值得阅读的一本。这里借用thinkphp 麦苗当儿的座右铭:每多学一点知识,就少写一行代码。希望大家都能多抽些时间来看书,然后工作的更加轻松也更快乐~~~


下面进入正题,先来看一个问题,我们在项目里经常封装类来实现指定的业务逻辑,比如下面的Memebr类:

 class Member {

 protected $name;
 protected $age;

function __construct($name,$age){
     $this->name=$name;
     $this->age=$age;
 }

//登陆
 public function login($name,$pwd){
 if(!$info=M('Member')->where(array('name'=>$name,'pwd'=>$pwd))->find()){
     return false;
 }elseif($info['status']==0){
     return false;
 }
 //具体登陆操作...
 return true;
 }
 }
 

Member类很简单,每个会员有姓名和年龄属性,然后还有一个登陆的方法,那么现在重点在登陆方法,我们在控制器里调用会员的login方法可以实现登陆与否的检测,但是问题在于当登陆失败后我们不知道具体的失败原因,因为程序只返回布尔类型的判断,于是聪明的程序员可以这样更改login:

 //登陆
 public function login($name,$pwd){
 if(!$info=M('Member')->where(array('name'=>$name,'pwd'=>$pwd))->find()){
     return array('status'=>0,'info'=>'用户不存在');
 }
 elseif($info['status']==0){
     return array('status'=>0,'info'=>'用户被禁用');
 }
 //具体登陆操作...
 return true;
 }

这样传递数组就可以解决问题了,控制器里可以获取错误信息了,不过你可能就会说这样太繁琐了,返回数组写好多代码,且最大问题是每个人可能返回各自数组命名,这样就不能统一而导致代码混乱了,混乱是不可取的。于是聪明的程序员就想到了我们现在使用面向对象,那就要用对象的思想来解决,于是我们这样来写:

 class Member {

 protected $name;
 protected $age;
 public $error;//错误信息

function __construct($name,$age){
     $this->name=$name;
     $this->age=$age;
 }

//登陆
 public function login($name,$pwd){
 if(!$info=M('Member')->where(array('name'=>$name,'pwd'=>$pwd))->find()){
     $this->error='用户不存在';
     return false;
 }elseif($info['status']==0){
     $this->error='用户已被禁用';
     return false;
 }
 //具体登陆操作...
 return true;
 }
 }
 

我们给Member类添加一个错误的属性,来存放错误信息,这样控制器里就可以直接实例化获取error错误信息,但是呢,就像人一样,我们每个人都有属于自己的属性,比如姓名、年龄、存款等等,我们不会轻易随便就透露这些信息,只有当别人问起的时候我们才考虑要不要告诉他们,类里的属性也是一样的,我们会把属性尽可能的保护起来,这里我们就需要把Member类型的属性error改成protected类型的,方便子类和自己使用,那你要问了,那调用者怎么调用呢,这样我们就会约定好属性固定的getter和setter方法,如下面代码

 class Member {

 protected $name;
 protected $age;
 protected $error;//错误信息

function __construct($name,$age){
     $this->name=$name;
     $this->age=$age;
 }

//获取名字的getter
 public function getName(){
     return $this->name;
 }

//获取错误信息的getter
 public function getError(){
     return $this->error;
 }

//登陆
 public function login($name,$pwd){
 if(!$info=M('Member')->where(array('name'=>$name,'pwd'=>$pwd))->find()){
     $this->error='用户不存在';
     return false;
 } elseif($info['status']==0){
     $this->error='用户已被禁用';
     return false;
 }
 //具体登陆操作...
 return true;
 }
 }
 

这样我们就可以解决了,如果想要告诉别人某个属性那么我们就给它添加它的getter方法,不过挑剔的程序员肯定又会说了,我只是想要调取一个属性却要调取它的getter方法好烦呢,而且如果有一天你换了一种风格的getter方法是不是就需要修改控制器里的调取方法了。那怎么办呢?聪明的程序员发现了php中存在神奇的魔术方法,还不了解的童鞋可以去手册里看看,于是就有了下面的版本:

 class Member {

 protected $name;
 protected $age;
 protected $error;//错误信息

function __construct($name,$age){
     $this->name=$name;
     $this->age=$age;
 }

//获取名字的getter
 public function getName(){
     return $this->name;
 }

//获取错误信息的getter
 public function getError(){
     return $this->error;
 }

//__get魔术方法,访问未定义属性是调用
 public function __get($property){
     $method = 'get'.ucfirst($property);
     if(method_exists($this,$method))
         return $this->$method();
     }

}
 

我们添加类的一个__get魔术方法来拦截用户调用未定义或者受保护的属性,然后由这个魔术方法来调用我们的getter方法,这样前面控制器里就能直接调用受保护的属性了。当然,对于检测错误最好的方式还是使用php的异常功能即抛出一个特定的异常,这个我们到后面再来补充说明吧。

深入php(第三版) 读书笔记一》有1个想法

发表评论

邮箱地址不会被公开。