web-dev-qa-db-ja.com

Laravelネストされた関係

たくさん laravelで正しく動作するために非常にネストされた関係を得るのに問題があります。

必要な動作は次のとおりです。

IDでイベントを選択し、どのユーザーがサブスクライブしているのかを確認したい問題は、イベントとユーザーの間にいくつかのテーブルがあることです.

これが機能するクエリです!

SELECT persons.id, 
       persons.firstname, 
       persons.lastname, 
       event_scores.score 
FROM   events 
       JOIN cities 
         ON cities.id = events.city_id 
       JOIN companies 
         ON cities.id = companies.city_id 
       JOIN persons 
         ON companies.id = persons.company_id 
       JOIN event_scores 
         ON event_scores.person_id = persons.id 
WHERE  event_scores.event_id = 1 
GROUP  BY persons.id 

これらは私の関係です

イベントモデル

class Event extends Eloquent
{
    protected $table = 'events';

    public function city()
    {
        return $this->belongsTo('City');
    }
}

都市モデル

class City extends Eloquent
{
    protected $table = 'cities';

    public function companies()
    {
        return $this->hasMany('Company');
    }

    public function event()
    {
        return $this->hasMany('Event');
    }
}

会社モデル

class Company extends Eloquent {

    protected $table = 'companies';

    public function persons()
    {
        return $this->hasMany('Person');
    }

    public function city()
    {
        return $this->belongsTo('City');
    }
}

人物モデル

class Person extends Eloquent
{
    protected $table = 'persons';

    public function company()
    {
        return $this->belongsTo('Company');
    }

    public function eventscore()
    {
        return $this->belongsToMany('Event', 'event_scores', 'person_id', 'event_id')
            ->withPivot('score')
            ->withTimestamps();
    }
}

私が試したこと

return Event::with('city')->with('company')->get();

そして

return Event::with('city')
    ->whereHas('companies', function($query) use ($company_id){
        $query->where('company_id', $company_id);
    })->get();

そして、他の多くの可能性、私は本当にこれに固執しています。 laravelでは、この種のネストされた関係のリンクを実現するのは難しいですか?

ありがとう!

31
Notflip
return Event::with('city.companies.persons')->get();

personsテーブルから特定のフィールドのみを選択する場合、これを使用します。

return Event::with(['city.companies.persons' => function ($query) {
    $query->select('id', '...');
}])->get();
74
Joseph Silber

都市および企業固有のフィールドについては、雄弁に配布する必要があります。例えば:

return Event::with([
    'city' => function ($query) {
        $query->select('id', '...');
    },
    'city.companies' => function ($query) {
        $query->select('id', '...');
    },
    'city.companies.persons' => function ($query) {
        $query->select('id', '...');
    }
])->get();
16
Rashmi Nalwaya

次のような場合にHasManyThrough関係を作成しました。 GitHubのリポジトリ

インストール後、次のように使用できます。

_class Event extends Model {
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function persons() {
        return $this->hasManyDeep(
            Person::class,
            [City::class, Company::class],
            ['id'],
            ['city_id']
        );
    }
}
_

withIntermediate()を使用して、中間テーブルから属性を取得できます。

_public function persons() {
    return $this->hasManyDeep(
        Person::class,
        [City::class, Company::class],
        ['id'],
        ['city_id']
    )->withIntermediate(City::class, ['id', '...']);
}
_
1

@ rashmi-nalwayaの答えを展開します。 5.8のプロジェクトでいくつかの調整を加えて動作させました。

HasManyではなく、hasOneリレーションを参照しようとしているため、私の例は少し異なりました。

したがって、参照のために、ドメインは1つのWebサイトに属し、1つのWebサイトは1つのサーバーに属します。これらすべてのテーブルから特定の列のみを返したいと思いました。私はこれをしなければなりませんでした。

Domain::with([
    'website' => function($q){
        $q->select('id', 'server_id');
    },
    'website.server' => function($q){
        $q->select('id', 'hostname', 'nickname');
    }
])
    ->select('id', 'website_id', 'domain')
    ->get();

私がいつでもオンにしているテーブルのプライマリキー(私の場合はid)を通過し、次に、取得しようとしている関連テーブルの外部キーを必ず通過させなければなりませんでしたに。そう website_idドメインから、およびserver_idウェブサイトから。その後、完全に機能しました。

私のコードには、メインドメインのwhere句もあります。

0
John Halsey