Only update field if form value exists

2020-07-02 12:14发布

I'm using Form Model Binding as such and updating my DB using the fill() and save() methods.

{{ Form::model($account) }}
  {{ Form::text('name', null, array('class'=>'class')) }}
  {{ Form::text('email', null, array('class'=>'class')) }}
  {{ Form::password('password', array('class'=>'class')) }}
  {{ Form::password('password_confirmation', array('class'=>'class')) }}
{{ Form::close() }}

Which fires my editAccount controller method:

$rules = array(
  'name' => array('required'),
  'email' => array('required'),
  'password' => array('confirmed')
);

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

if ($validator->fails())
{
 // Redirect
}

// Save to DB
$account->fill(Input::all());
$account->save();

Which works fine, but if no password was supplied (because the user doesn't want to update/modify it) then the password field is set to null in the db. So, I only want the password field to update if a new password value is supplied via the form.

I know I can do the following:

// Set the fields manually
$account->name = Input::get('name');
$account->email = Input::get('email');

// Only update the password field if a value is supplied
if (Input::get('password')) {
    $account->password = Input::get('password');
}
$account->save();

However I'm wondering if there is a more cleaner way to handle this? Like an UpdateOnlyIfValueExists() method within Laravel/Eloquent.

8条回答
We Are One
2楼-- · 2020-07-02 12:46

Create Base model and override update function like

/**
 * @param array $attributes
 * @return mixed
 */
public function update(Array $attributes = array()){
    foreach($attributes as $key => $value){
        if(!is_null($value)) $this->{$key} = $value;
    }
    return $this->save();
}

After use:

$model = Model::find($id);
$model->update(Input::only('param1', 'param2', 'param3'));
查看更多
Summer. ? 凉城
3楼-- · 2020-07-02 12:48

Check this, you can validate if password is present in input, and exclude it from mass assignment. You can use Input::except and Input::only for this purpose

public function update ($id) {
    $user = User::findOrFail ($id);
    if (Input::get ('password') == '') {
        $user->update (Input::except ('password'));
    }
    else {
        $user->update (Input::all ());
    }

    //return something
}
查看更多
祖国的老花朵
4楼-- · 2020-07-02 12:49
$data = $request->password ? $request->all():$request->except('password');
$user->update($data);

This will only update the password if it's not null

查看更多
虎瘦雄心在
5楼-- · 2020-07-02 12:52

I would stick with your latter example. Another option would be to use a mutator which checks the value there, and doesn't update if the value is empty. But in my opinion, Eloquent should not be responsible for doing that.

I'd also avoid using ALL input with fill(). Choose only what you want.

查看更多
闹够了就滚
6楼-- · 2020-07-02 12:59

Using Input::only('foo', 'bar') will grab only the values needed to complete the request - instead of using Input::all().

However, if 'foo' or 'bar' doesn't exist within the input, the key will exist with the value of null:

$input = Input::only('foo', 'bar');
var_dump($input);

// Outputs
array (size=2)
  'foo' => null
  'bar' => null

To filter in a clean way, any values with a null value:

$input = array_filter($input, 'strlen');

In your example, this would replace: $account->fill(Input::all());

查看更多
萌系小妹纸
7楼-- · 2020-07-02 13:00

A much cleaner approach would be to use Eloquent Mutators

Under no circumstances would you allow a null or an empty string as password so you can safely define the following mutator in your Account model.

// Only accept a valid password and 
// hash a password before saving
public function setPasswordAttribute($password)
{
    if ( $password !== null & $password === '' )
    {
        $this->attributes['password'] = bcrypt($password);
    }
}

The above mutator will only set a password attribute if it is not null and an empty string. It also hashes the password before saving so you do not need to do it in your controller action or application elsewhere.

查看更多
登录 后发表回答