Get hasMany relationship through 4 levels of users childs - laravel

I have a users table that contains:
id
parent_id //=> refers to the users table
role // admin, salesman, agent, agent_account
and cards table :
id
user_id //refers to a user with "agent_account" role
user with admin role has many childs of users with salesman role
user with salesman role has many childs of users with agent role
user with agent role has many childs of users with agent_account role
user with agent_account role has many cards
I want to define the relationship of policies in the user form so that the user can access all of their child policies
public function cards()
{
switch ($this->role) {
case 'admin':
# return all cards
break;
case 'agent':
# foreach $this->child as $ch
# $allCards += $ch->cards;
#return $allCards;
break;
case 'agent_account':
return $this->hasMany(Card::class, 'user_id');
break;
default:
# code...
break;
}
}
How do I return a variable of relationship type and how do I bring the relationships together :how i can do this =>($allCards += $ch->cards;)?
Is there a better way or mechanism to solve this problem?

Related

Need help in registration system

In laravel9 I have created following tables
users (its laravel auth ui)
tournamnets
matches (in matches i have column "name")
registrations (in registration I have relation with users and one column status_id Bydefault its 0 and relation with matches is hasmany and belongsTo)
Note: match id is linked with hasmany and belongsto relation
Note: registrations and tournamnets have Pivot table which is reg_tours
Column names are tournaments_id and registrations_id.
Now I need with user registered for the specific tournament and registrations status is 0 the show {you are registered} in that specific tournament and if with user registered for the specific tournament and that registrations status is any match id which is linked with belongs to relation then show that match name
Tournament Controller
public function singleTournament($id) {
$game = Game::all();
$data = Tournament::find($id);
if ($data->teamsize == 1) {
$data->teamsize = "Solo";
} elseif ($data->teamsize == 2) {
$data->teamsize = "Duo";
} elseif ($data->teamsize == 4) {
$data->teamsize = "Squad";
}
return view('site.tournament',compact('data','game'));
}
Thank You!
I need to show status for specific tournament to specific user
you can add initialize for the status variable before

Laravel: sync many to many on a subset of rows

There is a multi-tenant laravel application that is implemented in a single database. There are models User and Role with the following relation in User model:
public function roles(): BelongsToMany
{
$relation = $this->belongsToMany(Roles::class, 'role_users', 'user_id', 'role_id')->withTimestamps()->withPivot('tenant_id');
$relation = $relation->where(function ($query) {
$query->where('tenant_id', Tenant::current()->id);
});
return $relation;
}
The role_users table contains user_id, role_id, tenant_id. A user may present in multiple tenants, when I update roles of a user in a tenant, I need to only update the roles of the current tenant, not the user roles on all tenants. This the code I write :
$user->roles()->syncWithPivotValues($roles, ['tenant_id' => Tenant::current()->id]);
But it doesn't work and syncs all roles not the roles of the current tenant. How can I solve the problem?
You can use the wherePivot() method passing the tenant id.
You can find the documentation here: https://laravel.com/docs/9.x/eloquent-relationships#filtering-queries-via-intermediate-table-columns
The code should then look like this:
$user->roles()->wherePivot('tenant_id', Tenant::current()->id)->sync($roles);

Create indirect relationships and return the sum of two relationships

I have a program to share services between people. Basically I am facing a problem trying to get the conversations between users. Here is the idea:
My program allows users to offer services to other users, but also to acquire services from other users. Each user can register an unlimited number of services.
When a user finds a service that he/she wants to get, he creates a deal and starts a conversation with the counterpart.
The structure of my tables is the following (I am only including the relationship columns):
Users table
id // This is the user identifier
Services table
id // This is the service identifier
user_id // This is the identifier of the user who created the service
Deals table
id // This is the deal identifier
user_id // This is the identifier of the user acquiring the service
service_id // This is the identifier of the service being acquired in this deal
Conversations table
id // This is the identifier of the conversation
deal_id // This is the identifier of the deal that the conversation belongs to
Here is my problem:
I want to be able to retrieve the conversations for each user, both as applicant and as a seller.
I created this relationship (in User.php) for conversations in which the user is acquiring the service:
public function conversationsApplicant(){
return $this->hasManyThrough( Conversations::class, Deal::class );
}
I would like to create also the conversationsSeller() function
public function conversationsSeller(){
return $this->????;
}
I am guessing I should add some kind of relationship between a Conversation and a Service in Service.php. It would be something like $this->services()->with( 'deals' )->with( 'conversations' );
The final goal would be to have a method that returns both relationships in one $user->conversations()->get().
public function conversations(){
return $this->conversationsApplicant() + $this->conversationsSeller();
}
To retrieve the relationship I was thinking that maybe there is a workaround using a SQL query, but I am not sure if that will return the relationship as I need it. Here is the query that I need to perform:
SELECT
conversations.*
FROM
mydb.conversations, mydb.services, mydb.users, mydb.deals
WHERE
users.id = services.user_id AND
services.id = deals.service_id AND
deals.id = conversations.deal_id AND
users.id = $user->id;
Here is how you implement merged relationship simply
public function getCombinedChats($value)
{
// There two calls return collections
// as defined in relations.
$Applicant= $this->conversationsApplicant;
$Seller= $this->conversationsSeller;
// Merge collections and return single collection.
return $Applicant->merge($Seller);
}

