PHP Exceptions are thrown when an unprecedented event or error occurs. As a rule of thumb, an exception should not be used to control the application logic such as if-statements and should be a subclass of the Exception
class.
当发生前所未有的事件或错误时,将引发PHP异常。 根据经验,不应将异常用于控制应用程序逻辑(例如if语句),而应将其作为Exception
类的子类。
Being unprecedented, an exception can be thrown at any point or time of our application.
前所未有,可以在我们应用程序的任何时间或任何点抛出异常。
Laravel provides a convenient exception handler class that checks for all exceptions thrown in a laravel application and gives relevant responses. This is made possible by the fact that all Exceptions used in Laravel extend the Exception class.
Laravel提供了一个方便的异常处理程序类,用于检查laravel应用程序中引发的所有异常并给出相关的响应。 由于Laravel中使用的所有Exception都扩展了Exception类,因此可以做到这一点。
One main advantage of having all exceptions caught by a single class is that we are able to create custom exception handlers that return different response messages depending on the exception.
将所有异常捕获到一个类中的一个主要优点是,我们能够创建自定义异常处理程序,该处理程序根据异常返回不同的响应消息。
In this tutorial, we will look at how to create a custom exception handler in Laravel 5.2 and how to return a 404 page depending on the Exception.
在本教程中,我们将研究如何在Laravel 5.2中创建自定义异常处理程序以及如何根据异常返回404页面。
这个怎么运作 ( How it Works )
In Laravel 5.2, all errors and exceptions, both custom and default, are handled by the Handler
class in app/Exceptions/Handler.php
with the help of two methods.
在Laravel 5.2中,所有错误和异常(无论是自定义还是默认)都由app/Exceptions/Handler.php
的Handler
类在两个方法的帮助下进行处理。
report()
report()
The report method enables you to log raised exceptions or parse them to error logging engines such as bugsnag or sentry which we will not delve into in this tutorial.
通过report方法,您可以记录引发的异常或将其解析为错误记录引擎,例如bugsnag或哨兵 ,我们将不在本教程中深入研究。
render()
render()
The render method responds with an error message raised by an exception. It generates a HTTP response from the exception and sends it back to the browser.
render方法以异常引发的错误消息作为响应。 它根据异常生成HTTP响应,并将其发送回浏览器。
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
return parent::render($request, $e);
}
We can however override the default error handling with our own custom exception handler.
但是,我们可以使用我们自己的自定义异常处理程序覆盖默认错误处理。
/**
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
if ($e instanceof CustomException) {
return response()->view('errors.custom', [], 500);
}
return parent::render($request, $e);
}
Under the hood, Laravel does it's own handling checks to determine the best possible response for an exception. Taking a look at the parent class (Illuminate\Foundation\Exceptions\Handler
), the render method generates a different response depending on the thrown Exception.
在后台,Laravel自己进行处理检查,以确定对异常的最佳可能响应。 看一下父类( Illuminate\Foundation\Exceptions\Handler
),render方法根据抛出的Exception生成不同的响应。
/**
* Render an exception into a response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Symfony\Component\HttpFoundation\Response
*/
public function render($request, Exception $e)
{
if ($e instanceof HttpResponseException) {
return $e->getResponse();
} elseif ($e instanceof ModelNotFoundException) {
$e = new NotFoundHttpException($e->getMessage(), $e);
} elseif ($e instanceof AuthenticationException) {
return $this->unauthenticated($request, $e);
} elseif ($e instanceof AuthorizationException) {
$e = new HttpException(403, $e->getMessage());
} elseif ($e instanceof ValidationException && $e->getResponse()) {
return $e->getResponse();
}
if ($this->isHttpException($e)) {
return $this->toIlluminateResponse($this->renderHttpException($e), $e);
} else {
return $this->toIlluminateResponse($this->convertExceptionToResponse($e), $e);
}
}
引发Laravel口才异常 ( Throwing a Laravel Eloquent Exception )
In this section, we will create an inbuilt Laravel error by intentionally raising an exception.
在本节中,我们将通过有意引发异常来创建内置的Laravel错误。
To do this, we will try to fetch records that do not exist from a model using the firstOrFail()
Eloquent method.
为此,我们将尝试使用firstOrFail()
方法从模型中获取不存在的记录。
Go ahead and set up a simple sqlite database. Luckily, Laravel ships with a User
model and a corresponding users table. Simply do the following.
继续并建立一个简单的sqlite数据库。 幸运的是,Laravel附带了一个User
模型和一个对应的users表。 只需执行以下操作。
- Create a new laravel project. 创建一个新的laravel项目。
- Update your
.env
file to have DB_CONNECTION to be sqlite and the only database parameter. 更新您的.env
文件,使DB_CONNECTION成为sqlite和唯一的数据库参数。 - Create a database.sqlite file in the database directory. This is the default sqlite database as configured in
config/database.php
在数据库目录中创建一个database.sqlite文件。 这是在config/database.php
中config/database.php
的默认sqliteconfig/database.php
- Run
php artisan migrate
on the route of your laravel project. This will set up a users table in the database. 在您的laravel项目路线上运行php artisan migrate
migration。 这将在数据库中建立一个用户表。
We will then add a route and a controller to get the first user in our users table who just so happens not to exist.
然后,我们将添加一条路由和一个控制器,以在我们的用户表中获得第一个用户,而该用户恰好不存在。
app/Http/routes.php
app / Http / routes.php
Route::get('/user', [
'uses' => 'SampleController@findUser',
'as' => 'user'
]);
App/Http/Controllers/SampleController.php
App / Http / Controllers / SampleController.php
/**
* Return the first user in the users table
*
* @return Array User details
*/
public function findUser()
{
$user = User::firstOrFail();
return $user->toArray();
}
Running this on the browser will return , a ModelNotFoundException
error response.
在浏览器上运行此命令将返回,一个ModelNotFoundException
错误响应。
使用自定义处理程序捕获异常 ( Catching Exceptions with a Custom Handler )
ModelNotFoundException (ModelNotFoundException)
With this exception, we can now add a custom handler that returns our own error message.
有了这个例外,我们现在可以添加一个自定义处理程序,该处理程序返回我们自己的错误消息。
We will modify the render
method in app/Exceptions/Handler.php
to return a json response for an ajax request or a view for a normal request if the exception is one of ModelNotFoundException
or NotFoundHttpException
.
如果异常是ModelNotFoundException
或NotFoundHttpException
之一,我们将修改app/Exceptions/Handler.php
的render
方法,以返回ajax请求的json响应或正常请求的视图。
If it is neither of the two, we will let laravel handle the exception.
如果两者都不是,我们将让laravel处理该异常。
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
//check if exception is an instance of ModelNotFoundException.
if ($e instanceof ModelNotFoundException) {
// ajax 404 json feedback
if ($request->ajax()) {
return response()->json(['error' => 'Not Found'], 404);
}
// normal 404 view page feedback
return response()->view('errors.missing', [], 404);
}
return parent::render($request, $e);
}
Add a 404.blade.php
file in resources/view/errors to contain our user feedback.
在resources / view / errors中添加404.blade.php
文件,以包含我们的用户反馈。
<!DOCTYPE html>
<html>
<head>
<title>User not found.</title>
</head>
<body>
<p>You broke the balance of the internet</p>
</body>
</html>
If we now refresh the page, we have the following message on our view with a 404 status code.
如果现在刷新页面,则视图上将显示以下消息,其中包含404状态代码。
NotFoundHttpException (NotFoundHttpException)
When a user visits an undefined route such as /foo/bar/randomstr1ng, a NotFoundHttpException
exception, which comes as part of the Symfony package, is thrown.
当用户访问未定义的路由(例如/ foo / bar / randomstr1ng)时 ,将抛出NotFoundHttpException
异常,该异常是Symfony软件包的一部分。
To handle this exception, we will add a second condition in the render
method we modified earlier and return a message from resources/view/errors/missing.blade.php
为了处理此异常,我们将在先前修改的render
方法中添加第二个条件,并从resources / view / errors / missing.blade.php返回一条消息。
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
//check if exception is an instance of ModelNotFoundException.
//or NotFoundHttpException
if ($e instanceof ModelNotFoundException or $e instanceof NotFoundHttpException) {
// ajax 404 json feedback
if ($request->ajax()) {
return response()->json(['error' => 'Not Found'], 404);
}
// normal 404 view page feedback
return response()->view('errors.missing', [], 404);
}
return parent::render($request, $e);
}
利用Laravel中止方法 ( Taking Advantage of Laravel's Abort Method )
Just like we did in the previous section, Laravel 5.2 makes it all too easy to create custom error pages based on the exception that was thrown.
就像我们在上一节中所做的一样,Laravel 5.2使根据抛出的异常创建自定义错误页面变得非常容易。
We can also simply generate a 404 error page response by calling the abort
method which takes an optional response message.
我们还可以通过调用带有可选响应消息的abort
方法来简单地生成404错误页面响应。
abort(404, 'The resource you are looking for could not be found');
This will check for a corresponding resources/view/errors/404.blade.php
and serve a HTTP response with the 404 status code back to the browser. The same applies for 401 and 500 error status codes.
这将检查相应的resources/view/errors/404.blade.php
并将带有404状态代码的HTTP响应返回给浏览器。 401和500错误状态代码也是如此。
结论 ( Conclusion )
Depending on an application's environment, you may want to show varying levels of error details. You can set the APP_DEBUG
value in config/app.php
to either true or false by changing it in your .env
file.
根据应用程序的环境,您可能需要显示不同级别的错误详细信息。 您可以通过在.env
文件中进行更改,将config/app.php
的APP_DEBUG
值设置为true或false。
In most cases, you may not want your users in production to see detailed error messages. It is therefore good practice to set APP_DEBUG
value to false while in a production environment.
在大多数情况下,您可能不希望生产环境中的用户看到详细的错误消息。 因此,在生产环境中,最好将APP_DEBUG
值设置为false。
翻译自: https://scotch.io/tutorials/creating-a-laravel-404-page-using-custom-exception-handlers