Francisunoxx Francisunoxx - 5 months ago 9
PHP Question

Save method won't update models that already exist in the DB

I retrieve properly the records in my DB and print out the values in textfield. But when I want to update my database it won't work. It says in the documentation that


save()
method may also be used to update models that already exist
in the database. To update a model, you should retrieve it.


So I have two blade template show and edit. First blade show the value exist in the database (GET REQUEST). Second blade show the edit form for the user to update data. (POST REQUEST).

show.blade.php

<form class = "form-vertical" role = "form" method = "post" action = "{{ route ('account.show', $result->id) }}">

<h3>View Employee</h3>
<hr>

<div class = "form-group">

<label for = "email" class = "control-label">Email Address</label>
<input type = "text" name = "email" class = "form-control" placeholder = "{{ $result->email }}" readonly>

</div>

<div class = "form-group">

<label for = "username" class = "control-label">Username</label>
<input type = "text" name = "username" class = "form-control" placeholder = "{{ $result->username }}" readonly>

</div>

<input type = "hidden" name = "_token" value = "{{ Session::token() }}">

</form>


edit.blade.php

<form class = "form-vertical" role = "form" method = "post" action = "{{ route ('account.edit', $result->id) }}">

<h3>Edit Employee</h3>
<hr>

<div class = "form-group">

<label for = "email" class = "control-label">Email Address</label>
<input type = "text" name = "email" class = "form-control" value = "{{ $result->email }}">

</div>

<div class = "form-group">

<label for = "username" class = "control-label">Username</label>
<input type = "text" name = "username" class = "form-control" value = "{{ $result->username }}">

</div>

<div class = "form-group">

<button type = "submit" class = "btn btn-success">Save</button>

</div>

<input type = "hidden" name = "_token" value = "{{ Session::token() }}">

</form>


Controller:

//SHOW
public function showEmployee($id)
{
$result = User::find($id);

//key //value
return view ('account.show')->with('result', $result);
}

//EDIT
public function editEmployee($id)
{

$result = User::find($id);

return view ('account.edit')->with('result', $result);
}

//UPDATE
public function updateEmployee(Request $request, $id)
{
$this->validate($request, [
//This will be unique in users table
'email' => 'required|unique:users,email,'.$id.'|email|max:255',
'username' => 'required|unique:users,username,'.$id.'|alpha|max:20',
]);

$email = $request['email'];
$username = $request['username'];

$user = User::findOrFail($id);
$user->email = $email; //Accessing properties of Model
$user->username = $username;

$user->save();

return view ('account.show');
}


Routes:

//SHOW
Route::get('/show/{id}',
[
'uses' => '\App\Http\Controllers\AccountController@showEmployee',
'as' => 'account.show',
]);

//EDIT
Route::get('/edit/{id}',
[
'uses' => '\App\Http\Controllers\AccountController@editEmployee',
'as' => 'account.edit',
]);


//UPDATE
Route::post('/edit/{id}',
[
'uses' => '\App\Http\Controllers\AccountController@updateEmployee',
'as' => 'account.edit',
]);

Answer

You are creating a new User here.

To update the existing data, you need to first load the user data you want to edit. You can do this and fix that problem by changing

$user = new User();

to

$user = User::findOrFail($id); 

(Assuming $id is the id of that user here)

Moreover, your validation will fail here if both the username and email are not changed since you're checking for the uniqueness of both entries and the current user will already have that username or email.

To fix this, you need to exclude the current user from the check through something like this for the validation,

  'email' => 'required|unique:users,email,'.$id.'|email|max:255',
  'username' => 'required|unique:users,username,'.$id.'|alpha|max:20',

For more information, see 'Forcing a unique rule to ignore a given id' in the documentation here - Validation - unique rule

Comments