Laravel在没有两个查询的情况下创建或更新

时间:2014-04-26 20:08:30

标签: php laravel laravel-4

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

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

如何重写此行:

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

这样它首先不从数据库中获取对象?没有必要;我没有做任何事情。如果设置了INSERT,它应该发出Input::get('id'),如果不设置UPDATE则应该发出{{1}}。

6 个答案:

答案 0 :(得分:32)

这就是我使用的:

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

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

答案 1 :(得分:10)

如果您的模型中所有字段都没有防范,我认为您可以这样做:

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

如果你有一些守卫的田地,那么你可以先保护它:

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

如果您不对该模型执行任何其他操作,则实际上不需要reguard()来电。

答案 2 :(得分:6)

我曾经遇到过这个问题,并在Laravel上创建了一个可以使用的pull request。请尝试下面的代码。您基本上需要的方法是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!');
}

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

答案 3 :(得分:5)

根据主键 ID

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

基于非主键单一字段

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

基于非主键多字段

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

答案 4 :(得分:2)

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

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

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

答案 5 :(得分:2)

你可以试试这个:

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

如果$data包含id/primary key,则会更新,否则将执行插入操作。换句话说,要进行更新,您需要将id/primary key中的$data/attributes与其他属性一起传递,newInstance方法中的第二个参数必须为true

如果您将false/default传递给newInstance方法,则它会执行插入,但$data无法包含id/primary密钥。你有了这个想法,这三行代码应该可行。 $isSaved值为Booleantrue/false

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

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

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