9. Registration and login, User Association

This section will implement the functions of registration and login; articles, comments and user association.

Relational Definition

First, modify the posts and comments table to add the user_id field

/database/migrations/2017_04_12_124622_create_posts_table.php
/database/migrations/2017_04_15_062905_create_comments_table.php
public function up()
{
    Schema::create('posts', function (Blueprint $table) {
         
           // increase
        $table->integer('user_id')->unsigned();
     
        $table->foreign('user_id')
              ->references('id')
              ->on('users')
              ->onDelete('cascade');
    });
}

Roll back all and re-execute the migration:

$ php artisan migrate:refresh

Add a one-to-many relationship between user table, article table and comment table:

/app/User.php
public function posts()
{
    return $this->hasMany(\App\Post::class);
}

public function comments()
{
    return $this->hasMany(\App\Comment::class);
}

Add many-to-one relationships between articles, comment tables and user tables:

/app/Comment.php
/app/Post.php
public function user()
{
    return $this->belongsTo(\App\User::class);
}

register

Firstly, a controller for registering related business is defined:

$ php artisan make:controller RegistrationController

Define routing to respond to registration requests:

Route::get('/register','RegistrationController@create');

Define the method and return to the registration page view:

public function create()
{
    return view('registration.create');
}

Create a registration page:

/resources/views/registration/create.blade.php
@extends('layouts.master')

@section('content')
    
    <div class="col-sm-8 blog-main">
        
        <form method="post" for="/register"> 
            {{ csrf_field() }}
            <fieldset class="form-group">
                <label for="name">User name:</label>
                <input type="text" name="name" id="name" class="form-control" required>
            </fieldset>
            <fieldset class="form-group">
                <label for="email">mailbox</label>
                <input type="email" class="form-control" name="email" id="email" required>
                <small class="text-muted">We will not share your email with others.</small>
            </fieldset>
            <fieldset class="form-group">
                <label for="password">Password:</label>
                <input type="password" name="password" class="form-control" id="password" >
            </fieldset>    
            <fieldset class="form-group">
                <label for="password_confirmation">Enter the password again:</label>
                <input type="password" name="password_confirmation" class="form-control" id="password_confirmation">
            </fieldset>    
            <button type="submit" class="btn btn-primary">Submission</button>
        </form>

    </div>

@endsection

Define routing response registration submission:

Route::post('/register','RegistrationController@store');

Define methods to handle registration submissions:

/app/Http/Controllers/RegistrationController.php
use App\User;
public function store()
{    
    $this->validate(request(),[
        'name' => 'required',
        'email' => 'required|email',
        'password' => 'required|confirmed',
    ]);

    $user = User::create(request(['name','password','email']));

    auth()->login($user);

    return redirect()->home();
}

The method consists of four parts:

  1. Validation fields, where password uses confirmed validation rules, automatically match whether XXX is consistent with xxx_confirmation, so the previous view should be named according to the specification.

  2. Creating Users

  3. Log on to the user

  4. Return the route with the name "home"

Among them, we need to name the route to match the fourth step:

Route::get('/posts','PostsController@index')->name('home');

Although we have completed the registration function, we can save the plaintext used by the password. We can define a modifier to automatically encrypt every time we save the password:

/app/User.php
public function setPasswordAttribute($password)
{
    $this->attributes['password'] = bcrypt($password);
}

Sign in

Create a controller to handle user login business:

$ php artisan make:controller SessionsController

When the user accesses/login, the routing distributes the request:

Route::get('/login','SessionsController@create');

The create method returns the user login page view:

/resources/views/sessions/create.blade.php
@extends('layouts.master')

@section('content')
    
    <div class="col-sm-8 blog-main">
        
        <form method="post" for="/login"> 
            {{ csrf_field() }}
            <fieldset class="form-group">
                <label for="email">mailbox</label>
                <input type="email" class="form-control" name="email" id="email" required>
            </fieldset>
            <fieldset class="form-group">
                <label for="password">Password:</label>
                <input type="password" name="password" class="form-control" id="password" >
            </fieldset>    
            <button type="submit" class="btn btn-primary">Sign in</button>
        </form>

    </div>

@endsection

After the user clicks on the login, the routing distributes the request:

Route::post('/login','SessionsController@store');

Finally, the controller processes the login behavior:

