Get parent model from child relationship OOP Laravel - php

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

Related

How to get a particular column value by using Eloquent ORM?

I have two migration tables and two models
1)User.
2)Subscription.
in subscriptions Model i write one method called user() which has hasMany relationship and in Users model it will contain subscriptions() method which have belongs() relationship.
in user table id acts as an primary key and in subscription table sub_id acts as a foriegn key,for example if the user subscribed to any subscription the user id will store in the sub_id in the subscription table upto this it's working fine.
$is_subscription=Subscription::where('sub_id',$user->id)->value('sub_id');
from the above code i am able to get the value but now what i want is is there any better way to write the query based on models ,please help me to write this one..
According to your descriptions, I believe this is what you have:
class User extends Model
{
public function subscriptions()
{
return $this->hasMany(Subscription::class);
}
}
class Subscription extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
So you want to check whether an user has any subscriptions. You can do one of the followings:
$user->subscriptions()->exists();
// Or
$user->subscriptions->isNotEmpty();
You can use pluck() method:
$is_subscription=Subscription::where('sub_id',$user->id)->pluck('sub_id');
You can find details on the methods that are available for collection using the Laravel Documentation

Laravel: One to Many relationship, pull last N record from table

I have a User model and workLOG model. The user model has many work logs, meaning One user can have many work logs (ONE TO MANY RELATIONSHIP). I have created a relationship using the Eloquent relationship.
User Model
public function workLog()
{
return $this->hasMany('App\WorkLog','user_id','id');
}
workLog Model
class WorkLog extends Model
{
protected $table="worklog";
}
The worklog table has a column called total_hours_per_day. How can I pull the last N records from the column of the logged-in or authenticated user?
What I have done to get workLog so far
$worklogs = Auth::user()->workLog;
Now I want to get last 7 data from the column total_hours_per_day
Screenshots of the table
you need to establish on the WorkLog model a belongsTo.
public function user()
{
return $this->belongsTo('App\User');
}
Edit: relationships have to be established in both models you're trying to relate. If you like a girl, she needs to like you back to establish a relationship. You just defined the relationship in one side.
Try using take()
As Laravel documentation says:
"The take method returns a new collection with the specified number of items"
$worklogs = Auth::user()->workLog->take(-7)->reverse();
and I pull the last 7 records from total_hours_per_daycolumn in the blade template as:-
#foreach ($worklogs as $worklog)
{{ $worklog->total_hours_per_day }}
#endforeach

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.

L5.5 relationship of pivot table with another model

In my application, a model Device has a many-to-many relationship with model Task.
A combination of Device and Task could be assigned to a various number of model User.
example: Device A has a Task Check something and this should be done by User Frank and Steven.
From my point of view, this should be a "standard problem", but so far I could not find a proper solution.
Right now, I use following workaround:
a) added an unique ID id to the device_task pivot table
b) query id from the pivot table
c) create a new table device_task_user which contains user_id and device_task_id
b) use query builder to get/add users
But I am really not happy with this approche.
Would it be possible, that the pivot table also extends Model and then have a one-to-many relationship with User?
Or would you suggest to add a json colum to the pivot table and store the users there?
Any idea would be very welcome!
Would it be possible, that the pivot table also extends Model
Yes, it's possible. From the docs:
If you would like to define a custom model to represent the intermediate table of your relationship, you may call the using method when defining the relationship. All custom models used to represent intermediate tables of relationships must extend the Illuminate\Database\Eloquent\Relations\Pivot class
You also can create a new hasMany() and belongsTo() relationships between Task and Device models and use them as well as existing belongsToMany relationship. And you'll need to define a new relationship between pivot model and User model to be able to get data by device, task or user.
Modify many-to-many relationship to hold an extra field user_id
class Device extends Model
{
public function tasks()
{
return $this->belongsToMany(
Task::class,
'device_task',
'device_id',
'task_id'
)->withPivot('user_id');
}
}
And when updating do like this in controller
$device->tasks()->attach([$taskId]=>['user_id']=>$userId);
And of-course you need DeviceTask model and also a has-many relationship between User model and DeviceTask model to get user's task

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.

Categories