Подтвердить что ты не робот

Проверка Laravel на нарушение ограничений

Мне было любопытно, есть ли способ проверить, есть ли ошибка нарушения ограничения при удалении или вставить запись в базу данных.

Исключенное исключение называется QueryException, но это может быть широкий диапазон ошибок. Было бы неплохо, если бы мы могли проверить исключение, какова конкретная ошибка.

4b9b3361

Ответ 1

Вы ищете 23000 Error code (Integrity Constraint Violation). Если вы посмотрите на QueryException класс, он простирается от PDOException, поэтому вы можете получить доступ к переменной $errorInfo.

Чтобы поймать эту ошибку, вы можете попробовать:

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 (...)'

Чтобы быть более конкретным (Duplicate entry, not null, add/update child row, delete parent row...), это зависит от каждой СУБД:

  • PostgreSQL и SQL-сервер следовать стандартные соглашения SQL для кода SQLSTATE, поэтому вы можете вернуть первое значение из массива $e->errorInfo[0] или вызвать $e->getCode() непосредственно
  • MySQL, MariaDB и SQLite не строго соблюдают правила, поэтому вам нужно вернуть второе значение из массива $e->errorInfo[1]

Для laravel, обработка ошибок проста, просто добавьте этот код в свой файл "app/start/global.php" (или создайте поставщик услуг):

App::error(function(\Illuminate\Database\QueryException $exception)
{
    $error = $exception->errorInfo;
    // add your business logic
});

Ответ 2

Вы также можете попробовать

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

затем найдите код ошибки.

Это улавливает все исключения, включая QueryException

Ответ 3

сначала поместите это в свой контроллер

use Exception;

второй обработать ошибку с помощью 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');
            }

Новые обновления здесь без необходимости использовать 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');
    }
}

где id относится к записи, которую вы редактируете.

Ответ 4

Вы можете добавить следующий код в файл app/start/global.php, чтобы распечатать исключение

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

проверьте часть в документации

Ответ 5

Если вы используете Laravel version 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');
}

Класс Response мы используем, представляет собой простую оболочку Symfony\Component\HttpFoundation\Response as HttpResponse которая возвращает HTTP-ответы более Symfony\Component\HttpFoundation\Response as HttpResponse для нас способом.