Есть ли опция insertUsing с игнорированием?

#php #laravel-5.7

#php #laravel-5.7

Вопрос:

В Laravel существует два полезных метода в DB facade:

  • insertOrIgnore() — позволяет игнорировать действие при вставке дубликата
  • insertUsing() — позволяет вставлять данные на основе данных из других таблиц

Мне нужно объединить эти два подхода, т.е. вставить данные на основе существующих данных и игнорировать дубликаты. Знаете ли вы какой-либо способ сделать это в Laravel 5.7 или новее?

Ответ №1:

Для этого нет ни одного простого метода. Но этого можно достичь с помощью facade DB .

Давайте предположим, что у нас есть 2 модели:

 class Car extends Model
{
    protected $table = "cars";

    protected $fillable = [
        "name",
        "production_year",
    ];
}
  
 class Antique extends Model
{
    protected $table = "antiques";

    protected $fillable = [
        "name",
        "production_year",
        "category",
    ];
}
  

Предположим, что наша задача — найти все автомобили, созданные до 1990 года, и на их основе создать антиквариат с категорией ‘car’, игнорируя все автомобили, которые уже существуют в таблице антиквариат.

Это решение.

 $selectQuery = Car::where('production_year', '<', 1990)->select([
    'name',
    'production_year',
    DB::raw('"car" as category'),
]);
$antiquesTable = (new Antique())->getTable();
$insertQuery = "INSERT IGNORE INTO $antiquesTable (
        `name`,
        `production_year`,
        `category`
    ) "
    . $selectQuery->toSql();
DB::insert($insertQuery, $selectQuery->getBindings());
  

Это сгенерирует следующий SQL-запрос

 INSERT IGNORE INTO antiques (`name`, `production_year`, `category`)
SELECT `name`, `production_year`, "car" AS category FROM cars WHERE `production_year` < 1990