1、实例演示四个属性重载的魔术方法;
2、实例演示call_user_func_array()回调执行函数/对象/类的方法的流程与方式;
3、实例演示方法重载的实现原理与参数获取方式;
4、实例演示数据库连接调用的实现原理与过程(静态方法重载__callStatic实现)
总结:
【1.2.3】集中到一个实例中演示。【4】数据库连接调用在一个实例中演示。
经过练习发现听得懂看得懂,轮到自己写感觉还是不熟练。总结一下完成过程中发现的问题:
1、使用__unset()自动重载unset()来删除类内成员属性,发现unset后确实访问不到了,但是isset()检查这个属性还是存在,还可以赋值,赋值后又可以正常访问到了。
2、为了避免外部访问重载的魔术方法,我把__set()设为private,结果php会给出警告,建议设为public,这是为什么?
3、对于__call()和__callStatic(),在练习中发现,__call()是可以不管你是静态方法还是实例方法,只要使用$obj->methodname()来调用无权访问或不存在的方法,都自动执行到__call(),在这里随便是private方法还是static方法,都可以在类内转调用,也就是可以实现外部访问类内的私有方法。而__callStatic()则只能针对ClassName::methodname()的自动处理,如果在这里执行类内的常规成员方法,会执行,但要给出一个“非静态声明”的警告。
4、没搞明白的是 --->下面这句代码 应该是调用了5次 __callStatic(),那是不是在__callStatic()里,建立了5次连接,实例化了5次 Query?我在代码中做了微调,竟然也成功了。
$staffs = DB::table('staff')
->field('staff_id,name,position,mobile')
->where('staff_id>4')
->limit(6)
->select();
代码如下:
实例 ---- 【1.2.3】集中到一个实例中演示
<?php
namespace _1008;
//创建一个画图类,为了练习类常量、静态属性、静态方法以及属性重载和方法重载;
class Draw {
const DPI = 72; //屏幕分辨率;类常量;
public static $width = 600; //画布的宽度;静态成员: 用static限定,是类属性
public static $height = 400; //画布的高度;静态成员: 用static限定,是类属性
private $pen; //画布的笔 ;私有成员属性;
private $color; //画笔的颜色;私有成员属性;
private $bkcolor = '白色'; //画布的背景颜色;私有成员属性;
protected $scale = 1; //图画的比例;受保护的成员属性;
//构造函数
public function __construct($pen, $color) {
$this->pen = $pen;
$this->color = $color;
}
//设置属性重载:针对访问一个不存在的
public function __get($property) {
return isset($property) ? $this->$property : '属性不存在';
}
public function __set($property, $value) {
switch (true) {
case $property == 'scale':
$this->$property = (($value > 0) && ($value <= 1)) ? $value : 1;
break;
case $property == 'pen':
$this->$property = (is_string($value) ? $value : '铅笔');
break;
case $property == 'color':
$this->$property = (is_string($value) ? $value : '黑色');
break;
case $property == 'bkcolor':
$this->$property = (is_string($value) ? $value : '白色');
break;
default:
if (isset($property)) {
$this->$property = $value;
}
break;
}
}
public function __isset($property) {
$has = isset($property) ? true : false;
return ($property == 'scale') ? false : $has;
// return ($property == 'scale') ? false : (isset($property) ? true : false);
}
public function __unset($property) {
if ($property == 'bkcolor') {
unset($this->$property);
echo '成功删除 ' . $property . '属性', '<br>';
} else {
echo '不允许删除' . $property . '属性', '<br>';
}
return;
}
//设置一个静态方法来重置静态属性
//静态方法中不允许调用实例属性,但实例方法中可以使用静态属性。
public static function resetCanvas($newWidth, $newHeight) {
self::$width = $newWidth;
self::$height = $newHeight;
}
//设置一个私有的成员方法
private function drawLine() {
return '画一条直线';
}
private static function drawRect() {
return '画一个矩形';
}
//设置__call()方法重载,访问不存在或无权访问的成员方法时自动执行;
public function __call($method, $params) {
if (method_exists(self::class, $method)) {
return call_user_func_array([(self::class), $method], $params);
}
return '实例方法调用:' . $method . ' 不存在!<br>参数:<pre>' . print_r($params, true) . '</pre>';
// return method_exists(self,$method)?'yes':'no';
}
//设置__callStatic()方法重载,访问不存在或无权访问的静态方法时自动执行;
public static function __callStatic($method, $params) {
if (method_exists(self::class, $method)) {
return call_user_func_array([(self::class), $method], $params);
}
return '静态方法调用:' . $method . ' 不存在!<br>参数:<pre>' . print_r($params, true) . '</pre>';
}
}
//---------------客户端测试----属性重载-----------------//
echo '类常量 DPI: ' . Draw::DPI, '<br>';
echo '画布宽度: ' . Draw::$width, ' 画布高度: ' . Draw::$height, '<br>';
echo '利用静态方法重设画布尺寸', '<br>';
Draw::resetCanvas(800, 600);
echo '画布宽度: ' . Draw::$width, ' 画布高度: ' . Draw::$height, '<br>';
echo '类常量和类静态属性方法,不需要实例化即可使用执行';
echo '<hr>';
$draw = new Draw('细毛笔', '黑色');
echo $draw->pen, '<br>';
echo $draw->color = '红色', '<br>';
echo isset($draw->scale) ? '有scale属性' : '无scale属性', '<br>';
echo isset($draw->bkcolor) ? '有bkcolor属性' : '无bkcolor属性', '<br>';
echo '<hr>';
echo $draw->bkcolor, '<br>';
unset($draw->bkcolor);
// echo $draw->bkcolor = '红色', '<br>';
echo $draw->bkcolor, '<br>';
// echo isset($draw->bkcolor) ? '有bkcolor属性' : '无bkcolor属性', '<br>';
echo '<hr>';
unset($draw->pen);
echo isset($draw->pen) ? '有pen属性' : '无pen属性', '<br>';
echo '<hr>';
//---------------客户端测试----方法重载-----------------//
echo '方法重载测试:', '<br>';
echo $draw->drawLine(0, 10, 100, 10);
echo '<hr>';
echo $draw->drawRect(0, 10, 100, 10);
echo '<hr>';
echo $draw->drawCircle(10, 10, 50);
// echo $draw::drawLine(0, 10, 100, 10);
// echo '<hr>';
echo $draw::drawRect(0, 10, 100, 10);
echo '<hr>';
echo $draw::drawCircle(10, 10, 50);
?>
运行实例 »
点击 "运行实例" 按钮查看在线实例运行效果为:

