Вставьте новую запись, если она не существует, и обновите, если существует, laravel eloquent


есть ли какая-либо стенография для нас, чтобы вставить новую запись, если она не существует, и обновить запись, если она существует? ниже приведен код, который я использую.

$shopOwner = ShopMeta::where('shopId', '=', $theID)->where('metadataKey', '=', 2001)->first();
if ($shopOwner==null){
    insert new record into database
} else {
    update the existing record
}

спасибо

13 116

13 ответов:

вот полный пример того, о чем говорил" lu cip":

$user = User::firstOrNew(array('name' => Input::get('name')));
$user->foo = Input::get('foo');
$user->save();

Ниже приведена обновленная ссылка на документы, которая находится на последней версии Laravel

документы здесь: обновили ссылку

Обновлено: 27 Августа 2014 - [updateOrCreate встроена в ядро...]

на всякий случай люди все еще сталкиваются с этим... Я узнал несколько недель после написания этого, что это на самом деле часть основного красноречивый фреймворк Laravel по...

копание в эквивалентный метод(ы) красноречивого. Вы можете посмотреть здесь:

https://github.com/laravel/framework/blob/4.2/src/Illuminate/Database/Eloquent/Model.php#L553

on: 570 и :553

    /**
     * Create or update a record matching the attributes, and fill it with values.
     *
     * @param  array  $attributes
     * @param  array  $values
     * @return static
     */
    public static function updateOrCreate(array $attributes, array $values = array())
    {
        $instance = static::firstOrNew($attributes);

        $instance->fill($values)->save();

        return $instance;
    }

Старый Ответ Ниже


мне интересно, есть ли какие-либо встроенные функции L4 для этого каким-то образом, например:

$row = DB::table('table')->where('id', '=', $id)->first();
// Fancy field => data assignments here
$row->save();

Я создал этот метод несколько недель назад...

// Within a Model extends Eloquent
public static function createOrUpdate($formatted_array) {
    $row = Model::find($formatted_array['id']);
    if ($row === null) {
        Model::create($formatted_array);
        Session::flash('footer_message', "CREATED");
    } else {
        $row->update($formatted_array);
        Session::flash('footer_message', "EXISITING");
    }
    $affected_row = Model::find($formatted_array['id']);
    return $affected_row;
}

Я надеюсь, что это поможет. Я хотел бы видеть альтернативу этому, если у кого-то есть один, чтобы поделиться. @erikthedev_

а в Laravel >= 5.3, если кому-то все еще интересно, как это сделать простым способом. Его можно использовать с помощью:updateOrCreate().

например на вопрос, вы можете использовать что-то вроде:

$matchThese = array('shopId'=>$theID,'metadataKey'=>2001);
ShopMeta::updateOrCreate($matchThese,['shopOwner'=>'New One']);

выше код будет проверять таблицу, представленную ShopMeta, которая будет, скорее всего,shop_metas если не определено иначе в самой модели

и он будет пытаться найти запись с

колонки shopId = $theID

и

колонки metadateKey = 2001

и если он найдет, то он будет обновлять столбец shopOwner нашел строку New One.

если он находит более одной совпадающей строки, то он обновит самую первую строку, которая означает, что имеет самый низкий первичный id.

если не найдено вообще, то он будет вставлять новую строку с :

shopId = $theID,metadateKey = 2001 и shopOwner = New One

обратите внимание Проверьте свою модель для $fillable и сделать Сью у вас есть каждое имя столбца, определенное там, которое вы хотите вставить или обновить, а остальные столбцы имеют значение по умолчанию или его id столбец автоматически увеличивается на единицу.

в противном случае он выдаст ошибку при выполнении примера выше:

Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 1364 Field '...' doesn't have a default value (SQL: insert into `...` (`...`,.., `updated_at`, `created_at`) values (...,.., xxxx-xx-xx xx:xx:xx, xxxx-xx-xx xx:xx:xx))'

поскольку там будет какое-то поле, которое будет нуждаться в значении при вставке новой строки, и это не будет возможно, поскольку либо его не определено в $fillable или он не имеет значения по умолчанию.

для получения дополнительной информации, пожалуйста, см. Документация Laravel на : https://laravel.com/docs/5.3/eloquent

один пример оттуда:

