I am a home hobbyist and am studying Laravel, currently in version 5.3
. I am using a Mac, neither homestead
nor vagrant
.
I'm currently working on a website that uses a login and a register system to create users.
I've used php artisan migrate
to manipulate my database locally.
As listed below, it has three fields, namely:
- Username
- Password
I have a User
model (users.php):
<?php
namespace blog;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Auth\Authenticatable;
class User extends Model implements Authenticatable {
use \Illuminate\Auth\Authenticatable;
use Notifiable;
protected $fillable = [
'username', 'email', 'password',
];
}
And also, a UserController
class (UserController.php):
<?php
namespace blog\Http\Controllers;
use Auth;
use blog\User;
use Illuminate\Http\Request;
class UserController extends Controller {
public function postRegister(Request $request) {
$username = $request['username'];
$email = $request['email'];
$password = bcrypt($request['password']);
$user = new User();
$user->email = $email;
$user->username = $username;
$user->password = $password;
$user->save();
return redirect()->route('login');
}
public function postLogin(Request $request) {
$credentials = [
'username' => $request['username'],
'password' => $request['password'],
];
if(Auth::attempt($credentials)) {
return redirect()->route('dashboard');
}
return 'Failure';
}
}
?>
As you can see, I am using bcrypt()
as my hashing method.
However, this problem is, it will always result to a failure.
I have checked the following links:
P.S. These links seem very hard to follow as I do not utilize the Input
class.
Best Answer
The problem is with the way you're redirecting the user to
login
route after the registration. You're falsely assuming that the$request
data will be accompanied with the redirect.Let's assume this scenario: A request gets dispatched to the
postRegister
method withname
,email
andpassword
fields. The controller creates the user and saves it into the database. Then it redirects the user, who is not yet authenticated, to thelogin
route. ThepostLogin
method gets triggered, but this time with no request data. As a result,Auth::attempt($credentials)
fails and you get that nastyFailure
on screen.If you add a
dd($credentials)
right after you create the array, you'll see that it has no values:It will return something like this:
You cannot redirect with custom request data (unless with querystring which is part of the URL), not matter what. It's not how HTTP works. Request data aside, you can't even redirect with custom headers.
Now that you know what's the root of your problem, let's see what are the options to fix it.
1. Redirect with flashed data
In case you want to preserve this structure, you need to flash the request data of
postRegister()
into the session (which is persistent between requests) and then retrieve it in thepostLogin()
method usingSession
facade,session()
helper or the actualIlluminate\Session\SessionManager
class.Here's what I mean:
(I slightly modified your code; dropped extra variables, made it a lil bit cleaner, etc.)
I strongly recommend you against using this approach. This way the implementation of
postLogin()
method which is supposed to be responsible to login users gets coupled with session data which is not good. This way, you're not able to usepostLogin
independently from thepostRegister
.2. Login the user right after the registration
This is a slightly better solution; If you decided that you need to log in the user right after the registration, why not just doing that?
Note that Laravel's own authentication controller does it automatically.
By the way, here's what I mean:
(Ideally this should be broken down into multiple methods, just like Laravel's own authentication controller. But it's just an example to get you started.)
But still, it's far from perfect! There are many other ways to tackle this. One could be using events, throwing exceptions on failure and redirecting using custom exceptions. But I'm not gonna explore them as there's already a solution perfectly designed for this.
If you want to write your own authentication controller, that's fine. You'll learn a lot along the way. But I strongly suggest reading Laravel's own authentication code, especially
RegistersUsers
andAuthenticatesUsers
traits in order to learn from it.And one more note; you don't need that
Illuminate\Auth\Authenticatable
trait in yourUser
model as it's already extendingAuthenticatable
which use that trait.