@
jqh 这是一个例子恰好演示了其糟糕性。
单是返回就有四种可能
return $this->error($vaptcha->getError());
return $this->validationErrorsResponse($validator);
return $this->sendLoginResponse($request);
return $this->validationErrorsResponse([$this->username() => $this->getFailedLoginMessage(),]);
而且注意到的是,按常理,最后一个才是正常返回。取反放最后就是。
但是这样还没完。
validationErrorsResponse 接受的参数又是 Validator ,又是 array 。还好 php 是弱类型。
可是 $this->getFailedLoginMessage() 又从哪里来? 是否前面的调用会影响状态。
$this->guard()->attempt($credentials, $remember)
这个 guard() 也是怎么冒出来的,为什么要和控制器耦合,这个 attepm 词也很少见。
为什么不是 this->attempt($credentials, $remember)
下面是我重构的结果。
```
class MyController
{
public function postLogin(Request $request)
{
// 输入处理,放前面,不必节省性能。
$remember = (bool) $request->input('remember', false);
$credentials = $request->only([$key_username, 'password']);
//这也算输入吧
$key_username= $this->username();
//验证码服务
$error = VaptchaService::make()->validate();
if ($error) {
// 验证不通过
return $this->error($error);
}
//兼容,如果 service 有方式获得这个 $guard,则不需要输入。
$guard = $this->guard();
//登录服务
$error = LoginService::make()->login($guard,$key_username,$credentials,$remeber);
if($error){
if(is_array($error)){
$error[$key_username] = $this->getFailedLoginMessage();
}
return $this->validationErrorsResponse($error);
}
return $this->sendLoginResponse($request);
}
}
class VaptchaService
{
// 省略 make 静态方法。
public function validate()
{
// 验证验证码是否正确
if (! Vaptcha::make()->validate()) {
return $vaptcha->getError();
}
return null;
}
}
class LoginService
{
// 省略 make 静态方法
public function login($guard,$key_username,$credentials,$remember)
{
// 验证参数
$validator = Validator::make($credentials, [
$key_username => 'required',
'password' => 'required',
]);
if ($validator->fails()) {
return $validator;
}
// 登录验证
$flag=$guard->attempt($credentials, $remember);
if (!$flag) {
return [ $key_username => "something wrong"];
}
return null;
}
}
```
如果使用 DuckPhp 你大概会这么写。
```
class MyController
{
// 登录页面
public function login()
{
C::Show([],'login');
}
//处理 post
public function do_login()
{
// 输入处理,放前面,不必节省性能。
$remember = (bool) C::POST('remember', false);
$credentials = C::SG()->_POST();
$error=null;
try{
//验证码服务
VaptchaService::G()->validate();
//登录服务,返回用户信息。
$info = LoginService::G()->login($credentials,$remeber);
//保存 session 数据
SessionService::G()->setLoginUserInfo($info);
C::Show(get_defined_vars(),'login-done');
}catch(\Throwable $ex){
$error = $ex->getMessage();
C::Show(get_defined_vars(),'login');
}
}
}
```
为什么要调 3 个服务解决问题,而不是一个,
第一个是处理验证码的,和 web 平台有关的特殊服务
第二个是主要业务,测试的时候,可以命令行运行,获得信息,不必通过 web
第三个是 session 系统管理,管控所有 session 系统,也是和 web 平台有关的特殊服务