0214 PHP闭包与异常
PHP闭包
你可以把闭包当作是匿名函数
闭包的最常用的场景: 就是做为函数/方法的回调参数
也可以将父级中的变量/状态封装进匿名函数
namespace chapter5;
//闭包常用于,作为函数或者方法的回调参数
//示例
$data = ['id'=>1,'name'=>'xiaoyu','pwd'=>'xiaoyu'];
$cc = array_filter($data,function ($key){
return in_array($key,['id','name']);
},ARRAY_FILTER_USE_KEY);
var_dump($cc);
//势力在此处闭包的作用为作为array_filter的回调参数
接下来如何利用闭包与对象或类绑定来访问类成员
在此之前先说一下几个魔术方法
- __invoke 当类被当成函数使用时所执行
- __toSring 当类被当成字符串时
- __callStatic 执行一个不存在的静态方法时
Closure类 - 实例方法:
bindTo()
复制当前闭包对象,绑定指定$this和类作用域 - 静态方法:
bind()
: 复制一个闭包, 绑定指定$this和类作用域namespace chapter5;
$closure = function (string $data, string $method) : string{
return $data . ':' .$method;
};
echo get_class($closure);
echo '<hr>';
class demo
{
//当对象被当成函数使用时
public function __invoke()
{
return '你把我当成函数用了!';
}
//当对象被当成字符串直接使用时
public function __toString()
{
return '你把我当成字符串了';
}
}
$test = new demo;
echo $test;
echo '<br>';
echo $test();
为了方便起见我们会用到toString比较多namespace chapter5;
use Closure;
class info
{
public $name = '我';
public $school = '家';
public function __toString()
{
return $this->name . '在' . $this->school;
}
}
$test = new info;
echo $test;
//创建一个闭包用闭包来提
$bb = function (string $name, string $school) : void{
$this->name = $name;
$this->school = $school;
};
$clouser=$bb->bindTo($test);
$clouser('周小雨','学校');
echo $test;
echo '<hr>';
$bb = function (string $name, string $school) : void{
$this->name = $name;
$this->school = $school;
};
$clouser = Closure::bind($bb,$test);
$clouser('我','上课');
echo $test;
class imp
{
public static $xiaoyu = 'ok';
public static $home = 'zj';
//当访问一个类中不存在的静态方法时自动触发
public static function __callStatic($name, $arguments)
{
return static::$xiaoyu . '在' . static::$home;
}
}
echo imp::xiaoyu();
$bb = function (string $name, string $school) : void{
static::$xiaoyu = $name;
static::$home = $school;
};
echo '<hr>';
$clouser = $bb->bindTo(null,imp::class);
$clouser('我','上课');
echo imp::xiaoyu();
echo '<hr>';
$clouser = Closure::bind($bb,null,imp::class);
$clouser('bind','安排');
echo imp::xiaoyu();
接下来是异常
异常这边还是要说几句的,try里面是放执行的代码,而throw是来使用异常的,就是说假设你的代码没有问题throw是不会被执行捕捉异常的,假设你代码出现问题报错,啥的就会执行。catch(你在throw里面new的异常类名 空格一下 对象(随便起个名)catch里面输出对象即可)
自己写一个异常类(整好看点)namespace chapter5;
use Exception;
//设置一个用户
$users = [
['id'=>1,'username'=>'test','password'=>'test'],
];
$username = 'test1';
$password = 'test';
$d = array_filter($users,function ($users) use ($username,$password){
return $users['username'] === $username && $users['password'] === $password;
});
try{
if(count($d) != 1){
echo '登陆成功';
throw new Exception('账号或者密码错误','001');
}
} catch (Exception $e){
echo $e->getMessage().'<br>'.$e->getFile();
}
namespace chapter5;
use Exception;
$users = [
['id' => 1, 'username' => 'test', 'password' => 'test'],
];
$username = 'test1';
$password = 'test';
$d = array_filter($users, function ($users) use ($username, $password) {
return $users['username'] === $username && $users['password'] === $password;
});
class myExecption extends Exception
{
public function __toString(): string
{
return <<< Error
<table border="1" cellspacing="0" cellpadding="5">
<tr bgcolor="wheat">
<th>错误信息</th>
<th>代码</th>
<th>文件</th>
<th>行号</th>
</tr>
<tr>
<td>$this->message</td>
<td>$this->code </td>
<td>$this->file </td>
<td>$this->line</td>
</tr>
<tr>
<td colspan = '4'>请更正报错点</td>
</tr>
</table>
Error;
}
}
try{
if(count($d) === 1) echo '登陆成功';
throw new myExecption('账号或密码错误',001);
} catch (myExecption $e){
echo $e;
}
附加作业
闭包访问protect/private成员
其实很简单,因为其都不允许外部调用,所以我们借助公共函数去调用即可!
我这边申明一个私有成员$xiaoyu
再安排了一个公共函数xd(闭包给这个函数传参)用来更改私有成员$xiaoyu
的值
好了那这就是这次作业,拉下了好多一点点补上去!发现学到的内容都很实用!namespace chapter5;
class A
{
private $xiaoyu;
protected function test() : string
{
return $this->xiaoyu;
}
public function xd($class) : string
{
return $this->xiaoyu = $class;
}
public function dy()
{
return $this->test();
}
}
$tt = new A;
$bb = function ($name) : void {
$this->xd($name);
};
$bbd = $bb->bindTo($tt);
$bbd('小雨');
echo $tt->dy();