php Laravel 无需两次查询即可创建或更新

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23315949/
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 16:38:21  来源:igfitidea点击:

Laravel create or update without two queries

phplaravellaravel-4

提问by mpen

I'm trying to use one form for both creates and updates. Both actions save through this method:

我正在尝试使用一种形式进行创建和更新。这两个操作都通过此方法保存:

public function store() {
    $data = Input::all();
    $data['company_id'] = Auth::user()->company_id;
    $validator = Validator::make($data, Feature::$rules);

    if($validator->fails()) {
        return Redirect::back()->withErrors($validator)->withInput();
    }

    Feature::firstOrNew(['id' => Input::get('id')])->update($data);

    return Redirect::route('features.index');
}

How can I rewrite this line:

我怎样才能重写这一行:

Feature::firstOrNew(['id' => Input::get('id')])->update($data);

So that it doesn't fetch the object from the database first? There's no need for that; I'm not doing anything with it. It should either issue a INSERTif Input::get('id')is set, or an UPDATEif it's not.

这样它就不会先从数据库中获取对象?没有这个必要;我不会用它做任何事情。它应该要么发出INSERTifInput::get('id')设置,要么发出if UPDATE

采纳答案by Vladislav Rastrusny

If you have all fields unguarded in your model, I think you can do it like this:

如果您的模型中的所有字段都不受保护,我认为您可以这样做:

$feature = new Feature($data);
$feature->exists = Input::has('id');
$feature->save();

If you have some guarded fields, then you can unguard it first:

如果你有一些受保护的字段,那么你可以先解除它:

$feature = new Feature();
$feature->unguard();
$feature->fill($data);
$feature->exists = Input::has('id');
$feature->reguard();
$feature->save();

The reguard()call is not actually needed if you don't do anything else with the model.

reguard(),如果你没有做任何其他与该模型实际上不需要调用。

回答by Keith Holliday

This is what I use:

这是我使用的:

Model::updateOrCreate(
   ['primary_key' => 8],
   ['field' => 'value', 'another_field' => 'another value']
);

The second parameter is an array of the data for the model you want to save.

第二个参数是要保存的模型的数据数组。

回答by yajra

I used to have this problem and created an accepted pull requeston Laravel which you can use. Try the code below. The method you will basically need is the findOrNew.

我曾经遇到过这个问题,并在 Laravel 上创建了一个可接受的拉取请求,您可以使用它。试试下面的代码。您基本上需要的方法是findOrNew.

public function store($id=0)
{
    $user = User::findOrNew($id);
    $data = Input::all();

    if (!$user->validate($data)) {
        return Redirect::back()->withInput()->withErrors($user->errors);
    }

    $user->fill($data);
    $user->save();
    return Redirect::to('/')->with('message','Record successfully saved!');
}

My model uses self validation but you can create your own validation like the one you have now.

我的模型使用自我验证,但您可以像现在一样创建自己的验证。

回答by Majbah Habib

Find or New based on primary key id

根据主键id查找或新建

$data = Input::all();
$user = User::findOrNew($id);  // if exist then update else insert
$user->name= $data['user_name'];
$user->save();

First or New based on non-primary key single filed

First 或 New 基于非主键单一归档

$user = User::firstOrNew(['field' => $data['value'] ]);
$user->name= $data['user_name'];
$user->save();

First or New based on non-primary key multiple filed

First 或 New 基于非主键多次归档

$user = User::firstOrNew([
                     'field1'=>$data['value1'],
                     'field2'=>$data['value2']
                     ]);
$user->name= $data['user_name'];
$user->save();

回答by peaceman

If you are following the resource router methodology of laravel, you should use a separate method named update to update your model, so the separation can be done by the framework. With this it is still possible to reuse your form.

如果你遵循 laravel 的资源路由方法,你应该使用一个名为 update 的单独方法来更新你的模型,这样分离可以由框架完成。有了这个,仍然可以重用您的表单。

If you really want to avoid a new method to update the model, you could rewrite it as follows:

如果你真的想避免更新模型的新方法,你可以按如下方式重写它:

public function store() {
    $model = Input::has('id')
        ? ModelClass::findOrFail(Input::get('id'))
        : new ModelClass;

    $inputData = Input::all();
    $validator = Validator::make($inputData, ModelClass::$rules);

    if ($validator->fails()) {
        return Redirect::back()
            ->withErrors($validator)
            ->withInput();
    }

    $model->fill($inputData);
    $model->save();

    return Redirect::route('modelclass.index');
}

回答by The Alpha

You may try this:

你可以试试这个:

$data = Input::except('_token');
$newOrUpdate = Input::has('id') ? true : false;
$isSaved = with(new Feature)->newInstance($data, $newOrUpdate)->save();

If $datacontains an id/primary keyit'll be updated otherwise insert will be performed. In other words, for updating, you need to pass the id/primary keyin the $data/attributeswith other attributes and second argument in the newInstancemethod must be true.

如果$data包含一个,id/primary key它将被更新,否则将执行插入。换句话说,用于更新,你需要通过id/primary key$data/attributes与其他属性,并在第二个参数newInstance的方法必须是true

If you pass false/defaultto newInstancemethod then it'll perform an insert but $datacan't contain an id/primarykey. You got the idea and these three lines of code should work. $isSavedwill be a Booleanvalue, true/false.

如果您传递false/defaultnewInstance方法,那么它将执行插入但$data不能包含id/primary键。你明白了,这三行代码应该可以工作。$isSaved将是一个Boolean值,true/false

You may write the code using one line:

您可以使用一行编写代码:

with(new Feature)->newInstance($data, array_key_exists('id', $data))->save();

If $datacontains id/primary keythen it'll be updated, otherwise an insert will be performed.

如果$data包含,id/primary key那么它将被更新,否则将执行插入。