Specifying Middleware Within Controller's Constructor - laravel

Here's a code snippet from laravel in-built RegisterController.
public function __construct(){
$this->middleware('guest'); //What does it actually do?
}
I know that it's a good practice to define middleware in the
controller constructor but I need to know what
$this->middleware('guest') actually does and what parameter (where
?) it sets.
Second question: within the same controller (RegisterController), we use RegisterUser (defined in namespace Illuminate\Foundation\Auth) but it seems we never use it throughout the controller (overriding methods or attributes). I'm a little bit confused. Thnaks in advance!
class RegisterController extends Controller
{
use RegistersUsers; //?????
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
}

1) $this->middleware(...) called in a constructor of a controller is only adding what ever value is in ... to an array named middleware on the controller. That is it at that point. Nothing is "ran" at that point. You can see this functionality in the Controller your Controllers extend from, Illuminate\Routing\Controller.
Later when the Router needs to dispatch the Request it will build a middleware stack to pass the request through by gathering the middleware which includes asking the instance of the controller for its defined middleware via getMiddleware.
public function getMiddleware()
{
return $this->middleware;
}
2) The trait is including functionality and variables into your controller. There are routes pointing to some of these methods on the controller.
You could take all that code and paste it into your controller and it would be the same thing basically.
If you need to change any functionality of that controller or customize it you will end up redefining some of those methods or adjusting the variables.

Related

Argument 1 passed to Laravel 6

I want to register on my site with an invitation code, so I added in my controller If statement for checking the activation code
protected function create (array $data)
{
if ($data['activation_code'] === 'mypassword123') {
return User::create([
'name' => $data['name'],
'lastname' => $data['lastname'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
return redirect('/register')->with('message', 'De activatiecode is onjuist');
}
}
And when I submit the registration I get this error
Argument 1 passed to Illuminate\Auth\SessionGuard::login() must be an instance of Illuminate\Contracts\Auth\Authenticatable, instance of Illuminate\Http\RedirectResponse given, called in C:\xampp\htdocs\Suppliers\vendor\laravel\framework\src\Illuminate\Foundation\Auth\RegistersUsers.php on line 35
So I don't know where the problem is, please help
Like the comment said protected function create (array $data) is not responsible for redirecting to a different page and the logic, I think, should not be there either.
you can either overwrite the register method from trait RegistersUsers or create a middleware.
overriding register method, in RegisterController add the logic here.
/**
* Handle a registration request for the application.
*
* #return \Illuminate\Http\Response
*/
public function register(Request $request)
{
if ('mypassword123' !== $request->input('activation_code')) {
return redirect('/register')->with('message', 'De activatiecode is onjuist');
}
$this->validator($request->all())->validate();
event(new Registered($user = $this->create($request->all())));
$this->guard()->login($user);
return $this->registered($request, $user)
?: redirect($this->redirectPath());
}
Middleware
<?php
namespace App\Http\Middleware;
use Closure;
class CheckCode
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
*
* #return mixed
*/
public function handle($request, Closure $next)
{
if ('mypassword123' !== $request->input('activation_code')) {
return redirect('/register')->with('message', 'De activatiecode is onjuist');
}
return $next($request);
}
}
And then add it when you need it.
use App\Http\Middleware\CheckAge;
Route::get('someroutes', function () {
//some code
})->middleware(CheckCode::class);
Hope this helps.

How do I fix the Laravel page not found error?

After registering, it redirects to / home. But I get a 404 error. When I set the route to / home, I get 302 continuous routing errors.
RegisterController.php
use RegistersUsers;
protected $redirectTo = '/';
public function __construct()
{
$this->middleware('guest');
}
Route.php
Auth::routes(['verify' => true]);
Route::get('/', 'HomeController#index')->name('home');
HomeController
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Show the application dashboard.
*
* #return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
return view('home');
}
}
if you have in your HomeController's construct a middleware that requires the user to be logged in then what you are getting is normal.
You should have a login page wich use the "guest" middleware.
or
login the user automatically once he registers before redirecting him to your home route.
Auth::login($user)
//or
Auth::loginUsingId($userId);
Remove guest middleware.
public function __construct()
{
$this->middleware('guest');
}
Your HomeController should look like
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* #return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
return view('home');
}
}
your route.php Look like
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/home', 'HomeController#index')->name('home');
RegisterController should look like
namespace App\Http\Controllers\Auth;
use App\User;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
}
make sure you're following laravel authentication.

Change login rules at Laravel 5.6

