Exception Handling
Configuration
config/exception.php
return [
// Configure the exception handling class here
'' => support\exception\Handler::class,
];
In multi-application mode, you can configure an exception handling class for each application individually. Refer to multi-application.
Default Exception Handler Class
Exceptions in webman are handled by the support\exception\Handler
class by default. You can modify the configuration file config/exception.php
to change the default exception handler class. The exception handler class must implement the Webman\Exception\ExceptionHandlerInterface
.
interface ExceptionHandlerInterface
{
/**
* Log the exception
* @param Throwable $e
* @return mixed
*/
public function report(Throwable $e);
/**
* Render the response
* @param Request $request
* @param Throwable $e
* @return Response
*/
public function render(Request $request, Throwable $e) : Response;
}
Rendering Responses
The render
method in the exception handler class is used to render the response.
If the debug
value in the configuration file config/app.php
is set to true
(hereinafter referred to as app.debug=true
), detailed exception information will be returned; otherwise, simplified exception information will be returned.
If the request expects a JSON response, the returned exception information will be in JSON format, similar to:
{
"code": "500",
"msg": "Exception information"
}
If app.debug=true
, an additional trace
field will be included in the JSON data, returning the detailed call stack.
You can write your own exception handler class to change the default exception handling logic.
Business Exception BusinessException
Sometimes we want to terminate the request in a nested function and return an error message to the client. We can achieve this by throwing a BusinessException
. For example:
<?php
namespace app\controller;
use support\Request;
use support\exception\BusinessException;
class FooController
{
public function index(Request $request)
{
$this->checkInput($request->post());
return response('hello index');
}
protected function checkInput($input)
{
if (!isset($input['token'])) {
throw new BusinessException('Parameter error', 3000);
}
}
}
The above example will return a
{"code": 3000, "msg": "Parameter error"}
Note
A BusinessException does not need to be caught with a try-catch in business logic, as the framework will automatically catch it and return an appropriate output based on the request type.
Custom Business Exception
If the above response does not meet your requirements, for example, if you want to change msg
to message
, you can customize a MyBusinessException
.
Create a new file app/exception/MyBusinessException.php
with the following content:
<?php
namespace app\exception;
use support\exception\BusinessException;
use Webman\Http\Request;
use Webman\Http\Response;
class MyBusinessException extends BusinessException
{
public function render(Request $request): ?Response
{
// Return JSON data for JSON requests
if ($request->expectsJson()) {
return json(['code' => $this->getCode() ?: 500, 'message' => $this->getMessage()]);
}
// For non-JSON requests, return a page
return new Response(200, [], $this->getMessage());
}
}
Then when a business logic calls:
use app\exception\MyBusinessException;
throw new MyBusinessException('Parameter error', 3000);
JSON requests will receive a response similar to:
{"code": 3000, "message": "Parameter error"}
Tip
Since BusinessException is a business exception (for example, user input parameter errors), it is predictable. Therefore, the framework does not consider it a fatal error and will not log it.
Summary
Whenever you want to interrupt the current request and return information to the client, consider using the BusinessException
exception.