66

I have this basic query i want to perform but an error keeps coming up. Probably due to my newness to laravel.

here is the code:

$userRecord = $this->where('email', $email)->where('password', $password);
        echo "first name: " . $userRecord->email;

I am trying to get the user record matching the credentials where email AND password are a match. This is throwing an error:

Undefined property: Illuminate\Database\Eloquent\Builder::$email

I've checked the email and password being passed to the function, and they are holding values. what is the problem here?

Thanks,

spacemonkey
  • 2,530
  • 6
  • 23
  • 27
  • as an aside, you may wish to to look at Eloquent's model scopes for tidying more complex queries. Suppose your email field was actually emailId with an FK constraint: users_emails_foreign, you can do something like: class Email extends Model {} class User extends Model { public function scopeEmail($query) { return $query->where('emailId', $Email::whereAddress("test@example.com")->first()->id); } } Now you could have a call in your code like $user->email()->wherename("Frank"); – Jay Edwards Sep 14 '15 at 22:24

7 Answers7

62
$this->where('email', $email)->where('password', $password) 

is returning a Builder object which you could use to append more where filters etc.

To get the result you need:

$userRecord = $this->where('email', $email)->where('password', $password)->first();
mjhinch
  • 771
  • 4
  • 8
  • I am getting Trying to get property of non-object – spacemonkey Dec 08 '13 at 15:15
  • 1
    if you're getting it when you call $userRecord->email; Then $userRecord is null as the query didn't return any records. – mjhinch Dec 08 '13 at 15:23
  • Yes could be the case but why so? I echoed email and password and both showed exactly to what is in database. Any thing I might be overlooking? – spacemonkey Dec 08 '13 at 15:28
  • Is the password being stored as a hashed value, which you should do? Then checking using the where clause won't work. It's better to user the built in Auth functions for validating users logins. – mjhinch Dec 09 '13 at 10:17
  • this is perhaps redundant query isnt it – Agil Oct 02 '18 at 11:26
15

You either need to use first() or get() to fetch the results :

$userRecord = $this->where('email', $email)->where('password', $password)->first();

You most likely need to use first() as you want only one result returned.

If the record isn't found null will be returned. If you are building this query from inside an Eloquent class you could use self .

for example :

$userRecord = self::where('email', $email)->where('password', $password)->first();

More info here

Mostafa Norzade
  • 1,578
  • 5
  • 24
  • 40
afarazit
  • 4,907
  • 2
  • 27
  • 51
  • I tried this and I get "Trying to get property of non-object" @afarazit – spacemonkey Dec 08 '13 at 15:14
  • and still it doesn't work mate. I am getting the same error :( – spacemonkey Dec 08 '13 at 15:18
  • You must update your question then and provide more info on where you're trying to run this code, provide the full class if possibly – afarazit Dec 08 '13 at 15:27
  • I am trying to run this code within User model. Hence I am using $this and self. Nevertheless, in my controller I am invoking the function $user->login($email, $password) and this is supposed to return the found user record. – spacemonkey Dec 08 '13 at 15:29
  • @spacemonkey where is `$user` coming from in your controller? Apparently `$user` isn't instantiating correctly – afarazit Dec 08 '13 at 15:31
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/42743/discussion-between-afarazit-and-spacemonkey) – afarazit Dec 08 '13 at 15:33
  • I figured out something. When I changed the string $userRecord = $this->where('email', $email)->where('password', $password)->first(); to $userRecord = $this->where('email', $email)->first(); it actually passed the if condition and loaded the correct page. I need both email and password to be checked. any hints there? – spacemonkey Dec 08 '13 at 16:22
  • @spacemonkey, may be it is not matching because in most cases password will be encoded in to some encrypt format and here you are matching it directly. – Haritsinh Gohil Mar 05 '20 at 11:31
11
$userRecord = Model::where([['email','=',$email],['password','=', $password]])->first();

or

$userRecord = self::where([['email','=',$email],['password','=', $password]])->first();

I` think this condition is better then 2 where. Its where condition array in array of where conditions;

Mgorunuch
  • 647
  • 1
  • 5
  • 16
6

The error is coming from $userRecord->email. You need to use the ->get() or ->first() methods when calling from the database otherwise you're only getting the Eloquent\Builder object rather than an Eloquent\Collection

The ->first() method is pretty self-explanatory, it will return the first row found. ->get() returns all the rows found

$userRecord = Model::where('email', '=', $email)->where('password', '=', $password)->get();
echo "First name: " . $userRecord->email;
Wader
  • 9,427
  • 1
  • 34
  • 38
6

After reading your previous comments, it's clear that you misunderstood the Hash::make function. Hash::make uses bcrypt hashing. By design, this means that every time you run Hash::make('password'), the result will be different (due to random salting). That's why you can't verify the password by simply checking the hashed password against the hashed input.

The proper way to validate a hash is by using:

Hash::check($passwordToCheck, $hashedPassword);

So, for example, your login function would be implemented like this:

public static function login($email, $password) {
    $user = User::whereEmail($email)->first();
    if ( !$user ) return null;  //check if user exists
    if ( Hash::check($password, $user->password) ) {
        return $user;
    } else return null;
}

And then you'd call it like this:

$user = User::login('email@aol.com', 'password');
if ( !$user ) echo "Invalid credentials.";
else echo "First name: $user->firstName";

I recommend reviewing the Laravel security documentation, as functions already exist in Laravel to perform this type of authorization.

Furthermore, if your custom-made hashing algorithm generates the same hash every time for a given input, it's a security risk. A good one-way hashing algorithm should use random salting.

Community
  • 1
  • 1
TonyArra
  • 10,607
  • 1
  • 30
  • 46
4

Here is shortest way of doing it.

$userRecord = Model::where(['email'=>$email, 'password'=>$password])->first();
Kaleem Shoukat
  • 811
  • 6
  • 14
1
$userRecord = $this->where('email', $email)->where('password', $password);

in the above code , you are just requesting for Eloquent object , not requesting for the data,

   $userRecord = $this->where('email', $email)->where('password', $password)->first();

so that, you can get the first data, from the given credentials by default ordering DESC with PK, in case of multiple data with the same credentials. but you have to handle the exception, in case of no matching data. you have one more option to achieve the same.

$userRecord = $this->where('email', $email)->where('password', $password)->firstOrfail();

in the above snippets, in case of no data, it will automatically throw a 404 error.

also, you can have alternative snippets

$filter['email']=$email;
$filter['password']=$password;
$userRecord = $this->where($filter)->first();

That's it

Kishor Pant
  • 136
  • 1
  • 4