Blogger Information
Blog 30
fans 0
comment 0
visits 13820
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
属性与方法重载和命名空间与类自动加载器
天宁
Original
452 people have browsed it

重载

  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;
Correcting teacher:PHPzPHPz

Correction status:qualified

Teacher's comments:
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post