/app/Http/Controllers/SessionsController.php
public function store()
{    

    if (!auth()->attempt(request(['email', 'password']))) {
        return back()->withErrors([
            'messages' => 'Make sure your email and password are correct!'
        ]);
    }

    return redirect()->home();
} 

We use the attempt() provided by the Auth class to verify it. We just need to pass in email and password. The attempt method compares the password encrypted with the database if matched.
Open an authenticated session to the user. At the same time, we also customized the error information returned.

Logout

Log-out implementation is relatively simple, first of all, routing:

Route::get('/logout','SessionsController@destroy');

Controller:

public function destroy()
{
    auth()->logout();

    return redirect()->home();
}

Finally, we optimize the navigation let to display different settings according to user login information:

<div class="blog-masthead">
  <div class="container">
    <nav class="nav blog-nav">
      <a class="nav-link active" href="#">Home</a>
      <a class="nav-link" href="#">New features</a>
      <a class="nav-link" href="#">Press</a>
      <a class="nav-link" href="#">New hires</a>
      <a class="nav-link" href="#">About</a>
      
      <ul class="nav nav-tabs ml-auto">
        <li class="nav-item dropdown">
            <a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#"Role=" button "aria-haspopup=" true "aria-expanded=" false "> setting</a>
            <div class="dropdown-menu">
                @if (Auth::check())
                    <a class="dropdown-item" href="#">{{ Auth::user()->name }}</a>
                    <a class="dropdown-item" href="/logout">Logout</a>
                @else
                    <a class="dropdown-item" href="/login">Sign in</a>
                    <a class="dropdown-item" href="/register">register</a>
                @endif

            </div>
        </li>
    </ul>

    </nav>
  </div>
</div>

<script type="text/javascript">
    $('.dropdown-toggle').dropdown()
</script>

Note that if you want the drop-down box to take effect, you need to introduce the relevant js:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/js/bootstrap.js"></script>

Privilege control

The functions of login and logout are realized, and the user's behavior can be controlled by privileges.

First, the access control of articles. For "unregistered" users, they can only read articles, so they can directly use the middleware provided by Laravel to achieve:

public function __construct()
{
    $this->middleware('auth')->except(['index','show']);
}

This means that only authorized users can access other requests except index and show.

Then the user's rights are controlled:

/app/Http/Controllers/SessionsController.php
public function __construct()
{
    $this->middleware('guest')->except(['destroy']);
}

This means that only visitors can access other requests except destroy.

Perfecting the Creation of Articles and Comments

Finally, we improve the creation function of articles and comments and bind user id. The first is the creation of the article:

/app/Http/Controllers/PostsController.php
public function store(Request $request)
{
    $this->validate(request(), [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required|min:5',
    ]);

    $post = new Post(request(['title', 'body']));

    auth()->user()->publishPost($post);

    return redirect("posts");
}

Create articles directly using the relational model:

/app/Post.php
public function addComment(Comment $comment)
{    
    $this->comments()->save($comment);
}

Then the creation of comments:

public function store(Post $post)
{    
    $this->validate(request(),[
        'body' => 'required|min:5'
        ]);

    $post->addComment(new Comment([
        'user_id' => auth()->user()->id,
        'body'       => request('body'),

        ]));
    return back();
}

Similarly, the relational model is used:

/app/Post.php
public function addComment(Comment $comment)
{    
    $this->comments()->save($comment);
}

Finally, some views are updated:

In the list of articles, bind authors:

/resources/views/posts/index.blade.php
 <p class="blog-post-meta">{{ $post->created_at->toFormattedDateString() }} by <a href="#">{{$post->user->name}}</a></p>

When specific articles and comments are displayed, authors are also bound:

/resources/views/posts/show.blade.php
<div class="blog-post">
    <h2 class="blog-post-title">{{ $post->title }}</h2>
    <p class="blog-post-meta">{{ $post->created_at->toFormattedDateString() }} by <a href="#">{{ $post->user->name }}</a></p>
    <p>{{$post->body}}</p>
 </div>

 @foreach ($post->comments as $comment)
    <div class="card">
        <div class="card-header">
            {{$comment->created_at->diffForHumans() }}
        </div>
        <div class="card-block">
            <p class="card-text">{{ $comment->body }}</p>
             <p class="card-text"><small class="text-muted">by {{$comment->user->name }}</small></p>
         </div>
    </div>

    <br>
@endforeach

Keywords: PHP Laravel Database JQuery

Added by chris270 on Tue, 09 Jul 2019 03:50:10 +0300