遥远的HasManyThrough

时间:2014-09-19 16:04:38

标签: php mysql laravel eloquent has-many-through

我有四个模特:

  1. 用户
  2. 客户端
  3. 存储
  4. 有机会
  5. 关系定义如下:

    • 用户拥有多个客户
    • 客户端拥有多家商店
    • 商店有很多机会
    • 用户hasManyThrough Store,Client(可行)

    问题在于我试图通过内置的Laravel关系访问User-> Opportunity关系,但是如果没有自定义查询或其他user_id列,我似乎无法做到这一点。机会表允许直接访问(即使可以从Store-> Client关系推断出)。如果可以避免,我也不是嵌套foreach循环的粉丝。

    我的问题:

    在这种情况下,有没有办法更深入一级并直接访问用户的机会?实际的Model代码和所有相关关系如下:

    用户

    class User extends Eloquent{
        public function clients(){
            return $this->hasMany('Client');
        }
        public function stores(){
            return $this->hasManyThrough('Store', 'Client');
        }
        public function proposals(){
            return $this->hasMany('Proposal');
        }
        public function opportunities(){ //This does the job, but I feel like it could be better
            return Opportunity::join('stores', 'stores.id', '=', 'opportunities.store_id')->
                                join('clients', 'clients.id', '=', 'stores.client_id')->
                                join('users', 'users.id', '=', 'clients.user_id')->
                                select('opportunities.*')->
                                where('users.id', $this->id);
        }
        public function getOpportunitiesAttribute(){ //This just helps mimic the hasManyThrough shorthand
            return $this->opportunities()->get();       
        }
    }
    

    客户端

    class Client extends Eloquent{
        public function stores(){
            return $this->hasMany('Store');
        }
        public function user(){
            return $this->belongsTo('User');
        }
        public function opportunities(){
            return $this->hasManyThrough('Opportunity', 'Store');
        }
    }
    

    商店

    class Store extends Eloquent {
        public function client(){
            return $this->belongsTo('Client');
        }
        public function opportunities(){
            return $this->hasMany('Opportunity');
        }
    }
    

    有机会

    class Opportunity extends Eloquent {
        public function store(){
            return $this->belongsTo('Store');
        }
    }
    

2 个答案:

答案 0 :(得分:0)

我不认为Laravel有这样的方法。您必须创建自定义查询。此自定义查询可能非常昂贵,因为将执行多个查询。因此,根据我的说法,最佳解决方案是将用户和机会与外键相关联。

但是,如果您不希望使用外键链接User和Opportunity,则可以创建自定义查询来处理此问题。只需添加一个" hasManyThrough"机会与客户模型之间的关系,如

    <?php
    class Client extends Eloquent{
        public function store(){
            return $this->hasMany('Store');
        }
        public function user(){
            return $this->belongsTo('User');
        }

        public function opportunity(){
            return $this->hasManyThrough('Opportunity', 'Store');
        }
    }

然后在用户模型中创建一个静态函数。

    <?php

    class User extends Eloquent implements UserInterface, RemindableInterface {

        use UserTrait, RemindableTrait;

        public function client(){
            return $this->hasMany('Client');
        }
        public function store(){
            return $this->hasManyThrough('Store', 'Client');
        }

        public static function getOpportunityOfUser($userId)
        {
             $clients = User::find($userId)->client;

            foreach ($clients as $client) {
                $opportunities[] = Client::find($client->id)->opportunity;
            }

            return $opportunities;
        }
    }

现在,您可以一次性访问向用户公开的商机,

    Route::get('/', function()
    {   
         return $usersOpportunities = User::getOpportunityOfUser(1);
    });

这将返回与ID为&#39; 1&#39;的用户相关的所有客户的所有机会。

答案 1 :(得分:0)

我创建了一个HasManyThrough级的无限关系:Repository on GitHub

安装后,您可以像这样使用它:

class User extends Model {
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function opportunities() {
        return $this->hasManyDeep(Opportunity::class, [Client::class, Store::class]);
    }
}