Laravel development structure - php

I am developing an application in which I have views for different roles.
For example, I have a form which has 5 fields. It may have 3 fields for role 1 and all fields for role 5 available when submitting.
Now, where I am showing the form data as graphically or using table, I have options to show 5 columns or fields for some role and less fields form for some other role.
Right now I am doing if else logic in each action of controller to determine the role then pass the appropriate data to the view, how do you manage this? I would like to know.
PLEASE READ FULL BEFORE SAYING 'SHOW ME SOME CODE :('
EDIT:
1 more question, suppose there is a users class and have a 1 to 1 relation with type class, in the views i can do:
{{ Auth::user()->type->key }}
Or some complex ones like
{{ Auth::user()->as_member->claims->sum('amount_claimed') }}
This is a complex relation, user as a member have many claims and I am summing it up here. Is it better to do this in controller then pass them as a value?

Generally speaking User and Role share Many-To-Many relation. A user can have many roles and a role can be shared by many users.
To implement it three database tables are required
1. users
2. roles
3. role_user (pivot table)
Then the relation could be defined in the models as
class User extends Model
{
public function roles()
{
return $this->belongsToMany('App\Roles');
}
//suppose you currently want to assign each user only one role
//however also want to provision multiple roles for user in future
//then you can define a virtual/calculated attribute to your model
//to simplify usage considering each user has only one role
public function getRoleAttribute()
{
return $this->roles[0]->name; //name is a field on the roles table
}
protected $appends = ['role']; //to ensure that the calculated attribute is available to ajax/json/api requests as well
}
class Role extends Model
{
public function users()
{
return $this->belongsToMany('App\User');
}
}
Say you have three users as sample data
User1 has role 'User'
User2 has role 'Manager'
User3 has role 'Admin'
Now you can test the functionality with a sample view like
<h4>Current user is {{auth()->user()->name}} having a role of {{auth()->user()->role}}</h4>
<div class="example-form">
<h4 class="all">Visible to all - User1, User2, User3</h4>
#if( (auth()->user()->role ==='Manager') || (auth()->user()->role ==='Admin'))
<h4>Visible to Manager and Admin only - User2 and User3</h4>
#endif
#if(auth()->user()->role === 'Admin')
<h4>Visible only to Administrator - User3</h4>
#endif
</div>
Hope this is what you are aiming for - is my understanding okay.
However since you have mentioned that you are using Laravel 5.2, better way of doing it would be to use out-of-box authorization provided by Laravel 5.2.
Refer Authorization documentation

Related

Get parent model from child relationship OOP Laravel

I'm facing an issue with model extension. Here's an example of my problem:
I have a User model and an Admin model that extends my User model. I use a github repo called Bouncer for permissions. When I save my roles for an Admin model, it saves as /App/Admin and for Users, it saves as /App/User for the model reference.
So when I call my roles for a Admin or for a User, no problem. But my issue is when I want to query all my users with their roles. I obviously get all my users AND my admin, but the Admins can't get their roles because the are "/App/Admin" in the database.
How can I get all the roles of my "extended" models when I call the parent?
You will create a relationship in your model using belongs to and use a method called "with ()".
First step:
In your model, create belongs to ex:
public function post()
{
return $this->belongsTo('App\Post', 'foreign_key', 'other_key');
}
Second step:
You will use it in your controller,example:
$users = User::with('podcasts')->get();
Eloquent: Relationships
https://laravel.com/docs/7.x/eloquent-relationships#updating-belongs-to-relationships
Another example
Get Specific Columns Using “With()” Function in Laravel Eloquent

Laravel three way polymorphic relation madness

Laravel 7.0
I am trying to set up a system where users can belong to
different models, like Courses or Realms. I call this a
'membership'.
A user who is a member in a Realm or Course always has a
Role within that Realm, like 'amdin', 'editor', or 'guest'
I have models for User, Role, Memberable and the Course/Realm stuff.
Like this:
Role ⇦1:N⇦ Memberable ⇨N:1⇨ User
⇩
poly 1:1
⇩
Realm/Course/YouNameIt
At the moment I am using a wild mix of relations to get
more or less what I want. But my approach seems rather
gross to me, or even wrong.
For example, to get a list of models that I am a member of, I write:
User::find(2)->memberships()->get()
But this gives me a Collection of Memberables, not Realms or
Courses, which kind of sucks. Can this be remedied?
To get my first Realm/Course, I have to write:
User::find(2)->memberships()->first()->memberable // YUCK!
Here are my models:
class User {
public function memberships()
{
return $this->hasMany(Memberable::class)->with('memberable');
}
public function roles()
{
return $this->belongsToMany(Role::class, 'memberables')
->withPivot(['memberable_id', 'memberable_type']);
}
}
class Memberable extends Model
{
public function role()
{
return $this->hasOne(Role::class, 'id', 'role_id');
}
public function memberable()
{
return $this->morphTo('memberable');
}
}
trait HasMembers
{
public function members()
{
return $this->morphToMany(User::class, 'memberable', 'memberables')
->withPivot('role_id')
->join('roles', 'roles.id', 'memberables.role_id')
->addSelect(['role' => Role::select('name')
->whereColumn('role_id', 'roles.id')]);
}
}
class Realm extends Model
{
use HasMembers;
}
class Course extends Model
{
use HasMembers;
}
I know that questions like "is this good" or "is this bad" are difficult to answer, so I'll ask:
Is this so wrong that I should worry?
How could I improve this design?
I'll probably never have more Models that Realms and Courses that can have members. Is it smarter to ditch the whole memberable-polymorphism in favour of two separate tables? It IS nice to keep the flexibility the polymorphic approach offers.
You could just set up more relationships
User belongsToMany Roles
Roles belongsToMany Users
User morphedByMany Realm using Memberable
User morphedByMany Courses using Memberable
User morphedByMany YouNameIt using Memberable
Realm morphToMany User using Memberable
Courses morphToMany User using Memberable
YouNameIt morphToMany User using Memberable
I'd make Memberable a morph pivot.
class Memberable extends MorphPivot { ... }
With this, accessing the relationships isn't hard.
$user->roles // Get an Eloquent Collection made up from $user's roles.
$role->users // Get an Eloquent Collection made up from users that have $role.
$user->realms // Get an Eloquent Collection made up from $user's realms.
$user->courses // Get an Eloquent Collection made up from $user's courses.
$user->youNameIt // Get an Eloquent Collection made up from $user's youNameIt.
$realm->users // Get an Eloquent Collection made up from users associated with $realm.
$course->users // Get an Eloquent Collection made up from users associated with $course.
$youNameIt->users // Get an Eloquent Collection made up from users associated with $youNameIt.
And maybe make User <---> Roles relationship use a separate pivot. If not, then make it a morph relationship as well (User morphedByMany Role using Memberable, Role morphToMany User using Memberable)
The thing is, if you use a central table to morph everything up, it will grow a lot. You're essentially making it do the job of 3-4 pivots (in this example). If your data grows a lot, it might become a problem.
Also, different relationships might need different data from the pivot table but since you're only using a single table, that would complicate things unless you opt to use a json field.

