博客列表 >属性与方法重载和命名空间与类自动加载器

属性与方法重载和命名空间与类自动加载器

天宁
天宁原创
2022年05月04日 23:27:24464浏览

重载

  1. 属性重载: __get(),__set()
  2. 方法重载: __call(),__callStatic()
查询拦截器
  1. // 查询拦截器
  2. public function __get($name)
  3. {
  4. // $name : 属性名
  5. if (array_key_exists($name, $this->data)) {
  6. return $this->data[$name];
  7. }
  8. return "属性 {$name} 不存在";
  9. }
更新拦截器
  1. // 更新拦截器
  2. public function __set($name, $value)
  3. {
  4. // 1. 有没有这个属性?
  5. if (array_key_exists($name, $this->data)) {
  6. // 2. 这个值是否合法?
  7. if ($name === 'age') {
  8. if ($value >= 18 && $value <= 59) {
  9. $this->data[$name] = $value;
  10. } else {
  11. echo '年龄必须在18-59之间';
  12. }
  13. } else {
  14. // 以上操作仅对age有效,其它属性直接赋值
  15. $this->data[$name] = $value;
  16. }
  17. } else {
  18. echo '禁止动态创建属性';
  19. }
  20. }
方法拦截器
  1. // 方法拦截器
  2. public function __call($name, $args)
  3. {
  4. // $name: 方法名, $args: 传给方法的参数
  5. printf('方法: %s<br>参数:<pre>%s</pre>', $name, print_r($args, true));
  6. }
静态方法拦截器
  1. // 静态方法拦截器
  2. public static function __callStatic($name, $args)
  3. {
  4. // $name: 方法名, $args: 传给方法的参数
  5. printf('方法: %s<br>参数:<pre>%s</pre>', $name, print_r($args, true));
  6. }

方法重载实例

  1. <?php
  2. // 方法重载的小案例
  3. // Db::table('think_user')->where('id', 1)->find();
  4. // 1. 查询类
  5. class Query
  6. {
  7. public function table($table)
  8. {
  9. // 返回当前类实例,方便后面的链式调用
  10. return $this;
  11. }
  12. public function where($where)
  13. {
  14. return $this;
  15. }
  16. public function find()
  17. {
  18. // 不需要返回 $this,它最一个最终方法,输出查询结果
  19. // 用数组来模拟数据表的查询结果
  20. return ['id' => 1, 'name' => '猪老师', 'email' => '498668472@qq.com'];
  21. }
  22. }
  23. $query = new Query;
  24. // $query->table('think_user');
  25. // $query->where('id', 1);
  26. // $query->find();
  27. $query->table('think_user')->where('id', 1)->find();
  28. // Db::table('think_user')->where('id', 1)->find()
  29. // 2. 入口类: 实现请求转发
  30. class Db
  31. {
  32. // 静态方法重载/重定向
  33. public static function __callStatic($name, $args)
  34. {
  35. // $query = new Query;
  36. // return $query->$name($args);
  37. // 回调的方式来执行对象方法
  38. return call_user_func_array([new Query, $name], $args);
  39. }
  40. }
  41. $res = Db::table('think_user')->where('id', 1)->find();
  42. printf('<pre>%s</pre>', print_r($res, true));

命名空间与自动加载器

命名空间,解决了全局成员的命名冲突
全局成员:类/接口,常量,函数

  1. 函数:全局成员,不能重复声明function hello(){}
  2. 常量:全局成员,不能重复声明const APP = '社区';
  3. 类/接口:全局成员,不能重复声明class Demo1{} interface A{}
一个脚本中,可以创建多个空间
  1. 命名空间还可以分级
  2. 命令空间类型

    1. 完全限定名称:根空间开始 ‘\’a\b\APP’ ,“绝对路径”
    2. 非限定名称: 从当前空间开始, ‘APP’ ,“当前路径”
    3. 限定名称:子空间, ‘ns\APP’ , “相对路径”
  1. // 一个脚本中,可以创建多个空间
  2. namespace ns1 {
  3. // 空间成员
  4. //常量
  5. const APP = '商城';
  6. }
  7. // 子空间要写在父空间的上面,这样才能在父空间里面访问
  8. // 空间分级管理: 子空间
  9. namespace ns2\ns3 {
  10. const APP = '问答';
  11. echo APP . '<br>';
  12. }
  13. namespace ns2 {
  14. // 空间成员
  15. // 常量
  16. const APP = '社区';
  17. // 2. 非限定名称: 总是从当前空间开始查询
  18. echo APP . '<br>';//直接访问即可
  19. echo \ns2\APP . '<br>'; //也可以用这种方式
  20. // 在ns2中访问 ns1的APP
  21. // 一定要通过全局空间/根空间进行访问
  22. // 根空间: \
  23. // 1. 完全限定名称: 从根空间开始查询
  24. echo \ns1\APP . '<br>';
  25. // 在ns2空间, 访问子空间 ns2\ns3中的成员
  26. // 3. 限定名称: ns3\APP,因为已经在ns2里面了,所以不需要写ns2
  27. echo '<span style="color:red">' . ns3\APP . '</span><br>';
  28. }
全局空间namespace:匿名的,不要写空间名,用”\“来引用
  1. namespace {
  2. function hello()
  3. {
  4. echo 'hello 大家好';
  5. }
  6. //访问ns1空间内的APP
  7. echo '<span style="color:blue">' . ns1\APP . '</span><br>';
  8. //访问ns3里面的APP
  9. echo '<span style="color:coral">' . \ns2\ns3\APP . '</span><br>';
  10. }
实际工作中的空间定义方式
  1. 一个文件中,只允许声明一个命名空间并只写一个类
  2. 命名空间的命名,应该与成员的路径一致
  3. 类名,必须与类文件名对应
  4. 也可以不写花括号
  5. 做个类文件自动加载器来加载类

    1. // 类文件自动加载器
    2. // 注册一个类的自动加载器
    3. spl_autoload_register(function ($class) {
    4. // echo $class;
    5. // 1. 将命名空间=>映射到一个类文件的绝对路径
    6. $path = str_replace('\\', DIRECTORY_SEPARATOR, $class);
    7. // 2. 生成类文件路径
    8. $file = __DIR__ . DIRECTORY_SEPARATOR . $path . '.php';
    9. // 3. 加载这个类文件
    10. require $file;
    11. });
  6. 需要用的时候,使用文件包含加载一下就可以

    1. namespace ns1;
    2. //调用类自动加载器文件
    3. require __DIR__ . '/autoloader.php';
    4. class Demo2
    5. {
    6. }
    7. // new \php\cn\Demo2;
    8. echo Demo2::class . '<br>';
    9. echo \php\cn\Demo2::class;
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议