Laravel Eloquent relationship Many to Many - php

A user can have one whitelabel.
A whitelabel can have many users.
I have a pivot table with whitelabel_id, and user_id columns
I have both relationships set up using ->belongsToMany() (with the inverse).
I am using a pivot table because I don't have a whitelabel_id on the users table (and won't be putting one in) so its defined as a many-to-many, but really it's one-to-many. I just get the first() whitelabel as there'll only be one for each user.
With this in mind. How do I select * users with the currently authenticated user's whitelabel?
I have this, it works, but is this the "Laravel" way? I feel it's slightly over engineered and Laravel would have a shorthand method.
$user->when(auth()->user()->whitelabel->first(), function ($query) {
return
$query->whereIn('id', auth()->user()->whitelabel->first()->users->pluck('id'));
})
This checks if the auth user has a whitelabel, and then gets all users with the same whitelabel.
Does Laravel have a quick shorthand for this?

Models:
class Whitelabel
{
public function users()
{
return $this->belongsToMany(User::class);
}
}
class User
{
public function whitelabels()
{
return $this->belongsToMany(Whitelabel::class);
}
}
you can retrieve records for simple
$user = User::find(Auth::id())
$user->whitelabels
if you want return all user in Auth user's whitelabel
foreach($user->whitelabels as $whitelabel){
$whitelabel->users
}

Related

How to get laravel pivot table records in views?

I have three tables.
Users: id,name
Courses: id,user_id,name
Order: id,user_id,course_id (
Pivot table)
How can i make sure in course view that this user has purchased this particular course using Laravel eloquent.
Firstly, you need to define a many to many relationship between your models:
class User extends Model {
public function courses() {
return $this->belongsToMany(Course::class);
}
}
Once you have it, you can easily check if User has bought access to a Course with given ID with:
if ($user->courses()->find($courseId)) {
// user has access to course with given $courseId
}
If you simply want to an error to be raised when course was not bought, replace a call to find() with a call to findOrFail():
if ($user->courses()->findOrFail($courseId)) {
// user has access to course with given $courseId
}

Applying hasManyThrough to deeper relationships

The Laravel docs seem to indicate that the hasManyThrough declaration can only be used for relationships that are two levels "deep". What about more complex relationships? For example, a User has many Subjects, each of which has many Decks, each of which has many Cards. It's simple to get all Decks belonging to a User using the hasManyThrough declaration, but what about all Cards belonging to a User?
I created a HasManyThrough relationship with unlimited levels: Repository on GitHub
After the installation, you can use it like this:
class User extends Model {
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
public function cards() {
return $this->hasManyDeep(Card::class, [Subject::class, Deck::class]);
}
}
As stated in the comments, hasManyThrough doesn't support this level of specificity. One of the things you can do is return a query builder instance going the opposite direction:
//App\User;
public function cards()
{
Card::whereHas('decks', function($q){
return $q->whereHas('subjects', function($q){
return $q->where('user_id', $this->id);
});
});
}
We're going from Cards -> Decks -> Subjects. The subjects should have a user_id column that we can then latch onto.
When called from the user model, it would be done thussly:
$user->cards()->get();
Well, actually the best solution will be put the extra column to Card table - user_id, if you have so frequent needs to get all cards for the user.
Laravel provides Has-Many-Through relations for 2-depth relation because this is very widely often used relation.
For the relations Laravel does not support, you need to figure out the best table relationship yourself.
Any way, for your purpose, you can use following code snap to grab all cards for the user, with your current relation model.
Assumption
User has hasManyThough relationship to Deck,
So Project model will have following code:
public function decks()
{
return $this->hasManyThrough('Deck', 'Subject');
}
Deck has hasMany relationship to Card
Code
$deck_with_cards = $user->decks()->with("cards")->get();
$cards = [];
foreach($deck_with_cards AS $deck) {
foreach ($deck->cards as $c) {
$cards[] = $c->toArray();
}
}
Now $cards has all cards for the $user.

Laravel - checking record existence

