博客列表 >PHP 18 序列化、__sleep__wakeup、匿名类(0728tue)

PHP 18 序列化、__sleep__wakeup、匿名类(0728tue)

老黑
老黑原创
2020年07月30日 08:09:11743浏览

主要内容:

  1. 序列化与反序列化:serialize(),unserialize()
  2. sleep(序列化限制)、wakeup(类反序列化时的连带操作) - 序列化类似睡着(哪些东东可以睡着),反序列化类似醒酒(醒酒的时候干点啥)
  3. 异常类:__toString()异常处理
  4. 匿名类(寻不到反击的对象:防攻击?老周的娃娃都笑了)

1. 序列化与反序列化:serialize(),unserialize()

  1. <?php
  2. // 序列化,序列化数据的目的是将数据进行传输或保存
  3. echo serialize('peter zhu'), '<br>';
  4. echo serialize([10, false, null]);
  5. echo '<hr>';
  6. class User
  7. {
  8. public $name = '汽车';
  9. public $price ='180000';
  10. public $num = 2;
  11. // 当外部序列化类实例的时候,自动调用它,用来隐藏一些属性
  12. // sleep内部的会包括,其他的会省略掉
  13. // serialize($this)被调用的时候自动执行它
  14. public function __sleep():array
  15. {
  16. return ['name', 'price'];
  17. }
  18. // 外部反序列化这个对象的时候,会被自动调用。例如这个里面对变量重新赋值。
  19. public function __wakeup()
  20. {
  21. // 在唤醒一个对象的时候,可以同步执行一些操作
  22. $this->price = 5000;
  23. }
  24. }
  25. $user = new User();
  26. // 序列化数据的目的是将数据进行传输或保存
  27. file_put_contents('obj.txt', serialize($user));
  28. $str = file_get_contents('obj.txt');
  29. // echo gettype($str);
  30. // 还可以反序列化,并将实例重新得到
  31. // string ===> object
  32. $obj = unserialize($str);
  33. // echo gettype($obj);
  34. echo $obj->name . ': 价格: ' . $obj->price . ', 数量 : ' , $obj->num;

2. sleep(序列化限制)、wakeup(类实例化连带操作)

  1. <?php
  2. // __sleep()和__wakeup()实战
  3. // 自定义数据库连接类
  4. // 功能:
  5. // 1. 类实例化时,自动连接数据库, 一定会生成一个:连接对象
  6. // 2. 将这个连接对象序列化,获取到连接参数
  7. // 3. 反序列化, 自动重新连接数据库
  8. // 连接类
  9. class Connection
  10. {
  11. // 数据库连接参数的属性
  12. private $params = [];
  13. // 连接对象
  14. private $link;
  15. // 构造方法
  16. public function __construct($dsn, $username, $password)
  17. {
  18. // 1. 连接参数的初始化
  19. $this->params['dsn'] = $dsn;
  20. $this->params['username'] = $username;
  21. $this->params['password'] = $password;
  22. // 2. 连接数据库
  23. $this->connect();
  24. }
  25. // 连接数据库
  26. private function connect()
  27. {
  28. $this->link = new PDO(...array_values($this->params));
  29. } // array_values为取出其中的值。
  30. // 将这个连接对象序列化,获取到连接参数
  31. public function __sleep(): array
  32. {
  33. return ['params'];
  34. }
  35. // 反序列化, 自动重新连接数据库
  36. public function __wakeup()
  37. {
  38. $this->connect();
  39. }
  40. // 测试,看是否连接成功,可以取出数
  41. public function select($sql)
  42. {
  43. return $this->link->query($sql)->fetchAll(PDO::FETCH_ASSOC);
  44. }
  45. }
  46. $dsn = 'mysql:host=localhost;dbname=phpedu';
  47. $username = 'root';
  48. $password = 'root';
  49. $db = new Connection($dsn, $username, $password);
  50. // o:构造函数的部分直接传参。对应几个就几个。
  51. $str = serialize($db);
  52. // echo $str;
  53. // print_r($db->select('select * from users limit 3'));
  54. // 3. 反序列化, 自动重新连接数据库(用了类中的__wakeup)
  55. $link = unserialize($str);
  56. // print_r($link);
  57. print_r($db->select('select * from users limit 2'));

