博客列表 >0214 PHP闭包与异常

0214 PHP闭包与异常

Admin
Admin原创
2020年02月21日 21:53:141016浏览

0214 PHP闭包与异常

PHP闭包

你可以把闭包当作是匿名函数
闭包的最常用的场景: 就是做为函数/方法的回调参数
也可以将父级中的变量/状态封装进匿名函数

  1. namespace chapter5;
  2. //闭包常用于,作为函数或者方法的回调参数
  3. //示例
  4. $data = ['id'=>1,'name'=>'xiaoyu','pwd'=>'xiaoyu'];
  5. $cc = array_filter($data,function ($key){
  6. return in_array($key,['id','name']);
  7. },ARRAY_FILTER_USE_KEY);
  8. var_dump($cc);
  9. //势力在此处闭包的作用为作为array_filter的回调参数

接下来如何利用闭包与对象或类绑定来访问类成员
在此之前先说一下几个魔术方法

  • __invoke 当类被当成函数使用时所执行
  • __toSring 当类被当成字符串时
  • __callStatic 执行一个不存在的静态方法时
    Closure类
  • 实例方法: bindTo()复制当前闭包对象,绑定指定$this和类作用域
  • 静态方法: bind(): 复制一个闭包, 绑定指定$this和类作用域
    1. namespace chapter5;
    2. $closure = function (string $data, string $method) : string{
    3. return $data . ':' .$method;
    4. };
    5. echo get_class($closure);
    6. echo '<hr>';
    7. class demo
    8. {
    9. //当对象被当成函数使用时
    10. public function __invoke()
    11. {
    12. return '你把我当成函数用了!';
    13. }
    14. //当对象被当成字符串直接使用时
    15. public function __toString()
    16. {
    17. return '你把我当成字符串了';
    18. }
    19. }
    20. $test = new demo;
    21. echo $test;
    22. echo '<br>';
    23. echo $test();

    为了方便起见我们会用到toString比较多
    1. namespace chapter5;
    2. use Closure;
    3. class info
    4. {
    5. public $name = '我';
    6. public $school = '家';
    7. public function __toString()
    8. {
    9. return $this->name . '在' . $this->school;
    10. }
    11. }
    12. $test = new info;
    13. echo $test;
    14. //创建一个闭包用闭包来提
    15. $bb = function (string $name, string $school) : void{
    16. $this->name = $name;
    17. $this->school = $school;
    18. };
    19. $clouser=$bb->bindTo($test);
    20. $clouser('周小雨','学校');
    21. echo $test;
    22. echo '<hr>';
    23. $bb = function (string $name, string $school) : void{
    24. $this->name = $name;
    25. $this->school = $school;
    26. };
    27. $clouser = Closure::bind($bb,$test);
    28. $clouser('我','上课');
    29. echo $test;
    30. class imp
    31. {
    32. public static $xiaoyu = 'ok';
    33. public static $home = 'zj';
    34. //当访问一个类中不存在的静态方法时自动触发
    35. public static function __callStatic($name, $arguments)
    36. {
    37. return static::$xiaoyu . '在' . static::$home;
    38. }
    39. }
    40. echo imp::xiaoyu();
    41. $bb = function (string $name, string $school) : void{
    42. static::$xiaoyu = $name;
    43. static::$home = $school;
    44. };
    45. echo '<hr>';
    46. $clouser = $bb->bindTo(null,imp::class);
    47. $clouser('我','上课');
    48. echo imp::xiaoyu();
    49. echo '<hr>';
    50. $clouser = Closure::bind($bb,null,imp::class);
    51. $clouser('bind','安排');
    52. echo imp::xiaoyu();

    接下来是异常

    异常这边还是要说几句的,try里面是放执行的代码,而throw是来使用异常的,就是说假设你的代码没有问题throw是不会被执行捕捉异常的,假设你代码出现问题报错,啥的就会执行。catch(你在throw里面new的异常类名 空格一下 对象(随便起个名)catch里面输出对象即可)
    1. namespace chapter5;
    2. use Exception;
    3. //设置一个用户
    4. $users = [
    5. ['id'=>1,'username'=>'test','password'=>'test'],
    6. ];
    7. $username = 'test1';
    8. $password = 'test';
    9. $d = array_filter($users,function ($users) use ($username,$password){
    10. return $users['username'] === $username && $users['password'] === $password;
    11. });
    12. try{
    13. if(count($d) != 1){
    14. echo '登陆成功';
    15. throw new Exception('账号或者密码错误','001');
    16. }
    17. } catch (Exception $e){
    18. echo $e->getMessage().'<br>'.$e->getFile();
    19. }
    自己写一个异常类(整好看点)
    1. namespace chapter5;
    2. use Exception;
    3. $users = [
    4. ['id' => 1, 'username' => 'test', 'password' => 'test'],
    5. ];
    6. $username = 'test1';
    7. $password = 'test';
    8. $d = array_filter($users, function ($users) use ($username, $password) {
    9. return $users['username'] === $username && $users['password'] === $password;
    10. });
    11. class myExecption extends Exception
    12. {
    13. public function __toString(): string
    14. {
    15. return <<< Error
    16. <table border="1" cellspacing="0" cellpadding="5">
    17. <tr bgcolor="wheat">
    18. <th>错误信息</th>
    19. <th>代码</th>
    20. <th>文件</th>
    21. <th>行号</th>
    22. </tr>
    23. <tr>
    24. <td>$this->message</td>
    25. <td>$this->code </td>
    26. <td>$this->file </td>
    27. <td>$this->line</td>
    28. </tr>
    29. <tr>
    30. <td colspan = '4'>请更正报错点</td>
    31. </tr>
    32. </table>
    33. Error;
    34. }
    35. }
    36. try{
    37. if(count($d) === 1) echo '登陆成功';
    38. throw new myExecption('账号或密码错误',001);
    39. } catch (myExecption $e){
    40. echo $e;
    41. }

    附加作业

    闭包访问protect/private成员
    其实很简单,因为其都不允许外部调用,所以我们借助公共函数去调用即可!
    我这边申明一个私有成员$xiaoyu再安排了一个公共函数xd(闭包给这个函数传参)用来更改私有成员$xiaoyu的值
    1. namespace chapter5;
    2. class A
    3. {
    4. private $xiaoyu;
    5. protected function test() : string
    6. {
    7. return $this->xiaoyu;
    8. }
    9. public function xd($class) : string
    10. {
    11. return $this->xiaoyu = $class;
    12. }
    13. public function dy()
    14. {
    15. return $this->test();
    16. }
    17. }
    18. $tt = new A;
    19. $bb = function ($name) : void {
    20. $this->xd($name);
    21. };
    22. $bbd = $bb->bindTo($tt);
    23. $bbd('小雨');
    24. echo $tt->dy();
    好了那这就是这次作业,拉下了好多一点点补上去!发现学到的内容都很实用!
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议