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:
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.
Creating Users
Log on to the user
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