Login With Facebook In Laravel 5.4
Krunal Lathiya
1126

Great tutorial, but I have some comments on the bad practices I’ve noticed.

A common practice I’ve noticed is storing the provider_user_id and provider inside the users table. Well, this is a bad practice, because a user can have accounts on multiple social networks, but this technique can only store one.

A better practice is to keep the social network accounts in a different table, as you did. But you SHOULD NEVER give such a specific name to a table. Your tutorial shows that you should create a social_facebook_accounts table. You can see that Socialite provides drivers for Twitter, Github, Google+, etc. If I was to follow your pattern, I would have social_facebook_accounts, social_github_accounts, social_twitter_accounts and social_google_accounts if I wanted my users to be able to log in with all of these 4 platforms. This is crazy! More than that, I would have to create 4 different models, one for each table. Does this sound like a good pattern? I doubt it. Also, if my table is named social_facebook_accounts, what’s the purpose of that provider field?

A better approach is to create a social_accounts table with a SocialAccount model. The table would have the same fields as you explained, but we would make that provider field work as it should.

$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->string('provider_user_id');
$table->string('provider');

(note that I have properly created a foreign key on lines 1 and 2)

That way, we can have:

user_id    provider_user_id    provider
1 1233123 facebook
1 4asd23314 twitter
1 s1244123 github

Notice how one user (with an id of 1) has 3 different social accounts associated to its account on our platform?

Have you noticed that I have not added a in(['facebook', 'twitter', ...]) directive to our provider field? Well, that’s because we want flexibility with that table, and any restrictions will be handled by the PHP itself, not by the database. Anyway, this should not become a general rule.

To properly deal with our SocialAccount model, we would add local scopes (check https://laravel.com/docs/5.5/eloquent#local-scopes).

One technique would be to add a scope for each of the social networks we’re allowing on our website. But we’re trying to use the best practices here, right?

What if next month we will want to add a LinkedIn login option for our users? We will have to open this model again and add a new scope. This will also make our model “fat”, writing 4 new lines of code for each social network we want to link our accounts to.

A better approach is building our model like this:

<?php

namespace
App;

use Illuminate\Database\Eloquent\Model;

class SocialAccount extends Model
{
public function scopeByProvider($query, $provider)
{
return $query->where('provider', $provider');
}
}

That way we will have one scope that will work for each and every option we want to add.

So when we want to get all of our Facebook accounts, we will do it like so:

SocialAccount::byProvider('facebook')->get()

Also, always name your routes and never use the url itself while redirecting the user, but rather use the name of the route.

So if in our web.php file we had this:

$route->get('/home')->name('home')

In our controllers we will redirect our users like this:

return redirect()->route('home')

To all writers: please, if you decide to write tutorials so people will learn something from you, make sure you teach them the right things. Making something work is simple. The true challenge in development is properly building something, making it flexible, so it will make your future development of that project easier.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.