批改状态:合格
老师批语:
__get(),__set()__call(),__callStatic()
// 查询拦截器public function __get($name){// $name : 属性名if (array_key_exists($name, $this->data)) {return $this->data[$name];}return "属性 {$name} 不存在";}
// 更新拦截器public function __set($name, $value){// 1. 有没有这个属性?if (array_key_exists($name, $this->data)) {// 2. 这个值是否合法?if ($name === 'age') {if ($value >= 18 && $value <= 59) {$this->data[$name] = $value;} else {echo '年龄必须在18-59之间';}} else {// 以上操作仅对age有效,其它属性直接赋值$this->data[$name] = $value;}} else {echo '禁止动态创建属性';}}
// 方法拦截器public function __call($name, $args){// $name: 方法名, $args: 传给方法的参数printf('方法: %s<br>参数:<pre>%s</pre>', $name, print_r($args, true));}
// 静态方法拦截器public static function __callStatic($name, $args){// $name: 方法名, $args: 传给方法的参数printf('方法: %s<br>参数:<pre>%s</pre>', $name, print_r($args, true));}
<?php// 方法重载的小案例// Db::table('think_user')->where('id', 1)->find();// 1. 查询类class Query{public function table($table){// 返回当前类实例,方便后面的链式调用return $this;}public function where($where){return $this;}public function find(){// 不需要返回 $this,它最一个最终方法,输出查询结果// 用数组来模拟数据表的查询结果return ['id' => 1, 'name' => '猪老师', 'email' => '498668472@qq.com'];}}$query = new Query;// $query->table('think_user');// $query->where('id', 1);// $query->find();$query->table('think_user')->where('id', 1)->find();// Db::table('think_user')->where('id', 1)->find()// 2. 入口类: 实现请求转发class Db{// 静态方法重载/重定向public static function __callStatic($name, $args){// $query = new Query;// return $query->$name($args);// 回调的方式来执行对象方法return call_user_func_array([new Query, $name], $args);}}$res = Db::table('think_user')->where('id', 1)->find();printf('<pre>%s</pre>', print_r($res, true));
命名空间,解决了全局成员的命名冲突
全局成员:类/接口,常量,函数
function hello(){}const APP = '社区';class Demo1{} interface A{}命令空间类型
// 一个脚本中,可以创建多个空间namespace ns1 {// 空间成员//常量const APP = '商城';}// 子空间要写在父空间的上面,这样才能在父空间里面访问// 空间分级管理: 子空间namespace ns2\ns3 {const APP = '问答';echo APP . '<br>';}namespace ns2 {// 空间成员// 常量const APP = '社区';// 2. 非限定名称: 总是从当前空间开始查询echo APP . '<br>';//直接访问即可echo \ns2\APP . '<br>'; //也可以用这种方式// 在ns2中访问 ns1的APP// 一定要通过全局空间/根空间进行访问// 根空间: \// 1. 完全限定名称: 从根空间开始查询echo \ns1\APP . '<br>';// 在ns2空间, 访问子空间 ns2\ns3中的成员// 3. 限定名称: ns3\APP,因为已经在ns2里面了,所以不需要写ns2echo '<span style="color:red">' . ns3\APP . '</span><br>';}
namespace {function hello(){echo 'hello 大家好';}//访问ns1空间内的APPecho '<span style="color:blue">' . ns1\APP . '</span><br>';//访问ns3里面的APPecho '<span style="color:coral">' . \ns2\ns3\APP . '</span><br>';}
做个类文件自动加载器来加载类
// 类文件自动加载器// 注册一个类的自动加载器spl_autoload_register(function ($class) {// echo $class;// 1. 将命名空间=>映射到一个类文件的绝对路径$path = str_replace('\\', DIRECTORY_SEPARATOR, $class);// 2. 生成类文件路径$file = __DIR__ . DIRECTORY_SEPARATOR . $path . '.php';// 3. 加载这个类文件require $file;});
需要用的时候,使用文件包含加载一下就可以
namespace ns1;//调用类自动加载器文件require __DIR__ . '/autoloader.php';class Demo2{}// new \php\cn\Demo2;echo Demo2::class . '<br>';echo \php\cn\Demo2::class;
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号