User: profile
- In this section, we implement the functionality for a user to edit or update his profile (name and/or Email address)
Preparation
Create controller
- Create a new controller class ProfileController.php in the folder app/Http/Controllers/User
- Run the command
php artisan make:controller User/ProfileController
- Run the command
- Add the methods
edit()
andupdate()
to the controller- The Laravel helper function
back()
is used to redirect to the previous page (return back();
is equivalent toreturn redirect('user/profile');
)
- The Laravel helper function
class ProfileController extends Controller
{
// Edit user profile
public function edit()
{
return view('user.profile');
}
// Update user profile
public function update(Request $request)
{
// Validate $request
// Update user in the database and redirect to previous page
return back();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Basic view
- Make a basic view profile.blade.php inside the folder resources/views/user
- Open the file resources/views/user/profile.blade.php and update the view
- The file contains a form (partial and slightly adjusted copy of the contact form) and includes the shared alert sub-view to display feedback
@extends('layouts.template')
@section('title', 'Update profile')
@section('main')
<h1>Update profile</h1>
@include('shared.alert')
<form action="/user/profile" method="post">
@csrf
<div class="form-group">
<label for="name">Name</label>
<input type="text" name="name" id="name"
class="form-control @error('name') is-invalid @enderror"
placeholder="Your name"
value="{{ old('name') }}"
required>
@error('name')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" name="email" id="email"
class="form-control @error('email') is-invalid @enderror"
placeholder="Your email"
value="{{ old('email') }}"
required>
@error('email')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<button type="submit" class="btn btn-success">Update Profile</button>
</form>
@endsection
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
REMARK
By comparing with the contact form, it should be noticed that this time, the Blade directive @error
is used to check whether validation error messages exist
@error('name') is-invalid @enderror
is an alternative for$errors->first('name') ? 'is-invalid' : ''
to add the classis-invalid
to the name input field- The error message is displayed using
$message
within the@error('name')
directive as an alternative for$errors->first('name')
Add routes
- Open routes/web.php and add two new routes
- One GET route for showing the (update) form
- One POST route for updating the profile
- Protect these routes with the auth middleware and group them using the prefix user
- Add a fallback route for the root of the user URI (http://localhost:3000/user/ and http://localhost:3000/user)
Route::redirect('user', '/user/profile');
Route::middleware(['auth'])->prefix('user')->group(function () {
Route::get('profile', 'User\ProfileController@edit');
Route::post('profile', 'User\ProfileController@update');
});
1
2
3
4
5
2
3
4
5
Prefill the form
- Because it is an update form, it is logical that the fields are filled in in advance
- All you have to do is add the name and the email (of the logged in user) as a second/default parameter to the
old()
helper function
...
value="{{ old('name', auth()->user()->name ) }}"
...
value="{{ old('email', auth()->user()->email) }}"
...
1
2
3
4
5
2
3
4
5
Form validation
- Add (server-side) form validation to ProfileController.php
- The name is required
- The email is required and must be unique (in the table users)
- If the validation fails, the user will automatically be redirected to the previous page. Remember that the old values are automatically sent with this redirect, so there is no need for a
$request->flash()
statement. - If the validation is successful, the user will (also) be redirected back and a message is flashed to the session to be displayed on top of the page
public function update(Request $request)
{
// Validate $request
$this->validate($request,[
'name' => 'required',
'email' => 'required|email|unique:users'
]);
// Update user in the database and redirect to previous page
session()->flash('success', 'Your profile has been updated');
return back();
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
- Test the form by clicking on the button 'Update Profile' (don't change anything in text fields!)
- You'll get the error: The email has already been taken
Refactor the email validation
- The email validation works perfect when you add a new email address
- For updating the name of the (logged in) user the validation must also pass when the email was not changed
- In the original validation, the unique field only uses one parameter: the table (users) to look in
- Now we add three parameters to the unique field:
- The table to look in: users
- The table column we look at: email of the user
- The id of the current user (in our case
auth()->id()
), which should be excluded from the uniqueness test
- Update the email validation rule and test the form again
$this->validate($request,[
'name' => 'required',
'email' => 'required|email|unique:users,email,' . auth()->id()
]);
1
2
3
4
2
3
4
Update the database
- Find the logged in user by his id (
auth()->id()
) - Copy the name from the request to the name of the user
- Copy the email from the request to the email of the user
- Save (update) the new credentials by using the
save()
method in the controller
public function update(Request $request)
{
// Validate $request
$this->validate($request,[
'name' => 'required',
'email' => 'required|email|unique:users,email,' . auth()->id()
]);
// Update user in the database and redirect to previous page
$user = User::findOrFail(auth()->id());
$user->name = $request->name;
$user->email = $request->email;
$user->save();
session()->flash('success', 'Your profile has been updated');
return back();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
REMARK
- As you can see in the navigation, the auth session is automatically adjusted