다음 튜토리얼 칼럼인 laravel에서는 Laravel 예외에 대한 솔루션을 소개할 예정입니다. 도움이 필요한 친구들에게 도움이 되길 바랍니다!
사용자 등록에 매개변수가 필요한 시나리오를 가정합니다
매개변수 이름 | 설명 | type | 필요 여부 |
---|---|---|---|
mobile | 사용자 휴대폰 번호 | 문자열 | 필수 |
sms_code | SMS 인증 코드 | 정수 | 필수 |
password | 사용자 비밀번호 | string | 사용자 비밀번호 |
re_password | 사용자 비밀번호 반복 | 정수 | 사용자 반복 비밀번호 |
以下列举会出现的问题情况
现在已知会复用的场景有 会在别的业务内有相同错误的类型 (具体业务不做赘述,业务不同,理解不同)
这里假定大家都不是大佬 业务有藕合 处理方案如下 (以下代码仅在checkSms下进行)
//第一次写文档 不会用markdown 你也可以用 response出去 这样浅显易懂exit(json_encode(['code'=>-1,'msg'=>'短信验证码错误']));
if (false === checkSms($mobile,$code,$type)){ exit(json_encode(['code'=>-1,'msg'=>'短信验证码错误']));}
已知你有三套业务 且每套业务包含N个子模块 (别杠微服务/跨语言等,杠就是你赢 /狗头)
Fatal error: Allowed memory size of 1073741824 bytes exhausted (tried to allocate 9216 bytes) in your problem
与其到处去找不如直接告诉我是怎么回事,但是你又很难保证大家写的错误信息内容都是一样的
首先我们明白一个道理 你写代码最害怕的是什么 是bug吗? 不是
是这个
你问我错哪了? 我怎么知道!!!!! 我就知道肯定报错了 抛出异常了 ,程序停了啊!!!
ok 那么我们知道了一个道理,当程序抛出异常的时候,项目就会停掉.
同时我们也明白了一件事 叫做:
假定我们有一个业务模块叫做 User 里面包含了一个控制器叫做 AuthController
内部需要完成一个login的行为
<?php namespace App\Http\Controllers\Application\Auth; use App\Http\Controllers\Controller; use App\Http\Requests\Application\Auth\LoginRequest; use Illuminate\Http\JsonResponse; class AuthController extends Controller { // public function index(LoginRequest $loginRequest): JsonResponse { $data = $loginRequest->all(); //todo 验证是否登录成功 //todo 登录成功之后需要从返回里面获取token 和 userInfo //todo 记录日志等行为 //todo 返回前端 return $this->success('登陆成功', compact('token', 'user')); } }
if (!empty(login($username,$password))){ //todo 登录成功 //tonext}
if(1){ if(1){ if(1){ if(1){ //建议这里直接用来测光速到底是多少 ,因为需求是无限长的 //并且你知道到底是什么问题,什么业务返回来的,到底的意思是什么嘛? (突然成为派大星 ) } } } }
我们上面已知程序抛出异常就会停掉,除非你继续catch 然后抛什么出来??????怕不是万能交税
1.我们设计让我们的程序听话,怎么听话,让他犯错自己会停,还会告诉你怎么回事
2.怎么实现,这么做的意义是什么
3.如何实现,这样做有什么别的意义没
4.性能损耗问题
回答问题
1.你是开发,程序是你的 你必须说什么让他听什么
2.此处仅做流程展示,最后会直接贴代码加注释,如果没耐心可以直接翻最后 创建异常应该都ok吧,不ok 就去看文档 你可以停在这了
<?php namespace App\Exceptions; use Exception; class XxxException extends Exception { /** * @Message('短信验证码错误') */ const SMS_CODE_IS_ERROR = '300000000'; /** * @Message('短信验证码类型错误') */ const SMS_CODE_TYPE_IS_ERROR = '300000001'; /** * @Message('短信验证码不存在') */ const SMS_CODE_IS_NOT_EXISTS = '300000002'; } ?>
伪代码
//todo 验证码类型错误throw new XxxException(XxxException::SMS_CODE_IS_ERROR);
程序现在是不是应该停下来了,因为当你exception的时候 下面代码不会执行了
但是新的问题出现了,如果这样抛出异常,前端怎么办???????????
此处小声bb 前端处理不了跟我什么关系啊,我是后台啊,你有问题找前端啊.
那么我们假设一下 如果我们告诉前端的是
{code:'300000000','message:'短信验证码错误'}
是不是就很舒服了,前后端是一家 怎么能闹脾气呢
那么如果 Code统一,请问出问题你在发愁什么? 是你的phpstorm不存在属性追踪吗?
怎么实现???????????????
你问我,我也不到啊 我只能给你这个啊
<?php namespace App\Exceptions;use App\Factory\ParseException; //解释异常的工厂 嫌弃名字长就没加Factory use App\Traits\ResponseTrait; //这个是我自己写的一个简单的trait 也会一并贴上去use Illuminate\Database\Eloquent\ModelNotFoundException;use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;use Illuminate\Http\JsonResponse;use Illuminate\Http\Response;use Illuminate\Support\Str;use Illuminate\Validation\ValidationException;use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;use Throwable;class Handler extends ExceptionHandler{ use ResponseTrait; /** * A list of the exception types that are not reported. * * @var array */ protected $dontReport = [ // ]; /** * A list of the inputs that are never flashed for validation exceptions. * * @var array */ protected $dontFlash = [ 'current_password', 'password', 'password_confirmation', ]; /** * Register the exception handling callbacks for the application. * * @return void */ public function register() { $this->reportable(function (Throwable $e) { // }); } public function render($request, $e) { //数据库没查到数据或者数据是softdelete if ($e instanceof ModelNotFoundException) { return $this->error('500', '数据不存在或已删除'); } //非允许请求方式 if ($e instanceof MethodNotAllowedHttpException) { return $this->error('422', '请求方式错误'); } //验证失败 if ($e instanceof ValidationException) { return $this->error(412, current(current($e->errors()))); } //这里是为了兼容其他的一些错误 if (Str::length($e->getMessage()) > 1 && Str::length($e->getCode()) > 1) { return $this->error($e->getCode(), $e->getMessage()); } //处理我们自己的错误 $result = ParseException::parseException($e); //这里判断的原因很简单 因为可能这个code没有按照规范声明 if (is_array($result)) { return $this->error($result['code'], $result['message']); } // Object Not Found 你懂我意思吧? if ($e instanceof NotFoundHttpException) { return $this->error('404', '页面路径不存在'); } //这里可以根据自己是否需要做兜底而决定是否兜底 }}
<?php namespace App\Factory;use Illuminate\Support\Facades\Log;class ParseException{ public static function parseException(\Throwable $exception) { //注解 不懂得话建议直接看文档->反射 ,我讲不明白这个东西 $annotation = new \ReflectionClass($exception); //翻转 成code->constant $values = array_flip($annotation->getConstants()); if (empty($values)) { return false; } //拿到对应的constant $constant = $values[$exception->getMessage()]; //constant反射 $annotation_text = new \ReflectionClassConstant($exception, $constant); //获取属性注释内容 $comment = $annotation_text->getDocComment(); try { //正则大法好 建议留意此处 preg_match("/Message\(\'(.*?)\'\)(\\r\\n|\\r|\\n)/U", $comment, $result); } catch (\Throwable $e) { return false; } if (false === isset($result[1])) { return false; } return [ 'code' => $exception->getMessage(), 'message' => $result[1] ]; }}
不要问我要 ResponseTrait 我相信一个简单的 响应实现你是ok的
这样实现的意义就是为了不管谁接手项目前端后端 看到错误信息一目了然,就算某天领导说不要需要告诉用户短信什么错了,就告诉他你短信错了,你只需要去改constant而已!
并且可读性高,ide支持 ,如果你觉得不合适,那我没辙了 ,我尽力了
성능 손실
지금까지 뚜렷한 성능 손실은 발견되지 않았습니다. 주어진 튜닝 계획은 가능하다면 주석이 달린 클래스(주의해야 할 사항)의 속성 목록을 캐시할 수 있다는 것입니다(필요하지 않기 때문입니다). 지금은 거기로 가려면) 이것을 고려하면 laravels가 좋은 방법입니다)
그 외에는 그냥 내 코드를 붙여넣고 직접 사용할 수 있지만 권장하지는 않습니다. 한 번이라고 해서 항상 배부르다는 뜻은 아닙니다. 최소한 좋아하고 포기해서는 안 된다는 점을 이해해 주시길 바랍니다
처음으로 마크다운을 작성했는데, 부족한 부분이 있으면 나가셔도 됩니다. 시간 내에 메시지를 보내주시면 최선을 다해 수정하겠습니다. 명백한 코드 오류가 있는 경우 메시지를 삭제할 수 있도록 알려주세요.
열심히 하는 척하지 마세요. 척은 안할게~!(단어색 어떻게 바꾸나요?)
위 내용은 해결 방법: laravel 반환 값 응답 처리의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!