2014-09-19 35 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