PHP:oop->重载之set/get/call/callStatic,oop事件委托,数据库查询构造器
魔术方法 | 含义 |
---|---|
__set() | __set(name,value) ,第一个值是成员属性名称,第二个值是成员属性值 |
__get() | __get(name) ,第一个值是成员名称或者成员属性值 |
php重载 PHP所提供的重载(overloading)是指动态地创建类属性和方法。我们是通过魔术方法(magic methods)来实现的。
当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。
①重载之__set()
在类中,如果实列未创建的成员属性会自动访问
__set方法
,__set(name,value)
,第一个值是成员属性名称,第二个值是成员属性值
②重载之__get()
在类中,如果输出未创建的成员属性会自动访问
__get()方法
,__get(name)
,第一个值是成员名称或者成员属性值
③属性拦截
以上我们得知,如果我们随意创建一个类中没有的成员属性,会自动调用set/get方法,这样的话就无法保护到私有成员或者受保护的成员,因此一般我们会在set/get里面建立一个中转站把获取到的数据传入到一个私有的方法中,来进行内容过滤,以下我们来过滤身份证信息。
判断身份证信息超过18位输出不合法
身份证信息判断未18位后,输出前5位,后4位
代码块
<?php//php重载 之 属性重载 属性拦截器use Credit as GlobalCredit;class Credit { //私有成员属性 private $idNum; private $age; //构造器 public function __construct($idNum,$age) { $this->idNum = $idNum; $this->age = $age; } //建立 set / get 中转站 把获取到的数据转入一个私有的方法中过滤 public function __set($name, $value) { //根据属性名称$name 生成对应的属性访问私有接口的名称 // ucfirst — 将字符串的首字母转换为大写 $method = "set" . ucfirst($name) ; //method_exists — 检查类的方法是否存在 第一个值传递对象 第二个值传递对象中的方法 return method_exists($this,$method) ? $this->$method($name,$value) : null; } //设置set 私立方法进行内容过滤 private function setIdNum($name,$value) { //property_exists — 检查对象或类是否具有该属性 第一个值是类,第二个值是属性名称 if (property_exists($this,$name)) { //判断属性值是否等于18位,不等于的话返回null return $this->$name = strlen($value) == 18 ? $value : null; } } public function __get($name) { $method = "get" . ucfirst($name); return method_exists($this,$method) ? $this->$method($name) : null; } private function getIdNum($name) { //empty — 检查一个变量是否为空 if (property_exists($this,$name) && !empty($this->$name)) { //返回前面5位数字 和 后4位数字 return mb_substr($this->$name,0,5) . "......" . mb_substr($this->$name,-4,4); }else { return "身份证信息不合法"; } }}//在外部实例化Credit类$User = new Credit("360723198905010042",32);$User->idNum = "360723199905050012";echo $User->idNum;// echo $User->idNums;
二.方法重载
魔术方法之call()和callStatic()__call()方法:当对象访问不存在的方法名称时,此方法自动调用。
调用示例:public function __call($name,$argument){}
注意:访问控制关键字必须为public;必须有两个参数:对象访问的方法名称($name)、方法包含的参数($argument ==> 自动转换成数组)。
__callStatic()方法:当对象访问不存在的静态方法名称时,此方法自动调用。
调用示例:public static function callStatic($name,$argument){}
注意:同call();此方法为静态方法(static)。
魔术方法 | 含义 |
---|---|
__call($name,$argument) | 第一个参数是对象访问的方法名称,第二个参数是方法包含的参数自动转换成数组 |
__callstatic() | 同__call();此方法为静态方法(static) |
①__call()
当我们调用没有创建的方法的时候 会自动调用
__call方法
和属性调用__set
一样
②__callstatic()
__callStatic
调用未定义静态方法的时候触发,参数和__call
一样
代码块
<?php/**方法重载(方法拦截器)*|__call($name,$argument)|*第一个参数是对象访问的方法名称,*第二个参数是方法包含的参数自动转换成数组*/class User { public function __call($name, $arguments) { return "方法名称是:$name,方法属性是:".implode(",",$arguments); } public static function __callStatic($name, $arguments) { return "静态方法名称是:$name,静态方法属性是:".implode(",",$arguments); }}//当我们调用没有创建的方法的时候 会自动调用__call方法 和属性调用__set一样echo (new User)->list("admin@qq.com","13456");echo "<hr>";echo User::demo("徐峥","泰囧","港囧");
三.事件委托
事件委托 : 访问类中不存在的成员方法时, 会被魔术方法拦截, 把请求重定向到别的类的成员方法来处理
代码块
<?php// 事件委托 : 访问类中不存在的成员方法时, 会被魔术方法拦截, 把请求重定向到别的类的成员方法来处理//被委托的类class User{ //CALL 普通未定义方法 public function write(...$arr) { printf("调用方法%s(),参数有:[%s]<br>",__METHOD__,implode(",",$arr)); } //CALLSTATIC 普通未定义静态方法 public static function fetch(...$arr) { printf("调用静态方法%s(),参数有:[%s]<br>",__METHOD__,implode(",",$arr)); }}//工作类class work{ //如果希望一个属性可以在多个类中共享, 可以将该属性放到某个类中的构造函数中 private $user; public function __construct( $User) { $this->user = $User; } //创建未定义方法的时候委托到User类里面的方法来处理 public function __call($method,$arr) { //用异步请求的方式进行委托,这样可以优化性能 call_user_func([$this->user,"write"],...$arr); } public static function __callStatic($method, $arr) { call_user_func(["user","fetch"],...$arr); }}//把委托类传递到工作类的成员属性$User中$user = new User();$Work = new work($user);$Work->list(50,60,70);work::list(1,2,3);
三.数据库查询构造器
代码块
<?php/** * 事件委托 : 数据库查询构造器 * Db::table()->field()->where()->limit()->select()->toArray(); * *///被委托的类class Query{ protected $db;//pdo连接对象 protected $table; protected $field; protected $limit; //连接数据库 private function connect($dns,$username,$password) { $this->db = new PDO($dns,$username,$password); } //构造器 传递参值 public function __construct($dns,$username,$password) { $this->connect($dns,$username,$password); } //数据表方法 public function table($table) { $this->table = $table; return $this; } public function field($field) { $this->field = $field; return $this; } public function limit($limit) { $this->limit = $limit; return $this; } //sql访问语句 public function getSQL() { return sprintf("SELECT %s FROM %s LIMIT %d",$this->field,$this->table,$this->limit); } //执行查询 public function select() { return $this->db->query($this->getSQL())->fetchAll(PDO::FETCH_ASSOC); }}//工作类class Db{ static function __callStatic($method,$args) { $dns = "mysql:host=localhost;dbname=zwz"; $username = "root"; $password = "a123456"; $query = new Query($dns,$username,$password); //直接委托给Query return call_user_func([$query,$method],...$args); }}$user = Db::table()->field()->limit()->select();echo '<pre>';print_r($res);