Eloquent Relationships, linking of models (Laravel 5.4)

I'm kinda confused how the eloquent relationships works in Laravel 5.4.
I got a school model that has a "hasMany" relationship with my user model:
public function users()
{
return $this->hasMany('App\User');
}
The user is not required to be linked to a school though, so I haven't put the belongsTo (school) function on my user model.
How should I link the user to a school, when I create the user and how can I pull all users in a specific school into a view, for example?
If the user can only belong to one school, the most straightforward approach would be to add a school_id column to the users table. Since it's not required, you can allow for it to be null. This will allow you to run $school->users to retrieve a list of users for a given school.
I would also recommend adding the belongsTo relationship to the User model, so you can do $user->school to retrieve a user's school when applicable. It's okay that it'll be null for some users.

How to retrieve data from additional columns in a pivot table and also be able to update it in laravel 5.2

I was working on making a group functionality for my website which uses a many to many relationship between groups and users.
My User model looks like this:
public function groups(){
return $this->belongsToMany('App\Group')->withPivot('role')->withTimestamps();
}
My Groups model looks like this:
public function users(){
return $this->belongsToMany('App\User')->withPivot('role')->withTimestamps();
}
So my third column has the name of role which is a string variable and is set to a default of "member" for members of my group and I set it to "admin" for the actual user who creates a new group. But I want the admin to have the option of making multiple members admins as well which would require me to check weather the current current user who sent the request is an admin or not. If he is, then I wanna be able to take his request of making a member an admin which would require me to update the role for that particular "member" to an "admin".
In the laravel documentation it only shows you how to attach and detach data in a pivot table and else where I have only seen methods of retrieving data from the first two columns but how can I do the same for additional columns and also be able to update it using the updateExistingPivot method?
You could access the column simply using pivot e.g :
$user->pivot->role
Take a look at Retrieving Intermediate Table Columns in documentation Eloquent Relationships.
Hope this helps.

Eloquent relationship between user roles

I am creating an app where users have different roles. Some of the roles include:
Administrator
Supervisor
Contractor
I have the following tables setup:
user
role
role_user
The role_user is a pivot table used to store the user_id and role_id.
Now, when a Contractor is created, I trigger an event which assigns the user to the Contractor role in the database:
$user->roles()->save($role, ['cust_id' => $event->user->cust_id]);
The above line basically just creates a new row in the role_user pivot table and points to the role_id of a Contractor. This results in the user having Contractor privileges.
Also, within the event I need to assign the user to a Supervisor. However, there is no Supervisor model. Supervisors are also stored in the user table and have a role of Supervisor assigned to them.
How can I create a relationship between Contractors and Supervisors?
Ideally, i'd like to use something like this to create the Contractor/Supervisor relationship in the pivot table:
$user->supervisors()->save($supervisors, ['cust_id' => $event->user->cust_id]);
But i'm not sure how to setup my model...?
/**
* The supervisors that belong to the user.
*
* #return Object
*/
public function supervisors()
{
return $this->belongsToMany('SimplyTimesheets\Models\User\User')->withTimestamps();
}
What your asking is possible, however your relationship model would look like this:
public function cands()
{
return $this->belongsToMany('Some\Model')->where('something', $something)->where('something', $something);
}
You would have to use where clauses to hard code a relationship between contractors and supervisors because there is no direct relationship between them both.
/* Edit */
From your comment, you would have to approach that query with eager loading your relationship like so:
User::has('supervisors')->join(...)->where(...)->get();
The query above would return all users which meet the roles criteria. If you was just after one result you could create a hasOne relationship with your where clauses.
public function relationship()
{
return $this->hasOne('Your\User_Role\Model', 'foreign_key', 'other_key')->where('role_id', supervisor)->where('role_id', contractor)
}
It all comes down to your application needs.

Categories