[英]Laravel check for constraint violation
I was curious if there is a way we can check if there is a constraint violation error when delete or insert a record into the database. 我很好奇,是否有一种方法可以在删除记录或将记录插入数据库时检查是否存在约束冲突错误。
The exception thrown is called 'QueryException' but this can be a wide range of errors. 引发的异常称为“ QueryException”,但这可能是多种错误。 Would be nice if we can check in the exception what the specific error is.
如果我们可以检查异常的具体错误,那就太好了。
You are looking for the 23000 Error code (Integrity Constraint Violation)
. 您正在寻找
23000 Error code (Integrity Constraint Violation)
。 If you take a look at QueryException
class, it extends from PDOException
, so you can access to $errorInfo
variable. 如果您看一下
QueryException
类,它是从PDOException
扩展的,因此您可以访问$errorInfo
变量。
To catch this error, you may try: 要捕获此错误,您可以尝试:
try {
// ...
} catch (\Illuminate\Database\QueryException $e) {
var_dump($e->errorInfo);
}
// Example output from MySQL
array (size=3)
0 => string '23000' (length=5)
1 => int 1452
2 => string 'Cannot add or update a child row: a foreign key constraint fails (...)'
To be more specific (Duplicate entry, not null, add/update child row, delete parent row...), it depends on each DBMS: 更具体地说(重复条目,不为null,添加/更新子行,删除父行...),它取决于每个DBMS:
SQLSTATE
code, so you may return the first value from the array $e->errorInfo[0]
or call $e->getCode()
directly SQLSTATE
代码约定,因此您可以从数组$e->errorInfo[0]
返回第一个值,或直接调用$e->getCode()
$e->errorInfo[1]
$e->errorInfo[1]
返回第二个值。 For laravel, handling errors is easy, just add this code in your "app/start/global.php" file ( or create a service provider ): 对于laravel,处理错误很容易,只需将以下代码添加到您的“ app / start / global.php”文件中(或创建一个服务提供商 ):
App::error(function(\Illuminate\Database\QueryException $exception)
{
$error = $exception->errorInfo;
// add your business logic
});
You may also try 您也可以尝试
try {
...
} catch ( \Exception $e) {
var_dump($e->errorInfo );
}
then look for error code. 然后寻找错误代码。
This catches all exception including QueryException 这捕获了所有异常,包括QueryException
first put this in your controller 首先把它放在你的控制器中
use Exception;
second handle the error by using try catch like this example 第二个通过使用try catch处理错误的例子
try{ //here trying to update email and phone in db which are unique values
DB::table('users')
->where('role_id',1)
->update($edit);
return redirect("admin/update_profile")
->with('update','update');
}catch(Exception $e){
//if email or phone exist before in db redirect with error messages
return redirect()->back()->with('phone_email','phone_email_exist before');
}
New updates here without need to use try catch you can easily do that in validation rules as the following code blew 此处的新更新无需使用try catch,您可以在验证规则中轻松完成此操作,因为以下代码自爆
public function update(Request $request, $id)
{
$profile = request()->all();
$rules = [
'name' => 'required|unique:users,id,'.$id,
'email' => 'required|email|unique:users,id,'.$id,
'phone' => 'required|unique:users,id,'.$id,
];
$validator = Validator::make($profile,$rules);
if ($validator->fails()){
return redirect()->back()->withInput($profile)->withErrors($validator);
}else{
if(!empty($profile['password'])){
$save['password'] = bcrypt($profile['password']);
}
$save['name'] = $profile['name'];
$save['email'] = $profile['email'];
$save['phone'] = $profile['phone'];
$save['remember_token'] = $profile['_token'];
$save['updated_at'] = Carbon::now();
DB::table('users')->where('id',$id)->update($save);
return redirect()->back()->with('update','update');
}
}
where id related to record which you edit. 与您要编辑的记录相关的ID。
If you are using Laravel version 5
and want global exception handling of specific cases you should put your code in the report
method of the /app/Exception/Handler.php
file. 如果您使用的是Laravel
version 5
并且希望对特定情况进行全局异常处理,则应将代码放在/app/Exception/Handler.php
文件的report
方法中。 Here is an example of how we do it in one of our micro services: 这是我们如何在其中的一个微服务中执行此操作的示例:
public function render($request, Exception $e)
{
$response = app()->make(\App\Support\Response::class);
$details = $this->details($e);
$shouldRenderHttp = $details['statusCode'] >= 500 && config('app.env') !== 'production';
if($shouldRenderHttp) {
return parent::render($request, $e);
}
return $response->setStatusCode($details['statusCode'])->withMessage($details['message']);
}
protected function details(Exception $e) : array
{
// We will give Error 500 if we cannot detect the error from the exception
$statusCode = 500;
$message = $e->getMessage();
if (method_exists($e, 'getStatusCode')) { // Not all Exceptions have a http status code
$statusCode = $e->getStatusCode();
}
if($e instanceof ModelNotFoundException) {
$statusCode = 404;
}
else if($e instanceof QueryException) {
$statusCode = 406;
$integrityConstraintViolation = 1451;
if ($e->errorInfo[1] == $integrityConstraintViolation) {
$message = "Cannot proceed with query, it is referenced by other records in the database.";
\Log::info($e->errorInfo[2]);
}
else {
$message = 'Could not execute query: ' . $e->errorInfo[2];
\Log::error($message);
}
}
elseif ($e instanceof NotFoundHttpException) {
$message = "Url does not exist.";
}
return compact('statusCode', 'message');
}
The Response
class we use is a simple wrapper of Symfony\\Component\\HttpFoundation\\Response as HttpResponse
which returns HTTP responses in a way that better suits us. 我们使用的
Response
类是Symfony\\Component\\HttpFoundation\\Response as HttpResponse
的简单包装, Symfony\\Component\\HttpFoundation\\Response as HttpResponse
,它以更适合我们的方式返回HTTP响应。
Have a look at the documentation , it is straightforward. 看一下文档 ,很简单。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.