Is removing the relations of a model, in a one-to-many relationship, and redefining the relations the best approach to peform update?

I have two models, user and permissions. 1 user can have many permissions, a user_id will have multiple occurrences on the permissions table. When updating an user I may change its permissions.
users permissions
id id
name user_id
With eloquent I do something like this:
$user = User::find(1);
$user->permission()->delete();
$user->permission()->create($permissions);
Although this code is very logical, it doesn't seem right to me. Finding the user, scanning the table to remove its permissions and reinserting new ones seems amateur, the deletion part doesn't seem right to me. To achieve one task I have to go through multiple processes.
If at least was something like this:
$user = User::find(1);
$user->permission()->recreate($permissions);
Of course recreate would have to be a built-in function and I am willing to code that functionality. Can't say if am doing things right.
Are you sure you are doing it rigth?
Since a user can have many permissions, you should have a user, permissions and a user_has_permissions or something like useR_permissions table.
users permissions user_has_permissions
id id user_id
name name permission_id
... ...
This is the relationships:
User permissions (in user model):
public function permissions()
{
return $this->belongsToMany(Permission::class, 'user_has_permissions');
}
To check if the user has permissions (in user model):
public function hasPermission($permissionId)
{
return null !== $this->permissions()->where('permission_id', $permissionId)->first();
}
You can also have a roles table, that has many permissions:
users permissions user_has_permissions roles role_has_permissions user_has_role
id id user_id id role_id user_id
name name permission_id name permission_id role_id
... ... ...
Now, user can have permissions and permissions through roles.
The user roles (in user model):
public function roles()
{
return $this->belongsToMany(Role::class, 'user_has_roles');
}
The role permissions (in the Role model):
public function permissions()
{
return $this->belongsToMany(Permission::class, 'role_has_permissions');
}
To check if the user has permissions through roles (in the user model):
public function hasPermissionThroughRoles($permissionId)
{
$roles = $this->roles;
foreach($roles as $role){
if($this->roles->contains($permissionId)
return true;
}
}
You can modify the hasPermissios function to check if the user has permission through roles, and if yes, grant access:
public function hasPermission($permissionId)
{
return (bool)($this->permissions()->where('permission_id', $permissionId)->first() || $this->hasPermissionThroughRoles($permissionId));
}
From laravel docs:
Eloquent also provides a few additional helper methods to make working with related models more convenient. For example, let's imagine a user can have many roles and a role can have many users. To attach a role to a user by inserting a record in the intermediate table that joins the models, use the attach method.
With the provided code snippets, you can add permission or role to the user with
$user = User::find(1);
$user->permissions()->attach(1);
$user->roles()->attach(1);
or remove permissions/roles:
$user = User::find(1);
$user->permissions()->detach(1);
$user->roles()->detach(1);
Check this package. The user permissions and roles (or group, as it is called in the package) management is easy with it.
Hope it helps.

Laravel user management

In Laravel we can manage Users and Permissions easly but i've a problem with my application.
In my application a User is attached to One or Many department.
But a User can have different Role/Permission between departments. That is the problem. In the department One he can have a Admin Role and in the department Two he can only have a User Role. When the User switch between department i would like that his Role can be update.
How i can manage this in Laravel and Eloquent ?
Thank you for your help.
Jeffrey
Without seeing any of your code, I am forced to be fairly generic here. But here is the basic concept.
Architecture
Assuming you have tables like departments, users, roles, and permissions already, all you would need next is define a joining table. Something like this:
department_role_user
department_id // for this department
role_id // this role is assigned to
user_id // this user
Authorization
Define something like a hasPermissionTo() method on your User model.
Definition
class User
{
public function hasPermissionTo($action, $department)
{
// first get permission
$permission = Permission::where('action', $action)->first();
// get all roles which have this permission
$roles = $permission->roles;
return DB::table('department_role_user')
->where('user_id', $this->id) // current user
->where('department_id', $department->id) // the dept
->whereIn('role_id', $roles->pluck('id')) // any of the roles
->exists();
}
}
Usage
And use it like so.
if ($user->hasPermissionTo('do-something', $someDept)) {
// allow action
} else {
// no way
}
This should also work nicely with Laravel's Gates and Policies. Just use your new hasPermissionTo() method inside your gate/policy definitions.

Resources