博客列表 >PHP类之魔术方法和类方法重载

PHP类之魔术方法和类方法重载

小威的博客
小威的博客原创
2018年06月06日 08:13:43816浏览
  • 魔术方法:

 * 1.类中以双下划线开头的方法,这是由系统内置的,用户方法不要用双下划线开头;

 * 2.魔术方法由系统在一定条件下自动触发调用,用户不能直接调用;

 * 注意:将类中的私有成员前面添加单下划线是一个好习惯;

 * 例如: private $_salary;    private function _listUsers(){...}

 * 使用魔术方法实现几个对象访问拦截器

 * 所谓拦截器:就是对用户的一些错误或非法访问进行检测和控制。


 * 之前我们学过__get($fieldName)和__set()这是二个最常用的拦截器

 * 现在我们再学习一组: __isset($fieldName)和__unset($fieldName)

 

1. __isset():当在类外检测一个类属性是否存在时会自动调用

2. __unset():当在类外销毁一个类属性时会自动调用  

实例

<?php
class Demo 
{
    private $name = 'peter';
    private $email = 'peter@php.cn';
    
    //当在类外使用isset()检测某个属性是否存在时自动调用
    public function __isset($name)
    {
        //对访问进行过滤:如果属性名是'name',返回false,否则允许访问
        //即除了'name'属性外的其它属性允许外部进行isset()检测
        return ($name=='name') ? false : true;
    }
}
//实例化 Demo 类
$obj = new Demo;
//检测$obj中是否有name属性,返回 
echo isset($obj->name)?'存在':'不存在';
echo '<hr>';
//检测$obj中是否存在email属性,返回存在,因为类中__isset()返回true
echo isset($obj->email)?'存在':'不存在';
//在外部使用unset()来销毁类属性

运行实例 »

点击 "运行实例" 按钮查看在线实例



  • 类方法重载: __call()和__callStatic()

1.call($name,$array): 当类外访问一个不存在的方法时自动调用

2.callStatic($name,$array):当类外访问一个不在静态上下文中的方法时自动调用

用途:

 1.防止访问不存在的方法时报错;

 2.其实最有用的应用场景是动态生成一个可访问的方法,实现方法的跨类调用


先创建一个数据库查询类: Query.php


实例

<?php

//数据库查询类

class Query
{
    private $pdo = null;  //数据库连接对象
    
    private $stmt = null; //预处理语句对象
    
    private $table = '';  //数据表名
    
    private $field = '';  //字段列表
    
    private $where = '';  //查询条件
    
    private $order = '';  //排序规则

    //构造方法: 初始化连接对象
    public function __construct($pdo)
    {
        $this->pdo = $pdo;
    }
    
    //设置数据表名
    public function table($table)
    {
        $this->table = $table;
        
        //***返回当前对象,便于链式调用后面的方法
        return $this;
    }
    
    //设置字段列表
    public function field($field)
    {
        $this->field = $field;
        
        //***返回当前对象,便于链式调用后面的方法
        return $this;
    }

    //设置查询条件
    public function where($where)
    {
        $this->where = $where;
        
        //***返回当前对象,便于链式调用后面的方法
        return $this;
    }
    
    //设置排序规则
    public function order($order)
    {
        $this->order = $order;
        
        //***返回当前对象,便于链式调用后面的方法
        return $this;
    }

    //单条查询语句: 仅返回符合条件结果集中的第一条记录
    public function find()
    {
        //简化查询参数
        $table = $this->table;
        $field = $this->field;
        $where = $this->where;
        
        //设置SQL语句
        $sql = "SELECT {$field} FROM {$table} {$where} LIMIT 1;";
//        die($sql);
        
        //创建预处理语句对象
        $this->stmt = $this->pdo->prepare($sql);
        
        //执行预处理查询
        $this->stmt->execute();
        
        //返回预处理查询的结果集(单条查询返回一维数组)
        return $this->stmt->fetch(PDO::FETCH_ASSOC);
        
        //***注: find是最终方法,负责执行SQL查询,不用返回当前对象$this
    }
    
    //多条查询语句
    public static function select($db,$table,$field,$where,$order)
    {
        //设置SQL语句
        $sql = "SELECT {$field} FROM {$table} {$where} {$order};";
//        die($sql);
        
        //为了简化代码,这里不再使用PDO来处理,直接使用原生的MySQLi来完成查询
        $res = mysqli_query($db, $sql);
        
        return mysqli_fetch_all($res);
        
        //***注: select是最终方法,负责执行SQL查询,不用返回当前对象$this
    }
}

运行实例 »

点击 "运行实例" 按钮查看在线实例


调用测试源码

实例

<?php
//导入数据库查询类
spl_autoload_register(function($className){
    require './class/'.$className.'.php';
});


class Db 
{
    public $pdo = null;
    public function __construct($host='localhost',$user='root',$pass='root',$dbname='php')
    {
        try {
            $this->pdo = new PDO("mysql:host={$host};dbname={$dbname}",$user,$pass);
        
            
        } catch (PDOException $e) {
            echo 'Connection failed: ' . $e->getMessage();
        }       
    }
    
    //当访问一个不存在的动态方法时会自动触发
    public function __call($name,$args)
    {
       $query = new Query($this->pdo);
       return call_user_func_array([$query,$name], $args);
    }
    
    //当访问一个不存在的静态方法时会自动触发,注意这个方法必须声明为public static
    public static function __callStatic($name,$args)
    {
       return call_user_func_array(['Query',$name], $args);
    }
}


//实例化Db
$db = new Db('localhost','root','root','php');

运行实例 »

点击 "运行实例" 按钮查看在线实例


任务一: 使用__call()实现动态方法的跨类调用

 * 1. 从Db类中去动态的执行Query类中的方法

 * 2. 返回符合条件的单条记录

 * 3. 使用PDO预处理对象完成


实例

<?php
/**接上**/

//实例化Db
$db = new Db('localhost','root','root','php');

//设置查询参数,因为是单条查询,无须设置排序规则$order
$table = 'staff';  //表名
$field = 'name,age,salary '; //字段列表
$where = 'WHERE age < 20 '; //查询条件

//链式调用Query查询类中的find()方法来完成查询
$row = $db->table($table)->field($field)->where($where)->find();

//查看单条查询结果
echo '<pre>'.print_r($row,true).'</pre>';

运行实例 »

点击 "运行实例" 按钮查看在线实例


任务二: 使用__callStatic()实现静态方法的跨类调用

 * 1. 从Db类静态调用Query中的静态方法

 * 2. 返回符合条件的多条记录

 * 3. 使用PDO预处理对象完成

实例

<?php
/**同上接上**/

//设置查询参数,增加一个排序规则$order
$table = 'staff';  //表名
$field = 'name,age,salary '; //字段列表
$where = 'WHERE age < 25 '; //查询条件
$order = 'ORDER BY age DESC';

//链式调用Query查询类中的select()方法来完成查询
//为简化代码,使用原生MySQLi来完成查询
$db = mysqli_connect('localhost', 'root', 'root', 'php');
$rows = Db::select($db,$table,$field,$where,$order);

//查看单条查询结果
echo '<pre>'.print_r($rows,true).'</pre>';

运行实例 »

点击 "运行实例" 按钮查看在线实例

上一条:java遗传算法下一条:适配器模式
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议