英文:
Understanding Laravel exception handling catching exceptions in the controller that have been thrown in service layer
问题
尝试使用laravel创建一个API服务器。我看过很多教程,在服务层捕获抛出的异常。然而,在Laravel中,我们有一个选项可以创建一个自定义的错误处理程序,其中包含一个将结果封装为JSON的render函数。
当在ServiceLayer中抛出此异常时,它会自动将响应JSON返回给调用者。在控制器中没有必要捕获相同的错误。但是大多数教程似乎也在控制器中捕获相同的自定义异常。是否有任何原因呢?
我的示例代码:
class CustomerSpecificException extends Exception
{
/**
* Report the exception.
*
* @return bool|null
*/
public function report()
{
}
/**
* Render the exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function render($request)
{
//some more logic to discern the type of exception (but omitted for clarity's sake)
return response()->json([
'error' => true,
'message' => 'Customer already exists',
'message' => $this->getMessage()
], 404);
}
}
现在,这是我的服务层。在示例中,我在自定义异常中处理QueryException,以便在此处返回相关消息。
public function createOrUpdateCustomer(Request $request, $customer_id) : Customer
{
try{
//do something
}
catch(QueryException $e)
{
throw new UniqueConstraintException();
}
}
上述代码已经返回了一个响应,即使我没有在控制器中捕获相同的错误。这是控制器代码。
public function store(Request $request, CustomerService $customerService)
{
return $customerService->createCustomer($request);
}
上述代码运行良好。当我从Postman访问API时,它返回正确的错误。然而,大多数教程坚持在控制器代码周围使用try-catch,即上面的store函数。我的上述代码是否正确,还是我漏掉了什么?
英文:
Trying to create an API server with laravel. I have seen many tutorials that catch the exception thrown in the service layer. However, in Laravel, we have an option to create a custom error handler that has a render function that encapsulates the result as JSON.
When this exception is thrown in the ServiceLayer it automatically returns the response JSON to the caller. There is no need to catch the same error in the controller. But most of the how-tos seem to catch the same custom exception in the controller as well. Is there any reason?
My example code:
class CustomerSpecificException extends Exception
{
/**
* Report the exception.
*
* @return bool|null
*/
public function report()
{
}
/**
* Render the exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function render($request)
{
//some more logic to discern the type of exception (but omitted for clarity's sake)
return response()->json([
'error' => true,
'message' => 'Customer already exists',
'message' => $this->getMessage()
], 404);
}
}
Now, here is my service layer. In the example, I process QueryException within my custom exception to relay back the relevant message here.
public function createOrUpdateCustomer(Request $request, $customer_id) : Customer
{
try{
//do something
}
catch(QueryException $e)
{
throw new UniqueConstraintException();
}
}
The above code already returns a response even without me catching the same error in the controller. Here is the controller code.
public function store(Request $request, CustomerService $customerService)
{
return $customerService->createCustomer($request);
}
The above code works fine. When I hit the API from Postman, it returns the right error. Most of the how-tos, however, insist on a try-catch around the controller code, i.e., the store function above. Is my above code fine, or is there something that I am missing?
答案1
得分: 0
我来试着翻译一下:
首先,我认为从理论上讲,这是一个涉及数据库连接的运行时异常。我相信,如果 Laravel 在控制器函数中没有在抛出异常之前尝试处理它,那么可能会导致一个无效的异常被首先抛出和捕获...就像一个“糟糕,出了点问题”的一般性错误。因此,我认为如果你想在控制器中添加异常处理,你可能会想在控制器的构造函数中进行。这可能不正确,但还要注意的一点是,在异常处理程序中有很多预定的异常路由处理。
此外,在那个 Handler 类中,它继承了框架中的 Handler,其中有一些基于可渲染、可报告、可忽略、报告等的函数。
Illuminate 的 Handler.php
protected $internalDontReport = [
AuthenticationException::class,
AuthorizationException::class,
BackedEnumCaseNotFoundException::class,
HttpException::class,
HttpResponseException::class,
ModelNotFoundException::class,
MultipleRecordsFoundException::class,
RecordsNotFoundException::class,
SuspiciousOperationException::class,
TokenMismatchException::class,
ValidationException::class,
];
我认为在查看了那个文件之后,你很快就会明白在哪里、何时以及如何管理和实现你的异常处理。
英文:
I am going to take a stab at this.
First I think in theory because this is a runtime exception involving a database connection. I believe if laravel does not attempt to handle it prior to it being thrown up the chain in the controller function it will likely result in an ineffective exception being thrown and caught first... like a general whoops something went wrong, type of error. Therefore, I think if you were to add the exception handling in the controller you would likely want to do it in the controller constructor. That may not be correct, However, also a thing to note is in the exception handler there are a lot of predetermined exception routing being done.
Also in that Handler class it extends the Handler from the framework where there are some functions based around renderable, reportable, ignore, report,etc...
Illuminates Handler.php
protected $internalDontReport = [
AuthenticationException::class,
AuthorizationException::class,
BackedEnumCaseNotFoundException::class,
HttpException::class,
HttpResponseException::class,
ModelNotFoundException::class,
MultipleRecordsFoundException::class,
RecordsNotFoundException::class,
SuspiciousOperationException::class,
TokenMismatchException::class,
ValidationException::class,
];
I think after looking through that file you will quickly pick up where, when, and how you would like to manage and implement your exception processing.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论