Blogger Information
Blog 71
fans 1
comment 1
visits 86943
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
PHP类之魔术方法和类方法重载
小威的博客
Original
815 people have browsed it
  • 魔术方法:

 * 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>';

运行实例 »

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

Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post