Currently my db tables are defined as below:
site_roles - Contains different roles
site_user_roles - Links Users to many roles
site_permission_modules - Contains different access levels [eg. view admin controls, ban users]
site_role_permissions - Links permission modules to roles
My models in laravel are correctly defined to query these many to many relations. In code I want to check if a user has a certain permission module linked to him.
For better understanding, here are my models as well:
User
public function SiteRoles()
{
return $this->belongsToMany('App\SiteRole', 'site_user_roles', 'users_id', 'site_roles_id');
}
SiteRole
public function Users()
{
return $this->belongsToMany('App\User', 'site_user_roles', 'site_roles_id', 'user_id');
}
public function SitePermissionModules()
{
return $this->belongsToMany('App\SitePermissionModule', 'site_role_permissions', 'site_roles_id', 'site_permission_modules_id');
}
SitePermissionModule
public function SiteRoles()
{
return $this->belongsToMany('App\SiteRole', 'site_role_permissions', 'site_permission_modules_id', 'site_roles_id');
}
Here is what I currently did:
Auth::User()->SiteRoles()->with('SitePermissionModules')->get()
The with() keyword retrieves a nested array of permissions associated with each role.
I need to check if the user has a specific permission module linked to him.
What would be the best laravel way to do this?
EDIT:
Basically I'm just asking what would be the best way to chain 2 many to many relationships.
Auth::User()->SiteRoles()->with(['SitePermissionModules' => function ($query) {
$query->where('site_role_permissions','=','admin');
//use where as per your requirment.
}])->get();
Querying Relaionship

Eloquent Laravel , Superior and Subordinate relationship

I have a project in laravel ,
It is an online library in which there can be three types of users , superAdmin
writersAdmin and writers,
I have already created the roles and permissions successfully
but i want to have superiors and subordinates kind of relationship in the users table
for example , the writersAdmin can have multiple writers that work for him,
is it possible to do so in the users table only or do i have to create other tables.
It can be achieved only in the user table.
for example, add superior_id column, and the save superior's id.
And, add the following code to the user model.
class User extends Eloquent {
protected $table = 'users';
public $timestamps = false;
public function parent()
{
return $this->belongsTo('User', 'superior_id');
}
public function children()
{
return $this->hasMany('User', 'superior_id');
}
}
How to use
User::with('parent')->find(1);
User::with('children')->find(1);
but, if there is more than one superiors in the user, can not be achieved in this method.
In that case, I recommend you to create other table.

Laravel 5 Relations

Database Structure:
-Users Table
-user_id
-name
-...
-Follow Table
-user_id
-follow_id
so when user follow another it will be inserted in follow table
and when get user followers
$user = User::where('user_id',$id)->first();
$user['followers'] = $user->Followers;
$user['following'] = $user->Following;
return $user;
By This Relation in User Model Side
public function Followers()
{
return $this->hasMany('App\Follow','follow_id','user_id');
}
And By This Relation in Follow Model Side
public function getUserData()
{
return $this->belongsTo('App\User','user_id','user_id');
}
It Works Fine for me and it gaves me every id But the problem is
that i want to get information about every user returned from this relation
so i should call User Model for each user returned to get his information
or what ??
The way you have you many-to-many relationship set up is almost right.
Firstly, change the Followers() method to be followers() as Laravel follows the PSR-2 standard.
Secondly, this isn't essential but change the user_id column in the users table to be just id. This is a laravel convension that does not need to be followed, however, at this point I don't see any reason not to follow it. I am assuming that you have something like:
protected $primaryKey = 'user_id';
in your User model. If you change your user_id column to id you won't have to have the above declaration anymore.
(If you don't have that line in and you want to continue using user_id as the primary key you WILL have to add that line to your User model.
Thirdly, change the relationship type in followers() to be:
public function followers()
{
return $this->belongsToMany('App\User', 'follower', 'user_id', 'follow_id');
//follower is the table name, user_id is column that relates to the current model and follow_id is the column that is for the relationships
}
With all of the above done you can now get a user with all of their followers by doing:
$user = User::with('followers')->find($id);
This will allow you to get the followers by simply doing:
$user->followers
At this point you can not get rid of you Follow model as you generally wont need a model for a pivot table.
To get the following relationship just add:
public function following()
{
return $this->belongsToMany('App\User', 'follower', 'follow_id', 'user');
}
to your User model.
Again to access this you can either:
$user = User::with('following')->find($id);
or if you have already have the user model and the relationship isn't loaded you can:
$user->load('following'); //in this case following is the name of the method where you have declared the relationship.
For more information please refer to the documentation http://laravel.com/docs/5.1/eloquent-relationships#many-to-many and http://laravel.com/docs/5.1/eloquent
Hope this helps!

Categories