2014-09-19 44 views
1

我有四个型号:远处HasManyThrough

  1. 用户
  2. 客户
  3. 商店
  4. 机会

的关系被定义为这样的:

  • 用户的hasMany客户
  • 客户的hasMany商店
  • 商店的hasMany机会
  • 用户hasManyThrough存储,客户端(这工作)

的问题是,我试图访问用户 - >相关机会通过内置的Laravel关系,但似乎没有自定义Query或机会表上的额外user_id列允许直接访问(即使可以从Store-> Client关系中推断出来) )。如果可以避免,我也不是嵌套foreach循环的粉丝。

我的问题:

有没有办法去更深层次的原因,直接在这种情况下访问用户的机会?实际模型代码和所有相关的关系如下:

用户

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'); 
    } 
} 
+1

我不知道Laravell,但是从我的Java Persistance API体验中,我可以说你需要一个自定义查询来解决这个问题,或者正如你所提到的那样,直接使用用户和oportunity之间的关系。 – ITroubs 2014-09-19 16:41:24

+0

@ITroubs是的,这就是目前为止的样子。尽管如此,如果我可以吃我的蛋糕并且也吃它,那会很棒。 – maiorano84 2014-09-19 16:50:41

+0

你的'加入'的解决方案是最好的,你可以做。否则,您可以为这种情况创建自定义关系,这将像'hasManyThorugh'一样工作,但具有更多嵌套级别。 – 2014-09-21 08:23:03

回答

-1

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

但是,如果您不希望将用户和商机与外键链接,则可以创建自定义查询来处理此问题。只需添加一个“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; 
     } 
    } 

现在您可以访问机会一气呵成像realted给用户,

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

这将返回与用户ID为所有客户端的所有机会“1”。

+0

不知道为什么你被低估了。这不是一种不好的处理它的方式,但是分离出这样的模型查询将导致对数据库的多次查询,这可能会变得昂贵。 – maiorano84 2014-09-20 22:07:30

+0

另外,这不会真的起作用。用户有很多客户。客户有很多商店的机会(如我的原始示例所示)。这只会检索第一个客户端,而不是全部。我希望为给定的用户返回所有商机,而不管客户或商店。我认为你是对的,因为自定义查询是唯一可行的方法。 – maiorano84 2014-09-20 22:52:11

+0

如果您想要所有客户端的机会,那么您可以循环访问$ client数组并获取与该客户端关联的机会。同样,获取机会的数据需要被推入一个数组中,一旦循环结束,数组将被返回。通过这种方式,您将获得与具有相同用户标识的许多客户端相关联的一系列机会。是的,这是相当昂贵的。你必须做很多事情,并且会运行多个查询。因此,最佳解决方案是将用户和机会与外键链接。这样你就可以在一个查询中获得你想要的数据。 – user4055288 2014-09-21 04:38:03