Creating and Update Laravel Eloquent

后端 未结 13 1325
广开言路
广开言路 2020-11-27 11:59

What\'s the shorthand for inserting a new record or updating if it exists?



        
相关标签:
13条回答
  • 2020-11-27 12:47

    like @JuanchoRamone posted above (thank @Juancho) it's very useful for me, but if your data is array you should modify a little like this:

    public static function createOrUpdate($data, $keys) {
        $record = self::where($keys)->first();
        if (is_null($record)) {
            return self::create($data);
        } else {
            return $record->update($data);
        }
    }
    
    0 讨论(0)
  • 2020-11-27 12:51
    $shopOwner = ShopMeta::firstOrNew(array('shopId' => $theID,'metadataKey' => 2001));
    

    Then make your changes and save. Note the firstOrNew doesn't do the insert if its not found, if you do need that then its firstOrCreate.

    0 讨论(0)
  • 2020-11-27 12:51

    Isn't this the same as updateOrCreate()?

    It is similar but not the same. The updateOrCreate() will only work for one row at a time which doesn't allow bulk insert. InsertOnDuplicateKey will work on many rows.

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

    0 讨论(0)
  • 2020-11-27 12:53

    2020 Update

    As in Laravel >= 5.3, if someone is still curious how to do so in easy way. Its possible by using : updateOrCreate().

    For example for asked question you can use something like:

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

    Above code will check the table represented by ShopMeta, which will be most likely shop_metas unless not defined otherwise in model itself

    and it will try to find entry with

    column shopId = $theID

    and

    column metadateKey = 2001

    and if it finds then it will update column shopOwner of found row to New One.

    If it finds more than one matching rows then it will update the very first row that means which has lowest primary id.

    If not found at all then it will insert a new row with :

    shopId = $theID,metadateKey = 2001 and shopOwner = New One

    Notice Check your model for $fillable and make sue that you have every column name defined there which you want to insert or update and rest columns have either default value or its id column auto incremented one.

    Otherwise it will throw error when executing above example:

    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))'
    

    As there would be some field which will need value while inserting new row and it will not be possible as either its not defined in $fillable or it doesnt have default value.

    For more reference please see Laravel Documentation at : https://laravel.com/docs/5.3/eloquent

    One example from there is:

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

    which pretty much clears everything.

    Query Builder Update

    Someone has asked if it is possible using Query Builder in Laravel. Here is reference for Query Builder from Laravel docs.

    Query Builder works exactly the same as Eloquent so anything which is true for Eloquent is true for Query Builder as well. So for this specific case, just use the same function with your query builder like so:

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

    Of course, don't forget to add DB facade:

    use Illuminate\Support\Facades\DB;
    

    OR

    use DB;
    

    I hope it helps

    0 讨论(0)
  • 2020-11-27 12:53

    Like the firstOrCreate method, updateOrCreate persists the model, so there's no need to call 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]
    );
    

    And for your issue

    $shopOwner = ShopMeta::updateOrCreate(
       ['shopId' => $theID, 'metadataKey' => '2001'],
       ['other field' => 'val' ,'other field' => 'val', ....]
    );
    
    0 讨论(0)
  • 2020-11-27 12:57

    Updated: Aug 27 2014 - [updateOrCreate Built into core...]

    Just in case people are still coming across this... I found out a few weeks after writing this, that this is in fact part of Laravel's Eloquent's core...

    Digging into Eloquent’s equivalent method(s). You can see here:

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

    Old Answer Below


    I am wondering if there is any built in L4 functionality for doing this in some way such as:

    $row = DB::table('table')->where('id', '=', $id)->first();
    // Fancy field => data assignments here
    $row->save();
    

    I did create this method a few weeks back...

    // 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;
    }
    

    I Hope that helps. I would love to see an alternative to this if anyone has one to share. @erikthedev_

    0 讨论(0)
提交回复
热议问题