// If there's a flight from Oakland to San Diego, set the price to .
// If no matching model exists, create one.
$flight = App\Flight::updateOrCreate(
    ['departure' => 'Oakland', 'destination' => 'San Diego'],
    ['price' => 99]
);

который в значительной степени очищает все.

надеюсь, это поможет

сохранить функция:

$shopOwner->save()

уже делать то, что вы хотите...

код Laravel:

    // If the model already exists in the database we can just update our record
    // that is already in this database using the current IDs in this "where"
    // clause to only update this model. Otherwise, we'll just insert them.
    if ($this->exists)
    {
        $saved = $this->performUpdate($query);
    }

    // If the model is brand new, we'll insert it into our database and set the
    // ID attribute on the model to the value of the newly inserted row's ID
    // which is typically an auto-increment value managed by the database.
    else
    {
        $saved = $this->performInsert($query);
    }
$shopOwner = ShopMeta::firstOrNew(array('shopId' => $theID,'metadataKey' => 2001));

затем внесите изменения и сохраните. Обратите внимание, что firstOrNew не делает вставку, если она не найдена, если вам это нужно, то ее firstOrCreate.

firstOrNew создаст запись, если она не существует, и обновит строку, если она уже существует. Вы также можете использовать updateOrCreate вот полный пример

$flight = App\Flight::updateOrCreate(
    ['departure' => 'Oakland', 'destination' => 'San Diego'],
    ['price' => 99]
); 

если есть рейс из Окленда в Сан-Диего, установили цену в $99. если не существует, создать новую строку

ссылка Doc здесь: (https://laravel.com/docs/5.5/eloquent)

еще один вариант, если Ваш идентификатор не является автоинкрементом, и вы знаете, какой из них вставить / обновить:

$object = MyModel::findOrNew($id);
//assign attributes to update...
$object->save();

на самом деле firstOrCreate не будет обновление в случае, если регистр уже существует в БД. Я немного улучшил решение Эрика, поскольку мне действительно нужно было обновить таблицу, которая имеет уникальные значения не только для столбца "id"

/**
 * If the register exists in the table, it updates it. 
 * Otherwise it creates it
 * @param array $data Data to Insert/Update
 * @param array $keys Keys to check for in the table
 * @return Object
 */
static function createOrUpdate($data, $keys) {
    $record = self::where($keys)->first();
    if (is_null($record)) {
        return self::create($data);
    } else {
        return self::where($keys)->update($data);
    }
}

тогда вы бы использовали его так:

Model::createOrUpdate(
        array(
    'id_a' => 1,
    'foo' => 'bar'
        ), array(
    'id_a' => 1
        )
);

как @JuanchoRamone опубликовано выше (спасибо @Juancho) это очень полезно для меня, но если ваши данные массив вы должны изменить немного так:

public static function createOrUpdate($data, $keys) {
    $record = self::where($keys)->first();
    if (is_null($record)) {
        return self::create($data);
    } else {
        return $record->update($data);
    }
}

как метод firstOrCreate, updateOrCreate сохраняется модель, Так что нет необходимости вызывать метод save()

// If there's a flight from Oakland to San Diego, set the price to .
// If no matching model exists, create one.

$flight = App\Flight::updateOrCreate(
   ['departure' => 'Oakland', 'destination' => 'San Diego'],
   ['price' => 99]
);

и для вашего вопроса

$shopOwner = ShopMeta::updateOrCreate(
   ['shopId' => $theID, 'metadataKey' => '2001'],
   ['other field' => 'val' ,'other field' => 'val', ....]
);

разве это не то же самое, что updateOrCreate()?

это похоже, но не то же самое. В updateOrCreate() будет работать только для одной строки за раз, которая не позволяет массовую вставку. InsertOnDuplicateKey будет работать на многих строках.

https://github.com/yadakhov/insert-on-duplicate-key

Если вам нужна такая же функциональность с помощью DB, в Laravel >= 5.5 вы можете использовать:

DB::table('table_name')->updateOrInsert($attributes, $values);

или сокращенная версия, когда $attributes и $values то же самое:

DB::table('table_name')->updateOrInsert($values);

проверьте, существует ли пользователь или нет. Если не вставить

$exist = DB::table('User')->where(['username'=>$username,'password'=>$password])->get();
if(count($exist)  >0) {
    echo "User already exist";;
}
else  {
    $data=array('username'=>$username,'password'=>$password);
    DB::table('User')->insert($data);
}
Laravel 5.4