方法重载与实战
程序员文章站
2022-03-11 13:38:57
...
1. 静态成员
静态成员是属于类的属性,只有类可以使用(这样就可以在不需要实例化类的情况下使用类中属性)。
静态成员可以实现 属性 的共享。
实例
class Demo1 { public static $name = 'jack'; function getName() { return self::$name; } public static function getPrice() { return '这是一个静态方法'; } } // 静态成员的访问用 :: 范围解析符 echo Demo1::$name; // 注意: 这里要加 $ 符 echo (new Demo1())->name; // 无法用 对象来调用 静态属性 echo Demo1::getPrice(); // 静态方法调用 echo (new Demo1())->getPrice(); // 静态方法可以用对象调用,这里要注意,尽量不要这样去做,以后应该会取消这种写法 echo Demo1::getName(); // 类调用 实例属性是不允许的
运行实例 »
点击 "运行实例" 按钮查看在线实例
2. 属性重载
重载:当外部访问一个不存在的或是没有权限的属性时会自动调用重载方法
属性重载有以下四种:__get __set __isset __ unset
重载方法都是魔术方法,不允许用户调用,由系统调用
实例
class Demo1 { private $name; protected $age; public function __construct($name, $age) { $this->name = $name; $this->age = $age; } // 读 $name 代表的是访问的属性名称 public function __get($name) { if ($name == 'name') { return '姓名:'.$this->name; } else if ($name == 'age') { return '年龄:'.$this->age; } return $this->$name; } // 写 // $name: 属性名 // $value: 设置的属性值 public function __set($name, $value) { if ($name == 'name') { $this->name = '重写后:' . $value; } else if ($name == 'age') { $this->age = '重写后:' . $value; } } // 判断是否存在 public function __isset($name) { // 在类中属性是存在的 return isset($this->name); } // 销毁属性 public function __unset($name) { // unset没有返回值 unset($this->name); } } $obj1 = new Demo1('TOM', 3); echo '<pre></pre>'; echo $obj1->name; echo $obj1->age; // 这里会调用 __get echo '<hr/>'; $obj1->name = 'Tom'; // 这里会调用 __set echo $obj1->name; echo '<hr/>'; // 在没有使用 __isset重载前,这里是 假,因为访问控制 echo isset($obj1->sex) ? '真' : '假'; unset($obj1->name); // 在没有使用 __unset重载前,这里报错,无法销毁 echo $obj1-
运行实例 »
点击 "运行实例" 按钮查看在线实例
3. call_user_func 和 call_user_func_array
回调执行函数,把第一个参数作为回调函数执行
这两个方法功能一样,只是参数传递格式不一样
实例
namespace php_1008; function minus($a, $b) { return "{$a} - {$b} = " . ($a - $b) . '<hr/>'; } // 调用这个方法 // echo call_user_func('minus',13,12); // 这样是找不到的,需要加上命名空间 echo call_user_func(__NAMESPACE__ . '\minus', 13, 2); echo call_user_func_array(__NAMESPACE__ . '\minus', [13, 2]); class Demo { // 声明一个普通方法 public function minus($a, $b) { return "{$a} - {$b} = " . ($a - $b) . '<hr/>'; } // 声明一个静态方法 public static function sum($a, $b) { return "{$a} + {$b} = " . ($a - $b) . '<hr/>'; } } // 访问对象方法,需要传递对象和函数名 数组 echo call_user_func(array(new Demo(), 'minus'), 29, 10); echo call_user_func([new Demo(), 'minus'], 43, 21); // 访问静态方法,传递 类名和 方法名 数组,也可以直接写 方法名 echo call_user_func(Demo::class.'::sum', 67, 25); echo call_user_func(array(__NAMESPACE__.'\Demo','sum'), 74, 34); echo call_user_func(array(Demo::class,'sum'), 77, 56); // 访问对象方法 echo call_user_func_array([new Demo(), 'minus'], [56, 38]); // 访问静态方法 echo call_user_func_array(Demo::class.'::sum', [29, 10]); echo call_user_func_array([Demo::class, 'sum'], [90, 19]);
运行实例 »
点击 "运行实例" 按钮查看在线实例
4. 方法重载
__call 和 __callStatic(重载静态方法),当执行一个不存在或是无权限访问的方法时会自动调用这些方法。
可以将这个看做为一种方法的监督机制。
实例
class Demo3 { // __call 访问一个不存在或无权限访问的方法的时候会自动调用 public function __call($name, $args) { echo $name; print_r($args); echo '<br/>'; } // __callStatic 重载静态方法 public static function __callStatic($name, $args) { echo $name; print_r($args); echo '<br/>'; } } (new Demo3())->getName1(1, 2, 90); Demo3::getAge(3,90,7);
运行实例 »
点击 "运行实例" 按钮查看在线实例
5. 数据库链接调用的实现
实现以下形式的对于数据库的增改删查操作,使用链式调用的形式。
$email = DB::table('users')->where('name', 'John')->value('email');
链式调用就在于每次调用都会返回一个当前实例以便于下一步操作的调用。
首先先建一个数据库查询类 Query,php
<?php namespace zmx1008; class Query { public $pdo = null; public $table; public $field; public $value; public $where; public $limit; // 初始化,将 pdo 传入 public function __construct($pdo) { $this->pdo = $pdo; } // 获取表名 public function table($table) { $this->table = $table; return $this; } // 获取选择的字段 public function field($field = '*') { $this->field = empty($field) ? '*' : $field; return $this; } // 新值 public function value() { // $this->value = empty(value) ? '*' : $field; return $this; } // 查询条件 public function where($where = '') { // 关键字之间的 空格 不要忘了 $this->where = empty($where) ? $where : ' WHERE ' . $where; return $this; } // 条数限制 public function limit($limit) { $this->limit = empty($limit) ? $limit : ' LIMIT ' . $limit; return $this; } // 查询方法 public function select() { // 拼接 sql 语句 $sql = 'SELECT ' . $this->field . ' FROM ' . $this->table . $this->where . $this->limit; $stmt = $this->pdo->prepare($sql); if ($stmt->execute()) { return $stmt->fetchAll(\PDO::FETCH_ASSOC); } else { echo $sql; die('查询失败:' . print_r($stmt->errorInfo())); } } // 增加方法 public function insert($data) { $set = ' SET '; foreach ($data as $key => $value) { $set .= $key . ' =:' . $key . ', '; } // 去掉最后一个 逗号 $set = rtrim($set, ", "); $sql = 'INSERT INTO ' . $this->table . $set; $stmt = $this->pdo->prepare($sql); if ($stmt->execute($data)) { if ($stmt->rowCount() > 0) { echo '成功新增了' . $stmt->rowCount() . '条记录,最后一条记录主键为' . $this->pdo->lastInsertId(); } } else { die('新增失败:' . print_r($stmt->errorInfo())); } } // 更新方法 public function update($data){ $set = ' SET '; foreach ($data as $key => $value) { $set .= $key . ' =:' . $key . ', '; } // 去掉最后一个 逗号 $set = rtrim($set, ", "); $sql = 'UPDATE ' . $this->table . $set.$this->where; $stmt = $this->pdo->prepare($sql); if ($stmt->execute($data)) { if ($stmt->rowCount() > 0) { echo '成功更新了' . $stmt->rowCount() . '条记录'; } } else { die('更新失败:' . print_r($stmt->errorInfo())); } } // 删除方法 public function delete(){ $sql = 'DELETE FROM '. $this->table. $this->where. $this->limit; $stmt = $this->pdo->prepare($sql); if($stmt->execute()){ if($stmt->rowCount() > 0){ echo '成功删除了'.$stmt->rowCount().'条记录'; } }else { echo $sql; die('查询失败:' . print_r($stmt->errorInfo())); } } }
数据库的操作就需要另一个类 DB.php
<?php namespace zmx1008; // 不要忘了先引入 查询类 require 'Query.php'; // DB 类的主要作用就是连接数据库以及方法重载 查询类中的方法 class DB { public static $pdo = null; // 这里的连接方法不能都用 构造方法实现, // 因为 构造方法只有在 类实例化时才执行,但是这里 $pdo是静态的,初始化并不需要实例对象 public static function connection() { self::$pdo = new \PDO('mysql:host=127.0.0.1;dbname=zmx;', 'root', 'root'); } // 这里是最关键的部分,使用方法重载来执行不同操作 public static function __callStatic($name, $arguments) { self::connection(); // 这里选用 call_user_func_array(), 因为 $arguments 是个数组 print_r(self::$pdo); $query = new Query3(self::$pdo); // 这里一定要 return // 这样才可以一直保持每次调用都返回一个当前类的实例 return call_user_func_array([$query, $name], $arguments); } } // 查询 $movies = DB::table('movies') ->field('mov_id,name') ->where('mov_id > 2') ->limit(5) ->select(); foreach ($movies as $movie) { print_r($movie); echo '<br>'; } // 更新 $newUpdate = [ 'name' => '水浒传', 'detail' =>'更新detail', 'cate_id' =>1, ]; DB::table('movies')->where('mov_id=10')->update($newUpdate); // 增加 $newInsert = [ 'name' => '西游记', 'image' => '', 'detail' =>'四大名著之一', 'cate_id' =>2, ]; DB::table('movies')->insert($newInsert); // 删除 DB::table('movies')->where('mov_id = 11')->delete();