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
  • Add the methods edit() and update() to the controller
    • The Laravel helper function back() is used to redirect to the previous page (return back(); is equivalent to return redirect('user/profile');)
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

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

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 class is-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

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

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
  • 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

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:
      1. The table to look in: users
      2. The table column we look at: email of the user
      3. 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

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

Auth session

REMARK

  • As you can see in the navigation, the auth session is automatically adjusted
Last Updated: 11/19/2019, 12:37:08 PM