2014-06-30 58 views
1

我用Eloquent來實現我的模型。它有很多方法可以讓模型的工作變得更容易。但是,在某些情況下,我必須實現訪問數據庫的功能,但不返回Eloquent模型。從哪裏可以得到與雄辯相關的SQL查詢

例如,設想一個常見的用戶模型。 Eloquent在用戶模型的CRUD操作中幫助我很多,但是如果我必須實現一種方法來返回一些關於用戶的統計信息(例如總共有多少用戶,多少活動用戶等),該怎麼辦?

我應該在哪裏實現此功能?在Eloquent模型中,作爲public static函數(例如User::getStats()),或者應該爲此具有不同的類。

將這些方法放在Eloquent模型上看起來有點不自然,因爲它們不是與Eloquent相關的。

+0

我在這種情況下使用存儲庫。存儲庫在構造函數中獲取User模型的一個實例。然後,我只與UserRepository一起工作,而不直接與User一起工作。 – Dave

+0

你在你的倉庫中有sql查詢,對吧? –

回答

1

一如既往,它取決於您的項目和用戶在其中扮演的角色。

但基本上,不,我不認爲構建報告的邏輯屬於用戶模型。雖然它可能與用戶有關,但對於SOLID原則,User類應該只有一個責任,在這種情況下是處理User實體。

這包含獲取和設置實例的屬性,在一個簡單的項目中,在模型上定義一些範圍可能也很好,例如,僅選擇活動用戶,例如User::getActive();

但隨着項目的增長,您應該考慮使用更具體的類。例如,您可以將Eloquent功能抽象爲User-Repository。所以,現在你有對entitiy本身操作的處理程序,像

$userRepo->getAll(); 
$userRepo->getActive(); 
$userRepo->getInactive(); 

,併爲用戶實例的句柄:

$user->getName(); 
$user->setStatus(); 

創建報表和統計又是一個完全不同的主題。所以,你可以有一些像UserReportBuilder奧德UserStatisticsService

$userStats->getMostActive(); 
$userStats->getRegistrationsPerDay(); 

一個簡單的例子:

// UserRepository:

class UserRepository 
{ 

    protected $model = $model; 

    public function __construct($model) 
    { 
    // you pass in an instance of the actual Eloquent model 
    // so you have the whole power of eloquent in here 
    $this->model = $model; 
    } 

    public function getActive() 
    { 
    // this returns a collection of models 
    return $this->model->where('status', 'active')->get(); 
    } 

} 

$userRepo = new UserRepo(new User); 

而這幾乎是它。你仍然可以使用Eloquent,但是你已經將部分功能與清晰的責任分開。所以,你的UserStats類將僅適用於構建用戶的統計數據是resposible:

class UserStats 
{ 
    // You could pass in the Repository through the constructor 
    // or just use the Eloquent model directly 

    public function getRegistrationsPerDay() 
    { 
     return User::groupBy('day')->get(
      [ 
       DB::raw('DATE(created_at) as day'), 
       DB::raw('count(*) as registration_count') 
      ] 
     ); 
    } 
} 

用戶實例或UserStats建設者不需要知道如何獲取所有用戶,和用戶實例或UserRepository不需要知道如何計算每天的註冊數量,因此將該功能分成獨立的,獨立的部分是完全合理的。

我想你明白了,我希望它有道理。也許你應該讓自己更熟悉SOLID-principles,並試着在遇到類似問題時記住它們。

+0

夢幻般的答案。爲我回答了更多的問題。 –

2

這真的取決於你,但是決定一個約定並堅持它是個好主意。

我的經驗法則是:

  1. 如果它涉及到的是通常由雄辯的模型表示一個單一的項目,這樣做是對模型中的公共靜態方法。例如,在我目前的項目中,我有一個Contract模型。我需要一種能夠爲新合同生成合同ID字符串(用於與舊系統兼容)的方法。這與單個項目(合同)有關,但由於技術原因需要與Eloquent模型分開生成(即它基於具有不同連接的單獨數據庫)。所以我創建了一個公共靜態方法:public static function generateContractIdentifier($id, $salesRep)。如果您使用存儲庫訪問數據庫,則可以將其放在那裏。

  2. 如果它更通用(即不與一個Eloquent模型的實例綁定),我把它放到一個單獨的庫中。例如,在同一個應用程序中,我有一個處理打印項目(工業過程)的隊列。該應用程序有一個儀表板,我需要顯示管理的當前隊列狀態。爲此,我創建了一個ProcessStatus庫,並實現了一個方法:public function getStatus(),它運行查詢並將結果作爲數組提供給視圖顯示。這與隊列中的任何特定項目無關,所以我將它放在單獨的庫中。