简体   繁体   中英

Relationship between 2 tables with a relationship table

I have 3 tables like the following diagram:

https://i.imgur.com/zL7ouGu.png

I created a relationship table between users and organizations

I would like to retrieve a collection with the list of organizations for each user.

Currently I am getting a collection in which a user comes back several times.

Collection {#226 ▼
  #items: array:4 [▼
    0 => {#232 ▼
      +"name": "GotExx"
      +"avatar_path": "gotexx.jpg"
      +"orga-name": "My orga 1"
      +"slug": "my-orga-1"
      +"orga-avatar": "myorga1_logo.png"
    }
    1 => {#228 ▼
      +"name": "GotExx"
      +"avatar_path": "gotexx.jpg"
      +"orga-name": "My orga 2"
      +"slug": "my-orga-2"
      +"orga-avatar": "myorga2_logo.png"
    }
    2 => {#234 ▼
      +"name": "GotExx"
      +"avatar_path": "gotexx.jpg"
      +"orga-name": "My orga 3"
      +"slug": "my-orga-3"
      +"orga-avatar": "myorga3_logo.png"
    }
    3 => {#233 ▼
      +"name": "root"
      +"avatar_path": null
      +"orga-name": "My orga 2"
      +"slug": "my-orga-2"
      +"orga-avatar": "myorga2_logo.png"
    }
  ]
}
select users.name, users.avatar_path, organizations.name, organizations.slug, organizations.avatar_path 
from relation_organization
right join users on relation_organization.user_id = users.id
left join organizations on relation_organization.organization_id = organizations.id

ideally I would like to get this:

Collection {#226 ▼
  #items: array:2 [▼
    0 => {#232 ▼
      +"name": "GotExx"
      +"avatar_path": "gotexx.jpg" 
      +"organizations" => {
        0 => {
          +"orga-name": "My orga 1"
          +"slug": "my-orga-1"
          +"orga-avatar": "myorga1_logo.png"
        }
        1 => {
          +"orga-name": "My orga 2"
          +"slug": "my-orga-2"
          +"orga-avatar": "myorga2_logo.png"
        }
        2 => {
          +"orga-name": "My orga 3"
          +"slug": "my-orga-3"
          +"orga-avatar": "myorga3_logo.png"
        }
      }
    }
    1 => {#232 ▼
      +"name": "root"
      +"avatar_path": "null" 
      +"organizations" => {
        0 => {
          +"orga-name": "My orga 2"
          +"slug": "my-orga-2"
          +"orga-avatar": "myorga2_logo.png"
        }
      }
    }
  ]
}

This is where Laravel really shines with relationships. Pull your users with an eager load with organizations all in one query. eg

$users = User::with('organizations')->get().  

Your $users will now have all users in the system, with their attached organizations, listed one time per user, as your question asks for.

If you want to limit the fields drawn as you had in your SQL , you can use select:

$users = User::select('avatar_path', 'name')->with(['organizations' => function($query){
      $query->select('name', 'slug', 'avatar_path );
}])->get().  

This all assumes you have the organizations relationship set up correctly on your Users model.

Laravel preferred way.

  1. Create models.
  2. Define relationships.
  3. Use eager loading when retrieving data.

Creating models and relationships.

User model

public class User extends Model
{
    public function organizations()
    {
        return $this->belongsToMany(Organization::class);
    }
}

Organization model

public class Organization extends Model
{
    public function users()
    {
        return $this->belongsToMany(User::class);
    }
}

Using eager loading when fetching.

Controller function

$usersWithOrganizations = User::with('organizations')->get();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM