web-dev-qa-db-fra.com

Création et mise à jour de Laravel Eloquent

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
}
126
1myb

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

198
weotch

Mise à jour: 27 août 2014 - [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_

68
Erik Aybar

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} _

44
Learner

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);
    }
16
lu cip

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 )

10
Saeed Ansari
$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. 

5
malhal

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);
4
Sasa Blagojevic

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();
2
vivoconunxino

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
        )
);
1
Juancho Ramone

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);
    }
}
1
Duy Ngo

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', ....]
);
1
Mahdi Bashirpour

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.

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

0
Pax Exterminatus