I have a fresh project of Laravel 5.6 installed. I changed create_users_migration, added $table->boolean('is_active'); field. Now, I want when user is trying to login, to check if is_active field is set to true.
I tried to rewrite standard AuthenticatesUsers method :
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required|string',
'password' => 'required|string',
]);
}
After password I added line 'is_active' => true, , and now, when I press Log In button, it returns me an array_map(): Argument #2 should be an array error.
I tried to just copy-paste this method in LoginController, but it gives me same error. Any ideas, or may be is here another solution?
Full LoginController code :
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = '/';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
/**
* Validate the user login request.
*
* #param \Illuminate\Http\Request $request
* #return void
*/
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required|string',
'password' => 'required|string',
'is_active' => true,
]);
}
}
You are editing the wrong method. This method validates the request and "true" is not a validation rule, that's why you are getting the error.
Here is a simple solution. Override the credentials method on your LoginController as below.
protected function credentials(Request $request)
{
$data = $request->only($this->username(), 'password');
$data['is_active'] = true;
return $data;
}
So this way only active users can login.
You can also create a middleware and use it to send the users that have not activated their account to activation page.
I did this for one project with a middleware :
<?php
namespace App\Http\Middleware;
use Closure;
class isActiv
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if($request->user()->isActiv()){
return $next($request);
}else{
return redirect()->route('dashboard')->with('errors', 'Votre compte utilisateur n\'est pas activé sur le site. Veuillez contacter un administrateur pour résoudre le problème.');
}
}
}
Then in my route file web.php :
Route::group(['middleware' => ['isActiv'] ], function(){
And in my user model :
public function isActiv(){
if($this->is_activ == 1 || $this->is_admin == 1){
return true;
}
return false;
}

Laravel Custom Registration Route/Logic

I would like to overwrite Laravel 5.2's public function postRegister() in my Auth controller.
I start by changing the route:
Route::post('/auth/register', 'Auth\AuthController#postRegisterI');
In my Auth controller, I now have this new postRegisterI() method as oppose to relying on the foundational postRegister(). But my changes in this new method don't seem to apply?
Is it still pointing to postRegister() for some reason? My AuthController looks like this:
class AuthController extends Controller
{
/*
|--------------------------------------------------------------------------
| Registration & Login Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users, as well as the
| authentication of existing users. By default, this controller uses
| a simple trait to add these behaviors. Why don't you explore it?
|
*/
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
/**
* Create a new authentication controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest', ['except' => 'getLogout']);
}
public function postRegisterI(Request $request)
{
return print_r($request);
$validator = $this->validator($request->all());
if ($validator->fails()) {
$this->throwValidationException(
$request, $validator
);
}
//Auth::login($this->create($request->all()));
$this->create($request->all());
//return redirect($this->redirectPath());
return;
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|max:255|unique:users',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|confirmed|min:2',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
}
}
For example in my ajax requests to /auth/register/ it never echoes out my returns as I indicate and it also keeps trying to redirect me to /home. I'm doing this because instead of passing /auth/register a form, I'm passing it a Javascript array with data to not only create a user (email, password, etc) but also an application that the user needs to join.
Eventually, I would like to create the Application model with that data right when the User is created, but right now I'm not sure that my function is even being called correctly!
EDIT: So, it looks like the __construct() function is causing the issue... should I get rid of it? I don't understand why I need to comment that out to get my returns from postRegisterI()?
First, make sure that your new route is declared before the call to Route::auth(). Otherwise, Laravel will ignore your addition, and will always call the one that Easy Auth comes with.
Second. Why do you want to override a method using another method with a different name? By simply creating a method postRegister in your AuthController you are automatically overriding the method that resides in the Trait. So you shouldn't be worrying about having to add an additional method and route. Unless you want to have a multi-authentication system, and in this case, this wouldn't be the correct solution.
Another thing, for ajax request, make sure you validate that the request is of type ajax:
if ($request->ajax()){
//Code here
return response()->json([],200);
}
This controller is designed to check registration rules, create an user, and redirect to the redirection path. It is not designed for ajax handling, thus, you will need to add code for it
maybe this topic will help you custom register

Laravel 5.1 FatalErrorException in RegistersUsers.php line 32

since a few time I started programming in Laravel for a schoolproject. Now I tried to implement a login system. My database for userinformation is running on my homestead virtual machine, running with Postgresql. I already migrated the tables, so they exist and the database is running. Problem is: When I fill in the registrationform and send it, I get an error:
FatalErrorException in RegistersUsers.php line 32: Call to a member function fails() on null
You can see the code of RegistersUsers.php underneath:
<?php
namespace Illuminate\Foundation\Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
trait RegistersUsers
{
use RedirectsUsers;
/**
* Show the application registration form.
*
* #return \Illuminate\Http\Response
*/
public function getRegister()
{
return view('auth.register');
}
/**
* Handle a registration request for the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function postRegister(Request $request)
{
$validator = $this->validator($request->all());
if ($validator->fails()) {
$this->throwValidationException(
$request, $validator
);
}
Auth::login($this->create($request->all()));
return redirect($this->redirectPath());
}
}
When I try to log in it gives the warning the log in credentials doesn't exist in the database (because I haven't registered yet), so it seems that the database connection works properly.
Does someone know a solution for this?
----UPDATE----
Underneath I added my AuthController is included. You can also see my project on my github, so you can look into my other files if needed: https://github.com/RobbieBakker/LaravelProject56
class AuthController extends Controller
{
/*
|--------------------------------------------------------------------------
| Registration & Login Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users, as well as the
| authentication of existing users. By default, this controller uses
| a simple trait to add these behaviors. Why don't you explore it?
|
*/
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
private $redirectTo = '/';
/**
* Create a new authentication controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest', ['except' => 'getLogout']);
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
$validator = Validator::make($data, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|confirmed|min:6',
]);
if(!$validator->fails())
{
session(['email' => $data['email']]);
}
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
}
}
I eventually solved it just by commenting the function which called this error. I'm not sure if it's supposed to be solved like that, but my login system seems to work fine now.
Thanks for your support!
You forgot return validator instance from your validator function ))
protected function validator(array $data)
{
$validator = Validator::make($data, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|confirmed|min:6',
]);
if(!$validator->fails())
{
session(['email' => $data['email']]);
}
return $validator;
}
I had same error )
I think you need to "make" the validator.
try changing it to this..
$validator = $this->validator->make($request->all(), $rules);
see if that works...

Resources