Создание и обновление 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
}
15 ответов
Вот полный пример того, о чем говорил lu cip:
$user = User::firstOrNew(array('name' => Input::get('name')));
$user->foo = Input::get('foo');
$user->save();
Ниже приведена обновленная ссылка на документацию по последней версии Laravel.
Документы здесь: Обновленная ссылка
Как и в 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 $99.
// If no matching model exists, create one.
$flight = App\Flight::updateOrCreate(
['departure' => 'Oakland', 'destination' => 'San Diego'],
['price' => 99]
);
который в значительной степени очищает все.
Я надеюсь, что это помогает
Обновлено: 27 августа 2014 г. - [updateOrCreate
Встроенный в ядро ...]
Просто на тот случай, если люди все еще сталкиваются с этим... Я узнал через несколько недель после того, как написал это, что это на самом деле часть ядра Eloquent в Laravel...
Копаться в эквивалентных методах Eloquent. Вы можете увидеть здесь:
https://github.com/laravel/framework/blob/4.2/src/Illuminate/Database/Eloquent/Model.php
на: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_
firstOrNew
создаст запись, если она не существует, и обновит строку, если она уже существует. Вы также можете использовать updateOrCreate
вот полный пример
$flight = App\Flight::updateOrCreate(
['departure' => 'Oakland', 'destination' => 'San Diego'],
['price' => 99]
);
Если есть рейс из Окленда в Сан-Диего, установите цену в $99. если не существует, создайте новую строку
Справочный документ здесь: ( https://laravel.com/docs/5.5/eloquent)
Функция сохранения:
$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);
}
Если вам нужна та же функциональность, используя DB
в Ларавеле >= 5.5
ты можешь использовать:
DB::table('table_name')->updateOrInsert($attributes, $values);
или сокращенная версия, когда $attributes
а также $values
подобные:
DB::table('table_name')->updateOrInsert($values);
$shopOwner = ShopMeta::firstOrNew(array('shopId' => $theID,'metadataKey' => 2001));
Затем внесите изменения и сохраните. Обратите внимание, что firstOrNew не выполняет вставку, если она не найдена, если вам это нужно, тогда ее firstOrCreate.
Как и метод firstOrCreate, updateOrCreate сохраняет модель, поэтому нет необходимости вызывать save()
// If there's 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', ....]
);
Еще один вариант, если ваш идентификатор не является автоинкрементом, и вы знаете, какой из них вставить / обновить:
$object = MyModel::findOrNew($id);
//assign attributes to update...
$object->save();
Метод UpdateOrCreate означает либо обновление, либо создание путем проверки условия where.
Это просто, как в коде, который вы можете видеть в таблице пользователей, он проверит, имеет ли адрес электронной почты значение$user->email
затем он обновит данные (которые находятся во втором параметре в виде массива) или создаст данные в соответствии с ними.
$newUser = User::updateOrCreate(['email' => $user->email],[
'name' => $user->getName(),
'username' => $user->getName().''.$user->getId(),
'email' => $user->getEmail(),
'phone_no' => '',
'country_id' => 0,
'email_verified_at' => Carbon::now()->toDateTimeString(),
'is_email_verified' => 1,
'password'=>Hash::make('Secure123$'),
'avatar' => $user->getAvatar(),
'provider' => 'google',
'provider_id' => $user->getId(),
'access_token' => $user->token,
]);
Как @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 не будет обновляться, если регистр уже существует в БД. Я немного улучшил решение Эрика, так как мне действительно нужно было обновить таблицу с уникальными значениями не только для столбца "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
)
);
Разве это не то же самое, что updateOrCreate()?
Это похоже, но не то же самое. UpdateOrCreate () будет работать только для одной строки за раз, что не позволяет массовую вставку. InsertOnDuplicateKey будет работать на многих строках.
Попробуйте больше параметров, которые обязательно найдут, и если доступно обновление, а не тогда, он создаст новый
$save_data= Model::firstOrNew(['key1' => $key1value,'key'=>$key2value]);
//your values here
$save_data->save();
Проверьте, существует ли пользователь или нет. Если не вставить
$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