Laravel Eloquent, как справиться с УНИКАЛЬНОЙ ошибкой? - PullRequest
2 голосов
/ 20 июня 2019

У меня есть ограничение MySQL для обеспечения уникальности составного ключа. При вставке новой записи в мою модель Foo я получаю ожидаемую ошибку:

$foo = new Foo(['foo' => 42, 'bar => 1]);
$foo->save();

Ошибка:

SQLSTATE [23000]: нарушение ограничения целостности: 1062 Повторяющаяся запись '42' для ключа 'Уникальный' ...

Одним из способов избежать этой ошибки является запрос модели перед вставкой:

if (!Foo::where('foo', 42)->where('bar', 1)->first()) {
  $foo = new Foo(['foo' => 42, 'bar => 1]);
  $foo->save();
}

Еще один вариант - перехватить исключение, когда preg_match(/UNIQUE/, $e->message) равно true.

Есть ли лучшее решение?

EDIT

Я заметил, что в Illuminate\Database\Eloquent\Builder Laravel все равно выполняет двойной запрос, что немного грустно:

public function findOrNew($id, $columns = ['*'])
{
    if (! is_null($model = $this->find($id, $columns))) {
        return $model;
    }

    return $this->newModelInstance();
}

Ответы [ 4 ]

3 голосов
/ 20 июня 2019

Вы можете использовать метод firstOrCreate:

$foo = Foo::firstOrCreate(['foo' => 42, 'bar' => 1]);

Это проверит, существует ли запись в базе данных перед ее созданием. Если он существует, он вернет запись.

Для получения дополнительной информации: https://laravel.com/docs/5.8/eloquent#inserting-and-updating-models

2 голосов
/ 20 июня 2019

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

В вашем конкретном случае предварительный запрос или использование метода Laravel, который делает это автоматически для вас, может быть предпочтительнее, если вы намерены перезаписать / обновить существующие данные.

Если вы хотите предвидеть ошибку и обрабатывать ее, вы должны сделать что-то вроде:

try {
   $foo = new Foo(['foo' => 42, 'bar' => 1]);
   $foo->save();
} catch (\Exception $e) { // It's actually a QueryException but this works too
   if ($e->getCode() == 23000) {
       // Deal with duplicate key error  
   }
}

См. https://dev.mysql.com/doc/refman/5.5/en/error-reference.html для получения исчерпывающего списка кодов ошибок (но в идеале вам нужно иметь дело только с парой конкретных ошибок и при очень определенных обстоятельствах.

Наконец, SQL ON DUPLICATE KEY UPDATE также может работать для вас, однако, если вы делаете это, чтобы игнорировать новые значения, тогда я предлагаю вам вместо этого выполнить обработку ошибок.

2 голосов
/ 20 июня 2019

Проверка должна быть выполнена на уровне контроллера (например, laravel Validator), и лучше сделать count() вместо first().

. Существуют различные решения в зависимости от того, что вы хотите сделать, когдасущность существует в базе данных.Например, вы можете сделать updateOrCreate()

$foo = App\Foo::updateOrCreate(['foo' => 42, 'bar' => 1]);

или сгенерировать исключение

2 голосов
/ 20 июня 2019

laravel предоставляет вам функции firstOrCreate, которые сначала проверяют, существует ли это значение в базе данных, затем у вас также есть функция updateOrCreate для использования, если вы хотите обновить какое-то значение, но самое важное, если вы хотите обрабатывать только уникальныеЗатем записи проверяют правила валидации, вы должны выполнить FormRequest и добавить уникальное правило в это поле, после того как laravel предоставит вам сообщения об ошибках, чтобы вы обрабатывали ошибку на стороне клиента

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...