Quel est le raccourci pour insérer un nouvel enregistrement ou mettre à jour s'il n'existe pas?
<?php
$shopOwner = ShopMeta::where('shopId', '=', $theID)
->where('metadataKey', '=', 2001)->first();
if ($shopOwner == null) {
// Insert new record into database
} else {
// Update the existing record
}
Voici un exemple complet de ce que "lu cip" parlait:
$user = User::firstOrNew(array('name' => Input::get('name')));
$user->foo = Input::get('foo');
$user->save();
Ci-dessous le lien mis à jour de la documentation qui se trouve sur la dernière version de Laravel
Docs ici: Lien mis à jour
updateOrCreate
Built into core ...]Juste au cas où les gens continueraient à le comprendre ... quelques semaines après avoir écrit cela, j'ai découvert que cela faisait en fait partie du cœur de Eloquent de Laravel ...
Creuser dans les méthodes équivalentes d’Eloquent. Vous pouvez voir ici:
https://github.com/laravel/framework/blob/4.2/src/Illuminate/Database/Eloquent/Model.php#L553
sur: 570 et: 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;
}
Ancienne réponse ci-dessous
Je me demande s’il existe une fonctionnalité L4 intégrée permettant de le faire, par exemple:
$row = DB::table('table')->where('id', '=', $id)->first();
// Fancy field => data assignments here
$row->save();
J'ai créé cette méthode il y a quelques semaines ...
// 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;
}
J'espère que ça aide. J'aimerais voir une alternative à cela si quelqu'un en a une à partager. @ erikthedev_
Comme dans Laravel> = 5.3, si quelqu'un est toujours curieux de savoir comment le faire facilement. C'est possible en utilisant: updateOrCreate()
.
Par exemple, pour les questions posées, vous pouvez utiliser quelque chose comme:
$matchThese = array('shopId'=>$theID,'metadataKey'=>2001);
ShopMeta::updateOrCreate($matchThese,['shopOwner'=>'New One']);
Le code ci-dessus vérifie la table représentée par ShopMeta, qui sera probablement shop_metas
, sauf indication contraire dans le modèle lui-même.
et il va essayer de trouver une entrée avec
colonne shopId = $theID
et
colonne metadateKey = 2001
et s'il trouve, il mettra à jour la colonne shopOwner
de la ligne trouvée en New One
.
S'il trouve plus d'une ligne correspondante, il mettra à jour la toute première ligne, c'est-à-dire celle qui a la plus basse primaire id
.
S'il n'est pas trouvé du tout, il insérera une nouvelle ligne avec:
shopId = $theID
, metadateKey = 2001
et shopOwner = New One
Remarquez Recherchez $fillable
dans votre modèle et indiquez-lui que vous souhaitez insérer ou mettre à jour chaque nom de colonne défini. Les colonnes restantes ont une valeur par défaut ou sa colonne id
est incrémentée automatiquement.
Sinon, l'erreur sera générée lors de l'exécution de l'exemple ci-dessus:
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))'
Comme certains champs nécessiteront une valeur lors de l'insertion d'une nouvelle ligne, il ne sera pas possible, car ce n'est pas défini dans $fillable
ou il n'a pas de valeur par défaut.
Pour plus de références, veuillez consulter la documentation de Laravel à l'adresse suivante: https://laravel.com/docs/5.3/eloquent
Un exemple de cela est:
// 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]
);
ce qui efface à peu près tout.
_ {J'espère que ça aide} _
Fonction de sauvegarde:
$shopOwner->save()
fais déjà ce que tu veux ...
Code 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);
}
firstOrNew
va créer un enregistrement s'il n'existe pas et mettre à jour une ligne s'il existe déjà . Vous pouvez également utiliser updateOrCreate
voici l'exemple complet
$flight = App\Flight::updateOrCreate(
['departure' => 'Oakland', 'destination' => 'San Diego'],
['price' => 99]
);
_ {S'il y a un vol Oakland-San Diego, fixez le prix à 99 $. S'il n'existe pas, créez une nouvelle ligne.
Référence Doc ici: ( https://laravel.com/docs/5.5/eloquent )
$shopOwner = ShopMeta::firstOrNew(array('shopId' => $theID,'metadataKey' => 2001));
Ensuite, effectuez vos modifications et enregistrez. Notez que firstOrNew ne fait pas l'insertion s'il n'est pas trouvé, si vous en avez besoin, alors firstOrCreate.
Si vous avez besoin de la même fonctionnalité en utilisant la variable DB
, dans Laravel >= 5.5
, vous pouvez utiliser:
DB::table('table_name')->updateOrInsert($attributes, $values);
ou la version abrégée lorsque $attributes
et $values
sont identiques:
DB::table('table_name')->updateOrInsert($values);
Une option supplémentaire si votre identifiant n'est pas auto-incrémenté et que vous savez lequel insérer/mettre à jour:
$object = MyModel::findOrNew($id);
//assign attributes to update...
$object->save();
En fait, firstOrCreate ne serait pas update dans le cas où le registre existe déjà dans la base de données . J'ai un peu amélioré la solution d'Erik, car j'avais réellement besoin de mettre à jour une table comportant des valeurs uniques, pas seulement pour la colonne. "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);
}
}
Ensuite, vous l'utiliseriez comme ceci:
Model::createOrUpdate(
array(
'id_a' => 1,
'foo' => 'bar'
), array(
'id_a' => 1
)
);
comme @JuanchoRamone posté ci-dessus (merci @Juancho), c'est très utile pour moi, mais si vos données sont un tableau, vous devriez modifier un peu comme ceci:
public static function createOrUpdate($data, $keys) {
$record = self::where($keys)->first();
if (is_null($record)) {
return self::create($data);
} else {
return $record->update($data);
}
}
Comme la méthode firstOrCreate, updateOrCreate conserve le modèle, il n'est donc pas nécessaire d'appeler 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]
);
Et pour ton problème
$shopOwner = ShopMeta::updateOrCreate(
['shopId' => $theID, 'metadataKey' => '2001'],
['other field' => 'val' ,'other field' => 'val', ....]
);
N'est-ce pas la même chose que updateOrCreate ()?
C'est pareil mais pas pareil. UpdateOrCreate () ne fonctionnera que pour une ligne à la fois qui ne permet pas l'insertion en bloc . InsertOnDuplicateKey fonctionnera sur plusieurs lignes.