属性与方法访问拦截器
一、后期静态绑定应用场景
class Base
{
public static function index()
{
return __METHOD__;
}
//把Index方法放到另一个方法中
public static function fetch()
{
return static::index();
}
}
echo Base::fetch(),'<br>';
//User类继承Base类
class User extends Base
{
public static function index()
{
return __METHOD__;
}
}
echo User::index(),'<br>';
echo User::fetch();
二、构造方法的使用
<?php
//魔术方法
//魔术方法:由一个事件/行为来自动的触发,不允许用户主动调用
class Product
{
public $name = '手机';
public $price = 3000;
//构造方法,实现对类的初始化,并且在new的时候自动调用
public function __construct($name,$price)
{
//1.生成一个对象
//$this = new self($name,$price);
//2.给这个对象初始化
$this->name = $name;
$this->price = $price;
echo $this->getInfo();
//3.返回这个对象
//return $this;
}
//输出方法
public function getInfo()
{
return $this->name.':'.$this->price.'元';
}
//析构方法
public function __destruct()
{
//注销时执行或者在方法最后执行
echo '我是析构方法';
}
}
$product = new Product('中华',100);
//echo ''.$product->name.':'.$product->price.'元<hr>';
/* $product->name = '电脑';
$product->price = 10000;
echo $product->name.':'.$prodict->price.'<hr>'; */
三、属性访问拦截器
__get()
:当外部访问一个或者无权限访问的属性的时候会自动调用,__get()返回值是属性名称
__set()
:给无权限访问的属性赋值时会自动调用,__set()返回值是属性名称
__isset()
:当对不可访问属性调用 isset() 或 empty() 时自动调用
__unset()
:当对不可访问属性调用 unset() 时自动调用
<?php
//重载:“访问拦截器”
//类:二类成员,属性和方法,所以也有两种重载:属性和方法重载
//换个叫法:属性拦截器和方法拦截器
class Product
{
private $name;
private $price;
//税率
private $tax = 0.06;
public function __construct($name,$price)
{
$this->name = $name;
$this->price = $price;
//echo $name;
}
//__get():当外部访问一个或者无权限访问的属性的时候会自动调用
//外部访问私有属性或者受保护的属性
//如果你类中定义有--get方法 会自动调用 参数就是你访问的属性值
//get返回属性名称
public function __get($name)
{
//根据属性名称生成对应的属性访问接口方法
//生成方法名
$method = 'get'.ucfirst($name);
//echo $method;
//调用这个处理属性访问的方法
//方法存在就调用这个方法,不存在就返回null
return method_exists($this, $method) ? $this->$method() : null;
//return method_exists($this, $method) ? $this->$method() : null;
}
public function __set($name,$value)
{
$method = 'set'.ucfirst($name);
return method_exists($this, $method) ? $this->$method($value) : null;
}
private function getName()
{
return mb_substr($this->name,0,5);
}
private function getPrice()
{
return $this->price + $this->price * $this->tax;
}
private function setName($value)
{
return $this->name = $value;
}
private function setPrice($value)
{
return $this->price =$value * (1 - $this->tax);
}
public function __isset($name)
{
echo '我是__isset()魔术方法';
}
public function __unset($name)
{
echo '我是__unset魔术方法';
}
}
$product = new Product('组装电脑 cpu:i7 9700',5500);
//这个方法实际中应该在类的内部调用
//echo $product->name .':'.$product->price;
echo $product->name,'...含税价:',$product->price.'元';
/* echo '<hr>';
echo $product->price; */
$product->name = '手机';
$product->price = 1000;
echo '<hr>'.$product->name,'不含税:',$product->price.'元<hr>';
var_dump(isset($product->name));
echo '<hr>';
unset($product->name);
四、方法拦截器
<?php
//方法拦截器
//当从类的外部,访问类中不存在或者无权限访问的方法的时候,会自动调用它
class User
{
//方法拦截器也是一个魔术方法__call(方法名称,参数数组)
public function __call($name,$arr)
{
echo '__call()魔术方法<br>';
printf('方法名:%s(),参数[%s]',$name,implode(',',$arr));
}
//静态方法拦截器:__callStatic(方法名称,参数数组)
public static function __callStatic($name,$arr)
{
echo '__callStatic()魔术方法<br>';
printf('方法名:%s(),参数[%s]',$name,implode(',',$arr));
}
}
$user = new User();
//调用当前类中不存在或者不可访问的方法时自动调用__call()魔术方法
$user->hello('cat','pig','dog');
echo '<hr>';
User::demo(1,2,3,4);
五、事件委托
<?php
//事件委托
class Base
{
public function write(...$arr)
{
printf('方法名:%s(),参数[%s]',__METHOD__,implode(',',$arr));
}
public static function fetch(...$arr)
{
printf('方法名:%s().参数[%s]',__METHOD__,implode(',',$arr));
}
}
//工作类
class Work
{
//事件委托时,重定向到的类
private $base;
//将$base初始化
public function __construct(Base $base)
{
$this->base = $base;
}
public function __call($name,$arr)
{
return call_user_func_array([$this->base,'write'],$arr);
}
public static function __callStatic($name, $args)
{
if (method_exists('Base', $name))
return call_user_func_array(['Base', 'fetch'], $args);
}
}
$base = new Base();
$work = new Work($base);
$work->write(1,2,3);
echo '<hr>';
$work::fetch('a','b','c');
六、方法委托实战
<?php
//方法委托实战:数据库查询构造器(链式查询)
//查询类
class Query
{
//连接对象
protected $db;
//数据表
protected $tale;
//字段列表
protected $field;
//记录数量
protected $limit;
//构造方法:连接数据库
public function __construct($dsn,$username,$password)
{
$this->connect($dsn,$username,$password);
}
//连接数据库
private function connect($dsn,$username,$password)
{
$this->db = new PDO($dsn,$username,$password);
}
//设置默认的数据表名称
public function table($table)
{
$this->table = $table;
return $this;
}
//设置默认的字段名称
public function field($field)
{
$this->field = $field;
return $this;
}
//链式方法:设置查询数量
public function limit($limit)
{
$this->limit = $limit;
return $this;
}
//生成查询语句
protected function getSql()
{
return sprintf('SELECT %s FROM %s LIMIT %s',$this->field,$this->table,$this->limit);
}
//执行查询
public function select()
{
return $this->db->query($this->getSql())->fetchAll(PDO::FETCH_ASSOC);
}
}
//数据库操作类
class DB
{
//静态方法委托
public static function __callStatic($name,$arr)
{
//获取到查询类的对象:new Query()
$dsn = 'mysql:host=localhost;dbname=tp5';
$username = 'root';
$password = 'wang1111';
$query = new Query($dsn,$username,$password);
return call_user_func([$query,$name], ...$arr);
}
}
$result = DB::table('user')->field('id,name')->limit(3)->select();
print_r($result);
七、学习总结
- 只能理解大概意思,有好多语句并不知道为什么这样用,我理解的方法委托就是在一个类的方法中调用另一个类的方法,然后在类外部调用