php 创建和更新 Laravel Eloquent

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18839941/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 18:18:06  来源:igfitidea点击:

Creating and Update Laravel Eloquent

phplaraveleloquentlaravel-query-builder

提问by 1myb

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

插入新记录或更新(如果存在)的简写是什么?

<?php

$shopOwner = ShopMeta::where('shopId', '=', $theID)
    ->where('metadataKey', '=', 2001)->first();

if ($shopOwner == null) {
    // Insert new record into database
} else {
    // Update the existing record
}

回答by weotch

Here's a full example of what "lu cip" was talking about:

这是“lu cip”所谈论的完整示例:

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

Below is the updated link of the docs which is on the latest version of Laravel

以下是最新版本的 Laravel 文档的更新链接

Docs here: Updated link

文档在这里:更新的链接

回答by Erik Aybar

Updated: Aug 27 2014 - [updateOrCreateBuilt into core...]

更新时间:2014 年 8 月 27 日 - [updateOrCreate内置于核心...]

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...

以防万一人们仍然遇到这个……我在写这篇文章几周后发现,这实际上是 Laravel 的 Eloquent 核心的一部分……

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

深入研究 Eloquent 的等效方法。你可以在这里看到:

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

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

on :570 and :553

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


Old Answer Below

下面的旧答案



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

我想知道是否有任何内置的 L4 功能可以以某种方式执行此操作,例如:

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

我希望这有帮助。如果有人可以分享,我很乐意看到替代方案。@erikthedev_

回答by Learner

2020 Update

2020 更新

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

就像在Laravel >= 5.3 中一样,如果有人仍然好奇如何以简单的方式做到这一点。它可能通过使用 : 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_metasunless not defined otherwise in model itself

上面的代码将检查由 ShopMeta 表示的表,shop_metas除非模型本身没有另外定义,否则很可能

and it will try to find entry with

它会尝试找到条目

column shopId = $theID

柱子 shopId = $theID

and

column metadateKey = 2001

柱子 metadateKey = 2001

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

如果找到,则将shopOwner找到的行的列更新为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.

如果它找到多个匹配的行,那么它将更新第一行,这意味着具有最低的 primary id

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

如果根本没有找到,那么它将插入一个新行:

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

shopId = $theIDmetadateKey = 2001shopOwner = New One

NoticeCheck your model for $fillableand 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 idcolumn auto incremented one.

请注意检查您的模型$fillable并确保您在其中定义了要插入或更新的每个列名称,其余列具有默认值或其id列自动增加一。

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 $fillableor it doesnt have default value.

因为在插入新行时会有一些字段需要值,并且不可能因为它没有定义$fillable或没有默认值。

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

如需更多参考,请参阅 Laravel 文档: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 .
// 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. Hereis reference for Query Builder from Laravel docs.

有人问是否可以在 Laravel 中使用 Query Builder。是 Laravel 文档中查询生成器的参考。

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:

Query Builder 的工作原理与 Eloquent 完全相同,因此任何适用于 Eloquent 的内容也适用于 Query Builder。因此,对于这种特定情况,只需对查询构建器使用相同的函数,如下所示:

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

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

当然,不要忘记添加DB Facade:

use Illuminate\Support\Facades\DB;

OR

或者

use DB;

I hope it helps

我希望它有帮助

回答by lu cip

Save function:

保存功能:

$shopOwner->save()

already do what you want...

已经做你想做的...

Laravel code:

拉维尔代码:

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

回答by Saeed Ansari

firstOrNewwill create record if not exist and updating a row if already exist. You can also use updateOrCreatehere is the full example

firstOrNew如果不存在则创建记录,如果已经存在则更新行。你也可以使用updateOrCreate这里是完整的例子

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

If there's a flight from Oakland to San Diego, set the price to $99. if not exist create new row

如果有从奥克兰飞往圣地亚哥的航班,请将价格设置为 99 美元。如果不存在创建新行

Reference Doc here: (https://laravel.com/docs/5.5/eloquent)

参考文档在这里:(https://laravel.com/docs/5.5/eloquent

回答by Sasa Blagojevic

If you need the same functionality using the DB, in Laravel >= 5.5you can use:

如果您需要使用DB, 在 Laravel>= 5.5中使用相同的功能,您可以使用:

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

or the shorthand version when $attributesand $valuesare the same:

或当$attributes$values相同时的简写版本:

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

回答by malhal

$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.

然后进行更改并保存。请注意,如果未找到,则 firstOrNew 不会执行插入,如果您确实需要,则它的 firstOrCreate。

回答by vivoconunxino

One more option if your id isn't autoincrement and you know which one to insert/update:

如果您的 id 不是自动增量并且您知道要插入/更新哪一个,则还有一种选择:

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

回答by Bashirpour

Like the firstOrCreate method, updateOrCreatepersists the model, so there's no need to call save()

与 firstOrCreate 方法一样,updateOrCreate将模型持久化,因此无需调用 save()

// If there's a flight from Oakland to San Diego, set the price to .
// 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', ....]
);

回答by Juancho Ramone

Actually firstOrCreatewould not updatein case that the register already exists in the DB. I improved a bit Erik's solution as I actually needed to update a table that has unique values not only for the column "id"

实际上,如果数据库中已存在寄存器,则firstOrCreate不会更新。我改进了一点 Erik 的解决方案,因为我实际上需要更新一个表,该表不仅针对“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);
    }
}

Then you'd use it like this:

然后你会像这样使用它:

Model::createOrUpdate(
        array(
    'id_a' => 1,
    'foo' => 'bar'
        ), array(
    'id_a' => 1
        )
);