web-dev-qa-db-ja.com

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

これが "lu cip"が話していたことの完全な例です:

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

以下はLaravelの最新版にあるドキュメントの更新されたリンクです。

こちらのドキュメント: 更新されたリンク

205
weotch

更新:2014年8月27日 - [updateOrCreateコアに組み込まれています...]

念のために、人々がまだこれに遭遇しています...これを書いてから数週間後に、これは実際にはLaravelのEloquentのコアの一部であることがわかりました...

Eloquentの同等の方法を詳しく調べてください。あなたはここで見ることができます:

https://github.com/laravel/framework/blob/4.2/src/Illuminate/Database/Eloquent/Model.php#L553

on:570 and: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_

71
Erik Aybar

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に更新します。

複数の一致する行が見つかった場合、一番最初の行が更新されます。つまり、最初の行が最小の1次idになります。

まったく見つからない場合は、次のように新しい行を挿入します。

shopId = $theIDmetadateKey = 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]
);

これはほとんどすべてをクリアします。

クエリビルダーの更新

LaravelでQuery Builderを使用することが可能かどうか、誰かが尋ねました。 ここで はLaravel docsからのQuery Builderのリファレンスです。

Query BuilderはEloquentとまったく同じように機能するため、Eloquentに当てはまるものはすべてQuery Builderにも当てはまります。したがって、この特定のケースでは、クエリビルダーと同じ関数を次のように使用します。

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

もちろん、DBファサードを追加することを忘れないでください。

use Illuminate\Support\Facades\DB;

OR

use DB;

お役に立てば幸いです

47
Learner

保存機能:

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

firstOrNewは、存在しない場合はレコードを作成し、すでに存在する場合は行を更新します。 updateOrCreateも使用できます。これは完全な例です。

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

オークランドからサンディエゴへのフライトがある場合は、価格を$ 99に設定してください。存在しない場合は新しい行を作成します

ここでの参照資料:( https://laravel.com/docs/5.5/eloquent

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

その後、変更を加えて保存します。 firstOrNewが見つからない場合は挿入を実行しません。必要な場合はfirstOrCreateを使用してください。

5
malhal

DBを使用して同じ機能が必要な場合は、Laravel >= 5.5で使用できます。

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

$attributes$valuesが同じ場合は省略形

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

あなたのIDが自動インクリメントではなく、あなたが挿入/更新するものを知っているならばもう一つのオプション:

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

実際にはfirstOrCreateは既にレジスタが存在する場合は更新しません DB列 "id"だけでなく一意の値を持つテーブルを実際に更新する必要があったため、少しErikのソリューションを改善しました。

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

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

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

これはupdateOrCreate()と同じではありませんか?

それは似ていますが同じではありません。 updateOrCreate()は一度に1行ずつしか動作しないため、一括挿入はできません。 InsertOnDuplicateKeyは多くの行で機能します。

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

0