3. 异常类:__toString()异常处理

  1. <?php
  2. // toString()
  3. // class User
  4. // {
  5. // public function __toString()
  6. // {
  7. // return 'Hello ';
  8. // }
  9. // }
  10. // 将这个类的实例,当成字符串打印
  11. // $user = new User();
  12. // echo $user;
  13. // __toString()应用场景案例: 异常处理
  14. // php异常处理类: Exception, 这个类除构造方法外, 外部仅有__toString()可访问
  15. // php异常与其它语言(如Java)不同, 大多数异常没有提供预置异常并且不会自动抛出,需要用户手工配置
  16. // Excepction异常类中, 只有属性和__toString()可以在子类中使用
  17. // Exception与try{...}catch (Exception $e) {...}结构配合使用
  18. // - 与错误机制对比, 异常处理机制主动抛出
  19. // - 异常并不一定是发生了错误, 所以异常应用范围更广
  20. // - 使用框架开发,异常与错误机制已经封装好了,简单的配置就可以直接用了
  21. // ## 2. Exception
  22. // ```php
  23. // Exception {
  24. // /* 属性 */
  25. // protected string $message ;
  26. // protected int $code ;
  27. // protected string $file ;
  28. // protected int $line ;
  29. // /* 方法 */
  30. // public __construct ([ string $message = "" [, int $code = 0 [, Throwable $previous = NULL ]]] )
  31. // final public getMessage ( void ) : string
  32. // final public getPrevious ( void ) : Throwable
  33. // final public getCode ( void ) : int
  34. // final public getFile ( void ) : string
  35. // final public getLine ( void ) : int
  36. // final public getTrace ( void ) : array
  37. // final public getTraceAsString ( void ) : string
  38. // public __toString ( void ) : string
  39. // final private __clone ( void ) : void
  40. // }
  41. //
  42. // try {
  43. // $db = new PDO('mysql:host=localhost;dbname=phpedu', 'root', 'root1');
  44. // // 出错后强制且自动的抛出预置的异常信息
  45. // } catch (Exception $exception) {
  46. // // echo $exception->getMessage(), '<br>';
  47. // echo $exception;
  48. // }
  49. // 自定义自己的数据库异常类
  50. class DbException extends EXception
  51. {
  52. public function __toString()
  53. {
  54. return <<< DBE
  55. <table>
  56. <tr>
  57. <td>编号</td>
  58. <td>信息</td>
  59. <td>文件</td>
  60. <td>行号</td>
  61. </tr>
  62. <tr>
  63. <td>$this->code</td>
  64. <td>$this->message</td>
  65. <td>$this->file</td>
  66. <td>$this->line</td>
  67. </tr>
  68. </table>
  69. <style>
  70. table {border-collapse: collapse;border:1px solid black;text-align: center;}
  71. td {border:1px solid black;padding: 5px;}
  72. tr:first-of-type {background-color:#eee;}
  73. tr:last-of-type td {color: coral;}
  74. </style>
  75. DBE;
  76. }
  77. }
  78. try {
  79. $db = new PDO('mysql:host=localhost;dbname=phpedu', 'root', 'root');
  80. // 自定义异常类需要手工抛出
  81. // 这里需要一个判断,如果连接失败应该实例化自定义的异常类并抛出它
  82. throw new DbException('连接失败', 110);
  83. } catch (DbException $dbException) {
  84. echo $dbException;
  85. }

4. 匿名类(寻不到反击的对象:防攻击?)

  1. <?php
  2. // 匿名类
  3. class Demo
  4. {
  5. public function hello($name)
  6. {
  7. return 'Hello '. $name;
  8. }
  9. }
  10. // 1. 传统语法
  11. $demo = new Demo();
  12. echo $demo->hello('Peter Zhu'), '<hr>';
  13. // 2.如果这个类实例(对象)只用一次, 将类的实例化与成员访问二合一
  14. echo (new Demo())->hello('Peter Zhu'), '<hr>';
  15. // 3. 如果这个类,我们也只用一次,将类的声明,类的实例化,类成员访问三合一
  16. // 此时,可以通过匿名类来实现。其实也就是class中的大括号中的内容拿过来。
  17. echo (new class {
  18. public function hello($name)
  19. {
  20. return 'Hello '. $name;
  21. }
  22. })->hello('Peter Zhu'), '<hr>';

5. 匿名类的mysqli、PDO应用

  1. <?php
  2. // 匿名类的应用场景
  3. // 1. 实现接口的部分功能
  4. interface iDb
  5. {
  6. public function __construct(...$params);
  7. }
  8. // 当前这个接口中的数据库连接操作应该支持PDO,mysqli
  9. // Mysqli实现
  10. // 命名类: 有类名称的类
  11. // 匿名类: 没有名称的类
  12. // 函数也有对应的做法。
  13. // 命名函数: 有名称的函数
  14. // function demo(){
  15. // //....
  16. // }
  17. // 匿名函数: 没有名称的函数
  18. // $demo = function (){
  19. // //....
  20. // };
  21. class My_mysqli implements iDb
  22. {
  23. private $db = null;
  24. public function __construct(...$params)
  25. {
  26. $this->db = new mysqli($params[0], $params[1],$params[2],$params[3]);
  27. }
  28. public function select()
  29. {
  30. return $this->db->query('select * from users limit 2')->fetch_all(MYSQLI_ASSOC);
  31. }
  32. }
  33. $mysqli = new My_mysqli('localhost', 'root', 'root', 'phpedu');
  34. // print_r($mysqli->select());
  35. echo '<hr>';
  36. // 使用匿名类改造
  37. $users = (new class ('localhost', 'root', 'root', 'phpedu') implements iDb {
  38. private $db = null;
  39. public function __construct(...$params)
  40. {
  41. $this->db = new mysqli($params[0], $params[1],$params[2],$params[3]);
  42. }
  43. public function select()
  44. {
  45. return $this->db->query('select * from users limit 2')->fetch_all(MYSQLI_ASSOC);
  46. }
  47. })->select();
  48. // print_r($users);
  49. echo '<hr>';
  50. // pdo实现
  51. class My_pdo implements iDb
  52. {
  53. private $db = null;
  54. public function __construct(...$params)
  55. {
  56. $this->db = new PDO($params[0], $params[1],$params[2]);
  57. }
  58. public function select()
  59. {
  60. return $this->db->query('select * from users limit 3')->fetchAll(PDO::FETCH_ASSOC);
  61. }
  62. }
  63. $mypdo = new My_pdo('mysql:host=localhost;dbname=phpedu', 'root', 'root');
  64. print_r($mypdo->select());
  65. // 匿名类改造pdo实现的接口
  66. $users = (new class ('mysql:host=localhost;dbname=phpedu', 'root', 'root') implements iDb {
  67. private $db = null;
  68. public function __construct(...$params)
  69. {
  70. $this->db = new PDO($params[0], $params[1],$params[2]);
  71. }
  72. public function select()
  73. {
  74. return $this->db->query('select * from users limit 3')->fetchAll(PDO::FETCH_ASSOC);
  75. }
  76. })->select();
  77. echo '------------------------------------------<br>';
  78. print_r($users);

6. 实战

  • sleep、wakeup
  1. <?php
  2. /*
  3. 0728作业
  4. 1. 自定义实例演示:__sleep(), wakeup()实战案例
  5. 2. 将课堂上的匿名类实战,加上自己理解重写,添加一个新增方法, 更新方法, 删除方法,
  6. 完善这个匿名操作类, mysqli, pdo任选一个完成即可
  7. */
  8. class Human
  9. {
  10. var $name;
  11. var $height;
  12. var $age;
  13. var $birthyear;
  14. public function __construct($n, $h, $a, $b)
  15. {
  16. $this->name = $n;
  17. $this->height = $h;
  18. $this->age = $a;
  19. $this->birthyear = $b;
  20. }
  21. public function __sleep()
  22. {
  23. return ['name', 'height', 'age', 'birthyear'];
  24. }//因为后面要计算,所以birthyear也需要加入
  25. public function __wakeup()
  26. {
  27. $this->age = 2020 - $this->birthyear;
  28. } // wakeup只在反序列化时有效
  29. }
  30. $person = new Human('张三','175cm','',1990);
  31. $str1 = serialize($person);
  32. echo $str1;
  33. echo '<br><hr>';
  34. //var_dump($person);
  35. //echo '<br><hr>';
  36. file_put_contents('person.txt', serialize($person));
  37. $str = file_get_contents('person.txt');
  38. echo gettype($str);
  39. echo '<br><hr>';
  40. $obj = unserialize($str1);
  41. var_dump($obj);

结果如图:

" class="reference-link">

  • 用匿名类操作数据库
  1. <?php
  2. /*
  3. 0728作业
  4. 1. 自定义实例演示:__sleep(), wakeup()实战案例
  5. 2. 将课堂上的匿名类实战,加上自己理解重写,添加一个新增方法, 更新方法, 删除方法,
  6. 完善这个匿名操作类, mysqli, pdo任选一个完成即可
  7. */
  8. interface iData
  9. {
  10. public function __construct(...$params);
  11. }
  12. $items = (new class('mysql:host=localhost;dbname=liangtest',
  13. 'liang','123456') implements iData {
  14. private $db = null;
  15. public function __construct(...$params)
  16. {
  17. $this->db = new PDO($params[0],$params[1],$params[2]);
  18. }
  19. public function select()
  20. {
  21. return $this->db->query('SELECT * FROM my_list LIMIT 2')
  22. ->fetchAll(PDO::FETCH_ASSOC);
  23. }
  24. })->select();
  25. echo '这是select的匿名实现:<br>';
  26. print_r($items);
  27. echo '<hr>';
  28. $items = (new class('mysql:host=localhost;dbname=liangtest',
  29. 'liang','123456') implements iData {
  30. private $db = null;
  31. public function __construct(...$params)
  32. {
  33. $this->db = new PDO($params[0],$params[1],$params[2]);
  34. }
  35. public function delete()
  36. {
  37. return $this->db->query('DELETE FROM my_list WHERE ID = 1')->rowCount();
  38. }
  39. })->delete();
  40. echo '这是delete的匿名实现:<br>';
  41. print_r($items);
  42. echo '<hr>';
  43. $items = (new class('mysql:host=localhost;dbname=liangtest',
  44. 'liang','123456') implements iData {
  45. private $db = null;
  46. public function __construct(...$params)
  47. {
  48. $this->db = new PDO($params[0],$params[1],$params[2]);
  49. }
  50. public function update()
  51. {
  52. return $this->db->query('UPDATE my_list SET ID = 1 WHERE ID = 2')->rowCount();
  53. }
  54. })->update();
  55. echo '这是update的匿名实现:<br>';
  56. print_r($items);
  57. echo '<hr>';
  58. $items = (new class('mysql:host=localhost;dbname=liangtest',
  59. 'liang','123456') implements iData {
  60. private $db = null;
  61. public function __construct(...$params)
  62. {
  63. $this->db = new PDO($params[0],$params[1],$params[2]);
  64. }
  65. public function insert()
  66. {
  67. return $this->db->query("INSERT INTO my_list (id, name, age, phone)
  68. VALUES ('999','小李飞刀','45','12365')")->rowCount();
  69. }
  70. })->insert();
  71. echo '这是insert的匿名实现:<br>';
  72. print_r($items);
  73. echo '<hr>';

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议