类中方法重载的代码实例演示如下:
<?php /** * 重载: 动态的"创建"出类的属性和方法 * 重载都是借助: 魔术方法来实现的,用双下划线开头的特殊方法 * 重载方法必须声明为: public * 重载分为: 属性重载和方法重载 * 属性重载: __get(),__set(),__isset(),__unset() * 方法重载: __call(), __callStatic() * 1. __call($method, $arguments): 当用户访问一个不存在或无权限的方法时调用 * 2.__callStatic($method, $arguments):当用户访问一个不存在或无权限的静态方法时调用 */ class Test { // 普通方法的重载 public function __call($method, $arguments) { // return $method; // 方法名称 // return $arguments; $args = implode(',',$arguments); return '方法名: '. $method. '<br>参数: '. $args; } //创建一个私有方法 private function select() { return __METHOD__; } // 静态方法的重载 public static function __callStatic($name, $arguments) { $args = implode(',',$arguments); return '方法名: '. $name. '<br>参数: '. $args; } } $test = new Test(); 访问一个不存在的非静态/普通/动态方法 echo $test->show(), '<br>'; print_r($test->show('合肥','杭州','上海')); echo $test->show('合肥','杭州','上海'), '<br>'; echo $test->select('staff','id,name,age'),'<br>'; echo '<hr>'; // 我从类外部访问一个不存在的静态方法 echo Test::assign('html','css','javascript');
点击 "运行实例" 按钮查看在线实例
使用call_user_func_array()模拟TP框架的链式查询操作代码实例演示如下:
<?php /** * 数据库查询类 */ class Query { // 保存sql语句中的各个组成部分 // SELECT 字段列表 FROM 表名 WHERE 条件 private $sql = []; // 数据库的连接对象 private $pdo = null; //构造方法: 连接数据库 public function __construct() { // 连接数据库并返回pdo对象 $this->pdo = new PDO('mysql:host=127.0.0.1;dbname=php','root','root'); } // table()获取sql语句的表名 public function table($table) { $this->sql['table'] = $table; return $this; //返回当前类实例对象,便于链式调用该对象的其它方法 } // fields()获取sql语句的字段列表 public function fields($fields) { $this->sql['fields'] = $fields; return $this; } // where()获取sql语句的查询条件 public function where($where) { $this->sql['where'] = $where; return $this; } //执行查询,是一个终级方法 public function select() { //拼装SELECT查询语句 $sql = "SELECT {$this->sql['fields']} FROM {$this->sql['table']} WHERE {$this->sql['where']}"; $stmt = $this->pdo->prepare($sql); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC); } }
点击 "运行实例" 按钮查看在线实例
<?php /** * 方法重载的实战案例: 模拟ThinkPHP5.1中的数据库链式操作 * 用方法重载实现方法跨类调用 */ // Db::table()->fields()->where()->select(); require 'Query.php'; // 数据库操作的入口类 class Db { public static function __callStatic($name, $arguments) { //call_user_func_array([类名, 方法],[]) //call_user_func_array([对象, 方法],[]) return call_user_func_array([(new Query()),$name],$arguments); } } $result = Db::table('staff') ->fields('id,name,age,salary') ->where('salary > 2000') ->select(); //print_r($result); // 用表格将查询结果格式化输出 $table = '<table border="1" cellpadding="5" cellspacing="0" width="60%" align="center">'; $table .= '<caption style="font-size: 1.5rem;margin:15px;">员工信息表</caption>'; $table .= '<tr bgcolor="#90ee90"><th>ID</th><th>姓名</th><th>年龄</th><th>工资</th></tr>'; foreach ($result as $staff) { $table .= '<tr align="center">'; $table .= '<td>'.$staff['id'].'</td>'; $table .= '<td>'.$staff['name'].'</td>'; $table .= '<td>'.$staff['age'].'</td>'; $table .= '<td>'.$staff['salary'].'</td>'; $table .= '</tr>'; } $table .= '</table>'; $num = '<p style="text-align: center"> 共计: <span style="color:red">'.count($result).'</span> 条记录</p>'; echo $table, $num;
点击 "运行实例" 按钮查看在线实例
后期静态绑定的原理与使用场景分析:
后期静态绑定工作原理是存储了在上一个“非转发调用”(non-forwarding call)的类名。当进行静态方法调用时,该类名即为明确指定的那个(通常在 :: 运算符左侧部分);当进行非静态方法调用时,即为该对象所属的类。所谓的“转发调用”(forwarding call)指的是通过以下几种方式进行的静态调用:self::,parent::,static:: 以及 forward_static_call()。可用 get_called_class() 函数来得到被调用的方法所在的类名,static:: 则指出了其范围。该功能从语言内部角度考虑被命名为“后期静态绑定”。“后期绑定”的意思是说,static:: 不再被解析为定义当前方法所在的类,而是在实际运行时计算的。也可以称之为“静态绑定”,因为它可以用于(但不限于)静态方法的调用。后期静态绑定本想通过引入一个新的关键字表示运行时最初用的类来绕过限制。简单地说,这个关键字能够让你在上述例子中调用 test() 时引用的类是 B 而不是 A。最终决定不引入新的关键字,而是使用已经预留的 static 关键字。后期静态绑定本想通过引入一个新的关键字表示运行时最初调用的类来绕过限制简单地说,这个关键字能够让你在上述例子中调用 test() 时引用的类是B 而不是 A。最终决定不引入新的关键字,而是使用已经预留的 static 关键字。
课堂总结:
9月4号课堂总结今天学习了类的方法重载和后期静态方法绑定的原理及使用场景,如何使用call _user _func _array ()模拟TP 框架的链式查询操作。call _user _func _array ()的使用场景有三个:第一,执行回调函数;第二,执行对象方法;第三,执行类中的静态方法。后期静态绑定的关键词是static ,主要作用是静态继承上下文的调用者。本堂课最重要的一点就是了解了一下TP 框架的结构和部分方法,一开始我其实是拒绝的,因为全都是英文,看的我头晕眼花,但是朱老师对我们说学习就是要迎难而上,越是不懂的越是要花时间去琢磨直到解决这个问题。学习并不可怕,可怕的是自己内心对学习产生了恐惧的心理。