Get resources with hasManyThrough a model using BelongsTo - laravel

I have the following models:
User:
- id
- name
Location:
- id
- name
- region_id
table: user_location
- user_id
_ location_id
The user belongsToMany location through that table. I also have another model:
Region
- id
- name
I defined Region hasMany Locations.
With those relationships, how do I define a relationship between User and Region which Region will be able to find all users under all Locations associated with it?
<?php
class User extends Model
{
public function locations() {
return $this->belongsToMany('App\Location', 'user_location');
}
}
class Location extends Model
{
public function users() {
return $this->belongsToMany('App\User', 'user_location');
}
public function region() {
return $this->belongsTo('App\Region', 'region_id');
}
}
class Region extends Model
{
public function locations() {
return $this->hasMany('App\Location', 'region_id');
}
public function users() {
// what am I supposed to put in here?
}
}

There is no native relationship for this case.
I created a HasManyThrough relationship for situations like this: Repository on GitHub
After the installation, you can use it like this:
class Region extends Model {
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
public function users() {
return $this->hasManyDeep(User::class, [Location::class, 'user_location']);
}
}

Related

Laravel: Nested relationship method

I have the following models:
users
id
name
organisation_members
id
organisation_id (FK to organisations)
user_id (FK to users)
unqiue(organisation_id, user_id)
organisations
id
name
A user can be a member to many organisations.
My models are written as follows
class User extends Model {
public function organisationMembers(): HasMany
{
return $this->hasMany(OrganisationMember::class);
}
public function organisations()
{
// TODO: how do I do this one
}
}
class OrganisationMember extends Model {
public function organisation(): BelongsTo
{
return $this->belongsTo(Organisation::class);
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}
class Organisation extends Model {
public function organisationMembers(): HasMany
{
return $this->hasMany(organisationMember::class);
}
}
How can I write a relationship method in the User model for organisations?
Thanks to #matiaslauriti comment the answer is:
class User extends Model {
public function organisationMembers(): HasMany
{
return $this->hasMany(OrganisationMember::class);
}
public function organisations()
{
return $this->belongsToMany(Organisation::class, 'organisation_members');
}
}

Laravel polymorphic relationships return null

I'm trying to join an Order and 2 different OrderDetailType tables.
OrderDetailType1
- id
- order_id
OrderDetailType2
- id
- order_id
Order
- id
- detail_type 'type1' or 'type2'
And I have followed Polymorphic Relations example in official Laravel site and adapted to my code like:
class OrderDetailType1 extends Model {
public function order() {
return $this->morphOne('App\Order', 'type_detail');
}
}
class OrderDetailType2 extends Model {
public function order() {
return $this->morphOne('App\Order', 'type_detail');
}
}
class Order extends Model {
public function type_detail() {
return $this->morphTo();
}
}
And I have put Relation::morphMap() into boot() function in AppServiceProvider class already.
use Illuminate\Database\Eloquent\Relations\Relation;
class AppServiceProvider extends ServiceProvider {
public function boot() {
Relation::morphMap([
'type1' => 'App\OrderDetailType1',
'type2' => 'App\OrderDetailType2'
]);
}
}
The example is different from my code. The difference is both foreign key and the attribute that specifying which table to be joined should be in Order. So I cannot use morphTo() and morphOne() like the example to solve this.
I am confuse which classes should contain morphTo() and morphOne(). And is there any overload to specify which table have foreign key and type?
I use Laravel 5.4. Thank You in Advance.
The _id column has to be in the Order table:
OrderDetailType1
- id
OrderDetailType2
- id
Order
- id
- detail_type
- detail_id
class OrderDetailType1 extends Model {
public function order() {
return $this->morphOne('App\Order', 'detail');
}
}
class OrderDetailType2 extends Model {
public function order() {
return $this->morphOne('App\Order', 'detail');
}
}
class Order extends Model {
public function detail() {
return $this->morphTo();
}
}

Laravel 5.4 table relationship between 3 small tables

I have a recently started learning Laravel 5.4, I am having trouble with my 3 way table relationship, I've looked at a few articles online regarding many to many, but this relationship is just a "hasOne" on both sides.
Could anyone give me a helpful hint as to how to structure my table relationship, here is the PK/FK relationship:
Users table (id)
Listings table (id, user_id)
Insights table (id, listing_id) - one insight row per listing only.
And the models below:
Users Model
class User extends Model
{
public function listing()
{
return $this->belongsTo('App\Listing');
}
}
Listing Model
class Listing extends Model
{
public function insight()
{
return $this->hasOne('App\Insight');
}
}
Insight Model
class Insight extends Model
{
public function listing()
{
return $this->hasOne('App\Listing');
}
}
And what I am trying to achieve is to query the users own listings, with each listings current insights.
Thanks a bunch.
Simon.
User model
class User extends Model
{
public function listing()
{
return $this->hasOne('App\Listing');
}
}
Listing Model
class Listing extends Model
{
public function insight()
{
return $this->hasOne('App\Insight');
}
public function user()
{
return $this->belongsTo('App\User');
}
}
Insight Model
class Insight extends Model
{
public function listing()
{
return $this->belongsTo('App\Listing');
}
}
And if you want query users with Listing and Insight
$users = User::with(['listing', 'listing.insight'])->get();
foreach($users as $user) {
$user->listing->insight;
}
class User extends Model
{
public function listing()
{
return $this->hasMany(Listing::class);
}
}
class Listing extends Model
{
public function insight()
{
return $this->hasOne(Insight::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
class Insight extends Model
{
public function listing()
{
return $this->belongsTo(Listing::class);
}
}
$users = User::with('listing.insight')->get();
foreach($users as $user) {
$user->listing->insight;
}

HasManyThrough with polymorphic and many-to-many relations

In my Laravel application I have the following classes:
class Product extends Model
{
public function extended()
{
return $this->morphTo();
}
public function users {
return $this->belongsToMany('App\User', 'products_users', 'product_id');
}
}
class Foo extends Model
{
public function product()
{
return $this->morphOne('App\Product', 'extended');
}
public function bars()
{
return $this->hasMany('App\Bar');
}
}
class Bar extends Model
{
public function product()
{
return $this->morphOne('App\Product', 'extended');
}
public function foo()
{
return $this->belongsTo('App\Foo');
}
}
class User extends Model
{
public function products()
{
return $this->belongsToMany('App\Product', 'products_users', 'user_id');
}
}
I can easily get users of a bar object using Bar::find(1)->product->users and I can also get the bars of a user with User::find(1)->products.
How can I get the users of all bars belonging to a specific foo? That is, Foo::find(1)->users should return all users that have the bars belonging to Foo with id 1. It's basically hasManyThrough with polymorphic and many-to-many relations.
Try something like this:
public function users()
{
$Foo = static::with(['bars', 'bars.products', 'bars.product.users'])->get();
return collect(array_flatten(array_pluck($Foo, 'bars.*.product.users')));
}
This should work for you (code has been tested, but not against the exact same structure as your setup). The first line will return all the users deeply nested through the relationships. The second line will pull out the users, flatten them into an array, then transform the array into a collection.
I created a HasManyThrough relationship for cases like this: Repository on GitHub
After the installation, you can use it like this:
class Foo extends Model {
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
public function users() {
return $this->hasManyDeep(
User::class,
[Bar::class, Product::class, 'products_users'],
[null, ['extended_type', 'extended_id']]
);
}
}

Laravel Eloquent Relationship Through Another Table

I have the following database tables:
Seasons
id
number
Teams
id
name
Standings
id
season_id
team_id
The question is, how could I get all of the teams in a season through the standings table. At the moment I am getting all of the teams this way:
$teams = [];
$standings = $season->standings;
foreach($standings as $standing){
$teams[] = $standing->team;
}
Is there a way I could do this using Eloquent relationships? I have tried HasManyThrough with no success. These are what my models look like currently:
class Season extends Eloquent{
public function standings(){
return $this->hasMany('Standing');
}
}
class Standing extends Eloquent{
public function team(){
return $this->belongsTo('Team');
}
}
class Team extends Eloquent{
public function standings(){
return $this->belongsToMany('Standing');
}
}
Your relationships look a little off. Here is all the relationships you should need though only the belongsToMany ones are required for this specific scenario of finding all the teams in a season.
class Season extends Eloquent {
public function teams()
{
return $this->belongsToMany('Team', 'Standings');
}
public function standings()
{
return $this->hasMany('Standing');
}
}
class Team extends Eloquent {
public function seasons()
{
return $this->belongsToMany('Season', 'Standings');
}
public function standings()
{
return $this->hasMany('Standing');
}
}
class Standing extends Eloquent {
public function team()
{
return $this->belongsTo('Team');
}
public function season()
{
return $this->belongsTo('Season');
}
}
You would use the belongsToMany relationship rather than a hasManyThrough to query all the teams in a season. That would look something like...
Season::with('teams')->find($season_id);
foreach($season->teams as $team) {
echo $team->name;
}

Resources