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

Что за сокращение для вставки новой записи или обновления, если она не существует?

<?php

$shopOwner = ShopMeta::where('shopId', '=', $theID)
    ->where('metadataKey', '=', 2001)->first();

if ($shopOwner == null) {
    // Insert new record into database
} else {
    // Update the existing record
}

Ответ 1

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

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

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

Документы здесь: Обновленная ссылка

Ответ 2

Обновлено: 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 _

Ответ 3

Как и в 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 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]
);

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

Обновление Query Builder

Кто-то спросил, возможно ли использовать Query Builder в Laravel. Вот ссылка на Query Builder из документов Laravel.

Query Builder работает точно так же, как Eloquent, поэтому все, что верно для Eloquent, также верно и для Query Builder. Так что для этого конкретного случая просто используйте ту же функцию с вашим построителем запросов, например, так:

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

Конечно, не забудьте добавить фасад БД:

use Illuminate\Support\Facades\DB;

ИЛИ ЖЕ

use DB;

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

Ответ 4

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

$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);
    }

Ответ 5

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

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

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

Ссылочный документ здесь: (https://laravel.com/docs/5.5/eloquent)

Ответ 6

$shopOwner = ShopMeta::firstOrNew(array('shopId' => $theID,'metadataKey' => 2001));

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

Ответ 7

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

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

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

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

Ответ 8

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

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

Ответ 9

Фактически 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
        )
);

Ответ 10

как @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);
    }
}

Ответ 11

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

// 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]
);

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

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

Ответ 12

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

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

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

Ответ 13

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

$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