php Laravel 检查约束违规

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26363271/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 22:52:19  来源:igfitidea点击:

Laravel check for constraint violation

phplaravellaravel-4exception-handling

提问by guidsen

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. Would be nice if we can check in the exception what the specific error is.

抛出的异常称为“QueryException”,但这可能是范围广泛的错误。如果我们可以在异常中检查特定错误是什么,那就太好了。

回答by Razor

You are looking for the 23000 Error code (Integrity Constraint Violation). If you take a look at QueryExceptionclass, it extends from PDOException, so you can access to $errorInfovariable.

您正在寻找23000 Error code (Integrity Constraint Violation). 如果您查看QueryExceptionclass,它从 扩展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:

更具体地说(重复条目,不为空,添加/更新子行,删除父行...),这取决于每个 DBMS:

  • PostgreSQLand SQL serverfollow the SQL standard's conventions for SQLSTATEcode, so you may return the first value from the array $e->errorInfo[0]or call $e->getCode()directly
  • MySQL, MariaDBand SQLitedo not strictly obey the rules, so you need to return the second value from the array $e->errorInfo[1]
  • PostgreSQLSQL Server遵循 SQL 标准的SQLSTATE代码约定,因此您可以从数组中返回第一个值$e->errorInfo[0]$e->getCode()直接调用
  • MySQLMariaDBSQLite不严格遵守规则,因此您需要从数组中返回第二个值$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
});

回答by Ahmed Mahmoud

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 catchyou 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 与您编辑的记录相关。

回答by Sam Wong

You may also try

你也可以试试

try {
       ...
    } catch ( \Exception $e) {
         var_dump($e->errorInfo );
    }

then look for error code.

然后查找错误代码。

This catches all exception including QueryException

这会捕获所有异常,包括 QueryException

回答by geoandri

You can add the following code in app/start/global.php file in order to print the exception

您可以在 app/start/global.php 文件中添加以下代码以打印异常

App::error(function(QueryException $exception)
{
  print_r($exception->getMessage()); 
 });

check this partin the documentation

检查文档中的这一部分

回答by Patrick.SE

If you are using Laravel version 5and want global exception handling of specific cases you should put your code in the reportmethod of the /app/Exception/Handler.phpfile. Here is an example of how we do it in one of our micro services:

如果您使用 Laravelversion 5并希望对特定情况进行全局异常处理,则应将代码放在文件的report方法中/app/Exception/Handler.php。以下是我们如何在我们的一项微服务中执行此操作的示例:

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 Responseclass we use is a simple wrapper of Symfony\Component\HttpFoundation\Response as HttpResponsewhich returns HTTP responses in a way that better suits us.

Response我们使用的类是一个简单的包装器,Symfony\Component\HttpFoundation\Response as HttpResponse它以更适合我们的方式返回 HTTP 响应。

Have a look at the documentation, it is straightforward.

看一下文档,很简单。