177

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

<?php

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

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

14 回答 14

246

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

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

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

此处的文档:更新的链接

于 2014-01-09T00:23:52.613 回答
90

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

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

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

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

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

下面的旧答案


我想知道是否有任何内置的 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_

于 2013-12-24T16:52:23.060 回答
90

2020 更新

就像在Laravel >= 5.3中一样,如果有人仍然好奇如何以简单的方式做到这一点,可以使用:updateOrCreate().

例如对于提出的问题,您可以使用以下内容:

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

shop_metas上面的代码将检查 ShopMeta 表示的表,除非模型本身没有另外定义,否则很可能会出现这种情况。

它会尝试使用

柱子shopId = $theID

柱子metadateKey = 2001

如果找到,则将shopOwner找到的行的列更新为New One.

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

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

shopId = $theID,metadateKey = 2001shopOwner = 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 中使用查询生成器。是 Laravel 文档中查询生成器的参考。

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;

或者

use DB;
于 2016-12-23T08:51:00.283 回答
20

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

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

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

此处参考文档:(https://laravel.com/docs/5.5/eloquent

于 2018-02-04T09:24:26.277 回答
18

保存功能:

$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);
    }
于 2013-09-17T09:26:35.380 回答
7

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

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

或当$attributes$values相同时的速记版本:

DB::table('table_name')->updateOrInsert($values);
于 2018-09-09T15:31:38.157 回答
6
$shopOwner = ShopMeta::firstOrNew(array('shopId' => $theID,'metadataKey' => 2001));

然后进行更改并保存。请注意,如果未找到 firstOrNew,则不会执行插入操作,如果确实需要,则使用其 firstOrCreate。

于 2014-08-24T11:59:54.947 回答
4

与 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', ....]
);
于 2018-03-30T14:05:55.773 回答
2

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

$object = MyModel::findOrNew($id);
//assign attributes to update...
$object->save();
于 2017-08-16T10:59:14.483 回答
1

实际上,如果数据库中已经存在寄存器,则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);
    }
}

然后你会像这样使用它:

Model::createOrUpdate(
        array(
    'id_a' => 1,
    'foo' => 'bar'
        ), array(
    'id_a' => 1
        )
);
于 2014-08-25T14:14:01.100 回答
1

就像上面发布的@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);
    }
}
于 2016-07-04T23:59:23.627 回答
0

这不是和updateOrCreate() 一样吗?

它相似但不一样。updateOrCreate() 一次只能处理一行,不允许批量插入。InsertOnDuplicateKey 将适用于许多行。

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

于 2018-05-24T11:42:04.467 回答
0

尝试更多参数,这些参数肯定会找到,如果可用更新而不是那么它将创建新的

$save_data= Model::firstOrNew(['key1' => $key1value,'key'=>$key2value]);
//your values here
$save_data->save();
于 2021-02-18T11:50:37.377 回答
-2

检查用户是否存在。如果不插入

$exist = DB::table('User')->where(['username'=>$username,'password'=>$password])->get();
if(count($exist)  >0) {
    echo "User already exist";;
}
else  {
    $data=array('username'=>$username,'password'=>$password);
    DB::table('User')->insert($data);
}
Laravel 5.4           
于 2017-04-24T10:14:24.047 回答