实例 --- 【4】数据库连接调用在一个实例中演示
<?php
namespace _1008;
class Query {
public $pdo = null;
public $table;
public $field = '*';
public $where;
public $limit;
public function __construct($pdo) {
$this->pdo = $pdo;
}
public function table($tableName) {
$this->table = $tableName;
return $this;
}
public function field($fields = '*') {
$this->field = empty($fields) ? '*' : $fields;
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 = 'SELECT '
. $this->field
. ' FROM '
. $this->table
. $this->where
. $this->limit;
$stmt = $this->pdo->prepare($sql);
$stmt->execute();
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
}
}
//-------------以下合并写DB class---------------//
class DB {
protected static $pdo = null;
protected static $query = null;
public static function connection() {
try {
self::$pdo = new \PDO('mysql:host=127.0.0.1;dbname=test', '******', '********');
} catch (PDOException $e) {
die('连接数据库 失败:' . $e->getMessage());
}
self::$query = new Query(self::$pdo);
}
public static function __callStatic($name, $argus) {
return call_user_func_array([self::$query, $name], $argus);
}
}
DB::connection();
$staffs = DB::table('staff')
->field('staff_id,name,position,mobile')
->where('staff_id>4')
->limit(6)
->select();
foreach ($staffs as $value) {
print_r($value);
echo '<br>';
}
?>
运行实例 »
点击 "运行实例" 按钮查看在线实例
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号