In this post, we will be drawing out snippets required for implementing custom registration without scaffolding step by step. If you follow these steps implementation of this feature will be completed quickly.
Step 01: Setting up routes/web.php
Route::controller(RegisterController::class)->group(function () { Route::get('/', 'signup')->name('signup'); Route::post('/', 'store'); });
Step 02: Setting up RegisterController with validation
namespace App\Http\Controllers; use Illuminate\Http\Request; class RegisterController extends Controller { // public function signup() { return view('auth.register'); } public function store(Request $request) { //dd('in store'); $this->validate($request, [ 'username' => 'required|min:5|max:40|unique:users', 'name' => 'required|max:255', 'email' => 'required|email|max:255|unique:users', 'password' => 'required|min:5|max:20', ] ); } }
Step 03: Setting up layout app.blade.php under resource folder using bootstrap
<!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Laravel User Registration</title> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" /> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet" /> </head> <div class="app-body"> <main class="main"> <div style="padding-top: 20px" class="container"> <nav class="navbar navbar-expand-sm bg-dark navbar-dark"> <ul class="navbar-nav"> <li class="nav-item active"> <a class="nav-link" href="{{ route('signup') }}">Home</a> </li> <li class="nav-item"> <a class="nav-link" href="#">Dashboard</a> </li> </ul> </nav> <br> @yield('content') </div> </main> </div> </body> </html>
Step 04: Setting up flash messages in flash-messages.blade.php under resource folder
@if ($message = Session::get('success')) <div class="alert alert-success alert-block"> <button type="button" class="close" data-dismiss="alert">x</button> <strong>{{ $message }}</strong> </div> @endif @if ($message = Session::get('error')) <div class="alert alert-danger alert-block"> <button type="button" class="close" data-dismiss="alert">x</button> <strong>{{ $message }}</strong> </div> @endif @if ($message = Session::get('warning')) <div class="alert alert-warning alert-block"> <button type="button" class="close" data-dismiss="alert">x</button> <strong>{{ $message }}</strong> </div> @endif @if ($message = Session::get('info')) <div class="alert alert-info alert-block"> <button type="button" class="close" data-dismiss="alert">x</button> <strong>{{ $message }}</strong> </div> @endif @if ($errors->any()) <div class="alert alert-danger"> <button type="button" class="close" data-dismiss="alert">x</button> Check the following errors </div> @endif
Step 05: There will be two pages register and dashboard. Now setting up register.blade.php under resource/auth folder
@extends('app') @section('content') <div class="card"> @include('flash-message') <div class="card-header"> Site Registration </div> <div class="card-body"> <form method="post" action="{{ route('signup') }}" id="updatefrm" method="post" enctype="multipart/form-data"> @csrf <div class="form-group"> <div class="form-group"> <label for="title">Name</label> <br> <input name="name" class="form-control" placeholder="Firstname and Lastname" title="Full Name" maxlength="50" type="text" id="UserFirstname" value="{{ old('name') }}"/> @if ($errors->has('name')) <span class="text-danger">{{ $errors->first('name') }}</span> @endif </div> <label for="title">Username</label> <br> <input name="username" class="form-control" placeholder="Username, must be between 5 - 40 characters" title="Username" maxlength="25" type="text" id="UserUsername" value="{{ old('username') }}"/> @if ($errors->has('username')) <span class="text-danger">{{ $errors->first('username') }}</span> @endif </div> <div class="form-group"> <label for="title">Password</label> <br> <input name="password" class="form-control" placeholder="Password, must be between 5 - 20 characters" title="password" type="password" id="UserPassword" required="required"/> @if ($errors->has('password')) <span class="text-danger">{{ $errors->first('password') }}</span> @endif </div> <div class="form-group"> <label for="title">Email</label> <br> <input name="email" class="form-control" placeholder="Email, verification required" title="Email" maxlength="255" type="email" id="UserEmail" value="{{ old('email') }}"/> @if ($errors->has('email')) <span class="text-danger">{{ $errors->first('email') }}</span> @endif </div> <div class="form-group"> <label for="title">Gender</label> <br> <div class="ml-4"> <input type="radio" name="gender" checked value ="public" class="form-check-input mb-2"> Male <div class="mb-2"></div> <input type="radio" name="gender" value ="private" class="form-check-input"> Female </div> </div> <input class="btn btn-info" class="form-control" type="submit" name="action" value="Signup" > </form> </div> <br> </div> @endsection
Step 06: Now setting up dashboard.blade.php under resource/auth folder. This page will be redirected to once registration gets completed.
@extends('app') @section('content') <div class="card"> @include('flash-message') <div class="card-header"> Site Dashboard </div> <div class="card-body"> Welcome to Site dashboard </div> </div> @endsection
Step 07: Now setting up DashboardController.php
namespace App\Http\Controllers; use Illuminate\Http\Request; class DashboardController extends Controller { // function index () { return view('auth.dashboard'); } }
Step 08: Back in routes/web.php setting up route for DashboardController.php
Route::controller(DashboardController::class)->group(function () { Route::get('/dashboard', 'index')->name('dashboard'); });
Step 09: We are not finished with RegisterController.php yet. Going back to that controller to add user saving process into database. Also as soon as user is created in database we will attempt to login the user as well with either username or email
// at the top use Illuminate\Support\Facades\Hash; // User creation User::create([ 'username' => $request->username, 'name' => $request->name, 'email' => $request->email, 'password' => Hash::make($request->password), 'gender' => $request->gender, ]); // attempting to login after registration with either username or email $fieldType = filter_var($request->email, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; // login with either username or email and password if( !auth()->attempt(array( $fieldType => $request->$fieldType, 'password' => $request->password))) { return redirect()->route( 'signup' )->with('error', 'Invalid login details'); } // now redirecting to dashboard return redirect()->route('dashboard');
Step 10: If we submit the form now without error still user creation will not occur because we have not setup User.php model yet. We are going to do now. We need to add following changes in User.php
protected $fillable = [ 'username', 'name', 'gender', 'email', 'password', ];
Step 11: We also need to change user migration file which is given by default by laravel in database/migration folder. We need to add following change there and run php artisan migrate
public function up() { Schema::create('users', function (Blueprint $table) { $table->id(); $table->string('username'); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->string('gender', 50)->default('male'); $table->rememberToken(); $table->timestamps(); }); }
Step 12: Now if we fill up the form again and submit this time registration will get completed and page will be redirected to dashboard page. Notice we still have not auth protected our controllers ( RegisterController and DashboardController ). We are going to do now with laravel middleware() method putting inside __constructor() method following way
// In RegisterController public function __construct() { //$this->middleware(['guest']); $this->middleware( 'auth', ['except' => ['signup','store']] ); } // In DashboardController public function __construct() { //$this->middleware(['guest']); $this->middleware( 'auth' ); }
Step 13: Back in app.blade.php under resource controller we need to auth protect the links as well. We need to update our nav element like below with auth directive provided by laravel
<nav class="navbar navbar-expand-sm bg-dark navbar-dark"> <ul class="navbar-nav"> <li class="nav-item active"> <a class="nav-link" href="{{ route('signup') }}">Home</a> </li> @auth <li class="nav-item"> <a class="nav-link" href="{{ route('dashboard') }}">Dashboard</a> </li> <li class="nav-item"> <a class="nav-link" href="{{ route('logout') }}">Logout</a> </li> @endauth </ul> </nav>
Step 14: adding logout() method in RegisterController
public function logout() { auth()->logout(); return redirect('/'); }
Step 15: adding route for logout in routes/web.php inside RegisterController route group
Route::controller(RegisterController::class)->group(function () {
Route::get('/', 'signup')->name('signup');
Route::post('/', 'store');
Route::get('/logout', 'logout')->name('logout');
});
Step 16: It is an advanced step. If you want to make your controller cleaner you can move away your validation codes separately under app/Http/Requests folder. In this case for store method in RegisterController
we are creating StoreUserRequest.php under Requests folder and adding following snippet.
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreUserRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'username' => 'required|min:5|max:40|unique:users',
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:5|max:20',
'gender' => ''
];
}
}
Step 17: Back in RegisterController.php in parameter of store() method we need to change like below. Also we need to remove existing validation rules written inside store() method. So, updated store() method will be like below
// at the top use App\Http\Requests\StoreUserRequest; public function store(StoreUserRequest $request) { User::create([ 'username' => $request->username, 'name' => $request->name, 'email' => $request->email, 'password' => Hash::make($request->password), 'gender' => $request->gender, ]); $fieldType = filter_var($request->email, FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; //dd($input); // login with either username or email and password if( !auth()->attempt(array( $fieldType => $request->$fieldType, 'password' => $request->password))) { return redirect()->route( 'signup' )->with('error', 'Invalid login details'); } return redirect()->route('dashboard'); }