PHP:oop->重载之set/get/call/callStatic,oop事件委托,数据库查询构造器

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( n a m e , name, name,argument){}
    注意:访问控制关键字必须为public;必须有两个参数:对象访问的方法名称( n a m e ) 、 方 法 包 含 的 参 数 ( name)、方法包含的参数( name)(argument ==> 自动转换成数组)。

__callStatic()方法:当对象访问不存在的静态方法名称时,此方法自动调用。

  • 调用示例:public static function __callStatic( n a m e , name, name,argument){}
    注意:同__call();此方法为静态方法(static)。
魔术方法含义
__call( n a m e , name, 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);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值