博客列表 >PHP基础-序列化/反序列化+__sleep()/__wakeup()函数+自定义异常+匿名类

PHP基础-序列化/反序列化+__sleep()/__wakeup()函数+自定义异常+匿名类

岂几岂几
岂几岂几原创
2020年05月06日 18:08:33817浏览

1. 序列化和反序列化,sleep()和wakeup()函数

  • sleep(): 在序列化对象时, 系统会调用sleep()方法, 它返回数组. 可以在__sleep()中确定哪些对象属性返回, 哪些不返回.
  • wakeup(): 在反序列化对象时, 可以调用wakeUp()方法, 设置需要反序列化的字段和对反序列化后的属性值进行控制修改. 还可以调用对象方法执行部分业务逻辑.
  1. interface Itf1
  2. {
  3. const CONST1 = 'const_from_interface';
  4. }
  5. trait Trait1
  6. {
  7. public static $tParam1 = 'static_param_from_trait';
  8. public $tParam2 = 'param_from_trait';
  9. private $tParam3 = 'private_param_from_trait';
  10. }
  11. class Demo1 implements Itf1
  12. {
  13. use Trait1;
  14. private $cParam1 = 'param_in_class';
  15. public $cParam2 = 'public_param';
  16. public static $cParam3 = 'static_param_in_class';
  17. public function func1()
  18. {
  19. echobr(__METHOD__);
  20. }
  21. /* sleep函数指定序列化时, 哪些熟悉被序列化 */
  22. public function __sleep()
  23. {
  24. // 不序列化cParam2属性, 私有属性也可以通过__sleep()函数指定被序列化; 接口或trait中的属性, 常量等同理.
  25. // 但是, 常量和静态变量的值并不被序列化, 所以CONST1, cParam3, tParam1在序列化字符串中的值是N(即NULL).
  26. return ['CONST1', 'tParam1', 'tParam2', 'tParam3', 'cParam1', 'cParam3'];
  27. }
  28. /* wakeup函数在反序列化时, 可以对对象属性赋值, 也可以调用对象方法 */
  29. public function __wakeup()
  30. {
  31. // 无法在wakeup中给静态属性赋值.
  32. // self::$tParam1 = 'value_set_by_wakeup';
  33. // self::$cParam3 = 'value_set_by_wakeup';
  34. // 普通属性(public/protected/private均没有问题)
  35. $this->cParam2 = '1234';
  36. }
  37. }
  38. // 执行序列化
  39. $objStr = serialize(new Demo1);
  40. echobr($objStr);
  41. /* result: O:5:"Demo1":6:{s:6:"CONST1";N;s:7:"tParam1";N;s:7:"tParam2";s:16:"param_from_trait";s:14:"Demo1tParam3";s:24:"private_param_from_trait";s:14:"Demo1cParam1";s:14:"param_in_class";s:7:"cParam3";N;} */
  42. echobr();
  43. // 执行反序列化
  44. $obj = unserialize($objStr);
  45. dumpbr($obj);
  46. /* result: object(Demo1)#1 (7) { ["cParam1":"Demo1":private]=> string(14) "param_in_class" ["cParam2"]=> string(4) "1234" ["tParam2"]=> string(16) "param_from_trait" ["tParam3":"Demo1":private]=> string(24) "private_param_from_trait" ["CONST1"]=> NULL ["tParam1"]=> NULL ["cParam3"]=> NULL } */

