Создание и обновление Laravel Eloquent

78

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

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

Спасибо

  • 0
    Я предполагаю, что shopId - это не ваш первичный ключ, верно?
  • 0
    @SergiuParaschiv, да. это не
Показать ещё 2 комментария
Теги:

9 ответов

133
Лучший ответ

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

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

Документы здесь: http://laravel.com/docs/eloquent#insert-update-delete

  • 1
    именно так! 'firstOrNew' также существует в 4.0 (не упоминается в документации)
  • 1
    Также мы можем проверить, что $ user новый / получен с помощью if ($ user-> существующие).
Показать ещё 2 комментария
53

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

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

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

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 _

  • 0
    Есть и это называется firstOrNew / firstsOrCreate
  • 0
    @malcolmhall Я обновил ответ выше. Оказывается, в Eloquent есть много функций, которые я восстановил;) Всегда приятно потратить некоторое время на просмотр документации :)
Показать ещё 3 комментария
27

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

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

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

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

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

column shopId = $theID

и

column metadateKey = 2001

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

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

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

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

Примечание Проверьте свою модель на $fillable и сделайте sue, что у вас есть каждое имя столбца, которое указано в столбцах, в которые вы хотите вставить, или обновить и сохранить столбцы, либо по умолчанию, либо в столбце 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 a flight from Oakland to San Diego, set the price to $99.
// If no matching model exists, create one.
$flight = App\Flight::updateOrCreate(
    ['departure' => 'Oakland', 'destination' => 'San Diego'],
    ['price' => 99]
);

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

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

16

Сохранить функцию:

$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 ID
    // which is typically an auto-increment value managed by the database.
    else
    {
        $saved = $this->performInsert($query);
    }
  • 6
    Это не похоже на атомную операцию. Если это не так, это может привести к условиям гонки.
  • 0
    Этот код проверяет, загружена ли модель из БД или является моделью на основе памяти. Обновление или создание требует явного определения ключевых столбцов, которые должны быть проверены и не могут быть выполнены неявно.
5
$shopOwner = ShopMeta::firstOrNew(array('shopId' => $theID,'metadataKey' => 2001));

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

1

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

$object = MyModel::findOrNew($id);
//assign attributes to update...
$object->save();
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);
    }
}
  • 0
    Просто быстрое замечание, что это должно быть updateOrCreate вместо createOrUpdate
  • 0
    Хорошо, но если есть 1000 строк, будет запущено 1000 запросов?
1

Фактически firstOrCreate не будет обновлять, если регистр уже существует в БД. Я немного улучшил решение Erik, поскольку мне действительно нужно было обновить таблицу, которая имеет уникальные значения не только для столбца "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
        )
);
-2

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

$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           
  • 0
    Добро пожаловать в SO.Посмотрите этот практический совет для обеспечения качественного ответа. ---
  • 0
    Пожалуйста, также пометьте фреймворк, который вы используете, версию php, базу данных.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню