作业1:使用方法重载与call_user_func_array()模拟TP框架的链式查询
代码1:主要实现统一入口,通过静态重载和回调函数 调用 query类
实例
<?php /** * 利用方法重载和call_user_func_array()实现跨类调用 * * 模拟TP5.1的链式查询操作 * * 主要思路: 建立一个入口类,在入口类中通过__callStatic() 静态重载方法,调用call_user_func_array()回调函数,实现 * 跨类调用查询方法:Db::table()->fields()->where()->select(); * */ include "Query.php"; //加载Query类 //建立入口类Db class Db{ public static function __callStatic($name, $arguments) { // call_user_func_array([对象,方法],[参数]) return call_user_func_array([(new Query()),$name],$arguments);//回调查询类Query的方法,$name 对应table,fields,where等方法。 } } $result = Db::table('student')->fields('name,sex,class')->where('bursary>500')->select(); echo '<pre>'; print_r($result); ////用表格输出 //$html = '<table>'; //$html .= '<caption>学生信息表</caption>'; //$html .= '<tr><th>姓名</th><th>性别</th><th>班级</th></tr>'; ////开始循环输出信息啦 // //foreach ($result as $student){ // // $html .= '<tr>'; // $html .= '<td>'.$student['name'].'</td>>'; // $html .= '<td>'.$student['sex'].'</td>>'; // $html .= '<td>'.$student['class'].'</td>>'; // $html .= '</tr>'; //} // //$html .= '</table>'; //闭合 HTML table标签语句 // //$num = count($result); // //echo $html,$num; /* * <table> * <caption></caption> * <tr> * <th>姓名</th> * <th>性别</th> * <th>班级</th> * </tr> * <tr> * //这一部分用来循环输出 * <td></td> * <td></td> * <td></td> * </tr> * * </table> */ //用美化版表格输出 $html = '<table border="1" cellpadding="10" cellspacing="0" align="center" width="60%">'; $html .= '<caption style="font-weight: bolder;font-size: 25px; margin: 20px">学生信息表</caption>'; $html .= '<tr style="font-weight: bolder ;background-color: lightgreen"><th>姓名</th><th>性别</th><th>班级</th></tr>'; //开始循环输出信息啦 foreach ($result as $student){ $html .= '<tr>'; $html .= '<td>'.$student['name'].'</td>>'; $html .= '<td>'.$student['sex'].'</td>>'; $html .= '<td>'.$student['class'].'</td>>'; $html .= '</tr>'; } $html .= '</table>'; //闭合 HTML table标签语句 $num = '<p style="text-align: center">共计:'.count($result).' 条记录</p>'; echo $html,$num;
运行实例 »
点击 "运行实例" 按钮查看在线实例
代码2: 查询类,主要负责查询方法的实现;
实例
<?php /** Query 查询类,主要被调用,实现数据库的查询功能 */ class Query{ private $sql = []; //保存返回的SQL语句参数,比如字段,条件等 private $pdo = null; //建立数据库的连接,使用构造方法,使对象建立时候就建立数据库连接 public function __construct() { $this->pdo = new PDO('mysql:host=localhost;dbname=stu','root','root'); // $this->pdo->prepare($sql); echo'连接数据库成功!'; echo'<br>'; } // table()方法,获取要查询语句的表名 public function table($table){ $this->sql['table'] = $table; //把传来的参数——表名 存放在$sql[]数组中 return $this; //返回当前对象,以便链式调用 } // 获取要查询的字段 public function fields($fields){ $this->sql['fields'] = $fields; return $this; } // where()方法获取,条件字段 public function where($where){ $this->sql['where'] = $where; return $this; } // 执行查询 public function select(){ // 从sql[]数组中取出字段信息,拼接成一条SQL语句 $sql = "SELECT {$this->sql['fields']} FROM {$this->sql['table']} WHERE {$this->sql['where']}"; echo var_export($sql); echo'<br>'; $stmt = $this->pdo->prepare($sql); $stmt->execute(); echo ($stmt->execute())?'成功!':'失败'; return $stmt->fetchAll(PDO::FETCH_ASSOC); //返回一个只有关联关系的结果集/数组 } }
运行实例 »
点击 "运行实例" 按钮查看在线实例
作业2:后期静态绑定的原理与使用场景分析 (和Java的弄混了,思考中)
<?php
/**
没有对比就没有伤害:看一下对比
* 范围解析符::的作用;
* a:可以用于访问静态成员,类常量,还可以用于覆盖类中的属性和方法。
* b:self,parent 和 static 这三个特殊的关键字是用于在类定义的内部对其属性或方法进行访问的。
* c:parent用于调用父类中被覆盖的属性或方法(出现在哪里,就将解析为相应类的父类)。
* d:self用于调用本类中的方法或属性(出现在哪里,就将解析为相应的类;注意与$this区别,$this指向当前实例化的对象)。
* e:当一个子类覆盖其父类中的方法时,PHP 不会调用父类中已被覆盖的方法。
* f:self::和parent::出现在某个类的定义中,则将被解析为相应的类,当子类覆盖了父类方法,且子类为当前工作类,则解析为子类。
* g: static关键字的三类作用:
* 1:定义静态局部变量(函数内部应用)
* 2:声明静态成员和方法(类的应用)
* 3:在范围解析符::前表示静态延迟绑定的类
*/
/*
* 转发调用:
* 通过以下几种方式进行的静态调用:self::,parent::,static:: 以及 forward_static_call()。
* 非转发调用:
* 明确指定类名的静态调用(例如Foo::foo())
*/
//原理:存储了在上一个“非转发调用”(non-forwarding call)中的类名。意思是当我们调用一个转发调用的静态调用时,实际调用的类是上一个非转发调用的类。
class A {
public static function foo()
{
echo __CLASS__."\n";
static::who();
}
public static function who (){
echo __CLASS__."\n";
}
}
class B extends A {
public static function test(){
echo "A::foo()\n";
A::foo();
echo "parent::foo()\n";
parent::foo();
echo "self::foo()\n";
self::foo();
}
public static function who () {
echo __CLASS__."\n";
}
}
class C extends B
{
public static function who(){
echo __CLASS__."\n";
}
}
C::test();
/*
* C::test(); //非转发调用 ,进入test()调用后,“上一次非转发调用”存储的类名为C
*
* //当前的“上一次非转发调用”存储的类名为C
* public static function test() {
* A::foo(); //非转发调用, 进入foo()调用后,“上一次非转发调用”存储的类名为A,然后实际执行代码A::foo(), 转 0-0
* parent::foo(); //转发调用, 进入foo()调用后,“上一次非转发调用”存储的类名为C, 此处的parent解析为A ,转1-0
* self::foo(); //转发调用, 进入foo()调用后,“上一次非转发调用”存储的类名为C, 此处self解析为B, 转2-0
* }
*
*
* 0-0
* //当前的“上一次非转发调用”存储的类名为A
* public static function foo() {
* static::who(); //转发调用, 因为当前的“上一次非转发调用”存储的类名为A, 故实际执行代码A::who(),即static代表A,进入who()调用后,“上一次非转发调用”存储的类名依然为A,因此打印 “A”
* }
*
* 1-0
* //当前的“上一次非转发调用”存储的类名为C
* public static function foo() {
* static::who(); //转发调用, 因为当前的“上一次非转发调用”存储的类名为C, 故实际执行代码C::who(),即static代表C,进入who()调用后,“上一次非转发调用”存储的类名依然为C,因此打印 “C”
* }
*
* 2-0
* //当前的“上一次非转发调用”存储的类名为C
* public static function foo() {
* static::who(); //转发调用, 因为当前的“上一次非转发调用”存储的类名为C, 故实际执行代码C::who(),即static代表C,进入who()调用后,“上一次非转发调用”存储的类名依然为C,因此打印 “C”
* }
*/
/*
故最终结果为:
A::foo()
A
A
parent::foo()
A
C
self::foo()
A
C
*/