2. 登录认证-自定义异常

  1. /* 自定义登录异常类 */
  2. class LoginException extends Exception
  3. {
  4. public function __construct($code, $message)
  5. {
  6. $this->code = $code;
  7. $this->message = $message;
  8. }
  9. public function __toString()
  10. {
  11. return "异常编码: {$this->code}, 异常信息: {$this->message}, 异常文件: {$this->file}, 异常行号: {$this->line}";
  12. }
  13. }
  14. class Login
  15. {
  16. private $username;
  17. private $password;
  18. public function __construct()
  19. {
  20. // 模拟有效的用户和密码分别是admin和123456
  21. $this->username = 'admin';
  22. $this->password = md5('123456');
  23. }
  24. /* 登录验证 */
  25. public function loginCheck($username, $password)
  26. {
  27. try {
  28. if (empty($username)) {
  29. throw new LoginException('1', '用户名不能为空');
  30. }
  31. if (empty($password)) {
  32. throw new LoginException('2', '密码不能为空');
  33. }
  34. if ($username != $this->username) {
  35. throw new LoginException('3', '无效的用户名');
  36. }
  37. if (md5($password) !== $this->password) {
  38. throw new LoginException('4', '密码不正确');
  39. }
  40. echobr('登录成功');
  41. return true;
  42. } catch (LoginException $le) {
  43. echobr('登录失败');
  44. echobr($le);
  45. return false;
  46. }
  47. }
  48. }
  49. // 客户端调用
  50. $login = new Login();
  51. $username = null;
  52. $password = null;
  53. // 验证1
  54. $login->loginCheck($username, $password);
  55. /* result:
  56. 登录失败
  57. 异常编码: 1, 异常信息: 用户名不能为空, 异常文件: D:\phpstudy_pro\WWW\php11\PHP\0504\homework.php, 异常行号: 95
  58. */
  59. $username = 'zhangsan';
  60. // 验证2
  61. $login->loginCheck($username, $password);
  62. /* result:
  63. 异常编码: 2, 异常信息: 密码不能为空, 异常文件: D:\phpstudy_pro\WWW\php11\PHP\0504\homework.php, 异常行号: 98
  64. */
  65. $password = '111111';
  66. // 验证3
  67. $login->loginCheck($username, $password);
  68. /* result:
  69. 登录失败
  70. 异常编码: 3, 异常信息: 无效的用户名, 异常文件: D:\phpstudy_pro\WWW\php11\PHP\0504\homework.php, 异常行号: 101
  71. */
  72. $username = 'admin';
  73. // 验证4
  74. $login->loginCheck($username, $password);
  75. /* result:
  76. 登录失败
  77. 异常编码: 4, 异常信息: 密码不正确, 异常文件: D:\phpstudy_pro\WWW\php11\PHP\0504\homework.php, 异常行号: 104
  78. */
  79. $password = '123456';
  80. //验证5
  81. if ($login->loginCheck($username, $password)) {
  82. echobr('跳转到首页...');
  83. }
  84. /* result:
  85. 登录成功
  86. 跳转到首页...
  87. */

4. 匿名类的使用

4.1 匿名类使用场景1: 实现接口部分方法, 且仅用在当前项目中

  1. interface ICalc
  2. {
  3. public function add($num1, $num2, ...$num3);
  4. public function minus($num1, $num2);
  5. public function multiply($num1, $num2, ...$num3);
  6. public function division($num1, $num2);
  7. }
  8. class Salary
  9. {
  10. public $name = '';
  11. // 基本工资
  12. private $basePay = 0;
  13. // 月绩效
  14. private $projectBonus = 0;
  15. // 其他补助
  16. private $otherPay = 0;
  17. public function __construct($name, $basePay = 0, $projectBonus =0, $otherPay = 0)
  18. {
  19. $this->name = $name;
  20. $this->basePay = $basePay;
  21. $this->projectBonus = $projectBonus;
  22. $this->otherPay = $otherPay;
  23. }
  24. public function getSalary() {
  25. return (new class() implements ICalc {
  26. public function add($num1, $num2, ...$num3) {
  27. $res = $num1 + $num2;
  28. if(!empty($num3) && count($num3) > 0) {
  29. foreach($num3 as $num) {
  30. $res += $num;
  31. }
  32. }
  33. return $res;
  34. }
  35. public function minus($num1, $num2){}
  36. public function multiply($num1, $num2, ...$num3){}
  37. public function division($num1, $num2){}
  38. })->add($this->basePay, $this->projectBonus, $this->otherPay);
  39. }
  40. }
  41. $salary = new Salary('张三', 3000, 8000, 2000);
  42. echobr("{$salary->name}的月薪为:{$salary->getSalary()}");
  43. /* result: 张三的月薪为:13000 */

4.2 匿名类应用场景2:用在函数/方法的参数中

  1. function getSalary(object $tool, $basePay, $projectBonus, $otherPay) {
  2. return $tool->getSalary($basePay, $projectBonus, $otherPay);
  3. }
  4. $salary = getSalary((new class() {
  5. public function getSalary($basePay, $projectBonus, $otherPay) {
  6. return $basePay + $projectBonus + $otherPay;
  7. }
  8. }), 3000, 8000, 2000);
  9. echobr("工资为:{$salary}");
  10. /* result: 工资为:13000 */

5. 学习心得

  • 序列化和反序列化,做作业的时候同时试了一下,静态成员,常量成员是不能被序列化的,哪怕在__sleep()方法中把这些特殊成员也返回,序列化出来的字符串中,相应的值也是N(null);反序列化时也不能在__wakeup()中给静态成员和常量设置值。没有预习,可能文档中有说到,但现在踩坑了体会更深一些。
  • 自定义异常,暂时还没发现其使用场景,作业中的实例,登录异常,其实可以用流程控制的方式,给前端返回json或序列化的信息,也能达到同样的目的。
  • 匿名类,也遇到坑:在匿名类中设置的属性,并不能成功返回,最终只能取到NULL值。我猜测可能是因为匿名类执行完后,垃圾回收机制把匿名类对象回收了,这样对象里面的属性也就没有了。且暂时没有感受到使用匿名类带来的便利,示例感觉不用匿名类也可以,而且代码还更方便阅读。可能在实战中才能体会到其便利吧。
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议