保持您的視圖儘可能少邏輯,不要讓邏輯混亂你的控制器。對大多數人來說,這意味着將所有的邏輯填充到模型中。這又不是一種有助於編寫可重用且更重要的可測試代碼的方法。
Laravel的IoC容器和依賴注入功能非常強大,應該用於以可測試的方式構建您的應用程序。
我可以理解你爲什麼還想傳遞查詢對象,這是我在模型中用來做的事情。這似乎很有意義,但很快就會發現,使用強大的查詢生成器創建一個嚴格的查詢生成器會創建一些溼代碼。
我的建議是儘可能保持模型苗條,使用它們來創建關係,設置雄辯屬性,驗證規則數組等等。基於接口將所有邏輯抽象爲存儲庫。爲什麼?那麼,接口可以通過IoC綁定到它應該解析的類上,這意味着它可以被依賴注入並輕鬆地交換出來(例如Mockery),同時在您可能想要構建的任何替換中保持結構完整性(Mongo,CouchDB等等實現)。
namespace Repositories;
interface TransactionInterface {
public function findAll();
public function findById($id);
public function findByDaysAhead($start = 0, $end = 1)
}
而對於倉庫
namespace Repositories;
use Transaction;
class TransactionEloquent implements TransactionInterface {
public function findAll()
{
return Transaction::all();
}
public function findById($id)
{
$transaction = Transaction::find($id);
if (! $transaction)
{
throw new Exception("Transaction not found");
}
return $transaction;
}
public function findByDaysAhead($start = 0 , $end = 1)
{
// Create one query to return all the data you need
}
}
然後,您可以綁定該存儲庫中的一個新的自定義的ServiceProvider或在您的routes.php
。
App::bind('Repositories\TransactionInterface', 'Repositories\TransactionEloquent');
現在,您可以依賴注入您的控制器的接口,將解析您的雄辯的實現。如果你寫一個不同的存儲庫實現,你可以簡單地把它重新綁定到接口意味着它會被用於任何接口注入(嘲弄類爲例)
class ApplicationController extends BaseController {
public function __construct(Repositories\TransactionInterface $interface)
{
$this->repo = $interface;
}
public function getIndex()
{
return View::make('index', array('transactions' => $this->repo->findAll());
}
}
在你看來,你只會在需要一個簡單的循環你的數據和輸出,不需要邏輯。
很明顯,你可以把儘可能多的邏輯,你的倉庫喜歡的,你可以看到你的控制器,模型和視圖履行只有他們打算爲責任(OOPS單一職責原則)
這是一個非常什麼是一個非常複雜的問題的簡短答案。我希望這會指導您在Laravel編寫可測試和可重用的模塊化代碼。
一些 '輕' 讀
在哪裏放置文件等
繼PSR-0規範我最終會得到這樣的
- app
- {name of app}
- Repositories
* TransactionInterface.php
* TransactionEloquent.php
結構這兩個文件的命名空間,現在是namespace {name of app}\Repositories
在作曲家中,您可以將其添加到自動載入對象:
"psr-0": {
"{name of app}" : "app/"
}
這都將PSR-0兼容的命名空間添加到自動加載,當你做出改變,你可以使用
composer dump-autoload
重建磁帶自動加載機,包括新的文件(並不總是需要的,但是是更好,更快比composer update
不斷)。
有多少存儲庫?
我通常最終得到每個模型1+存儲庫。例如,我在前端有一個模型和個人模型的骨幹集合。
使用Backbone.sync(param, collection)
將始終使用一個處理輸入作爲模型數組的回購。 Backbone.sync(param, model)
將使用處理髮送的單個模型的回購。我也有兩個Laravel資源控制器來處理這個問題。
服務提供商
我把這些在我的應用程序文件夾路徑,我的應用程序在這種情況下
- MFL
- Repositories
- MFLServiceProvider.php
我config\app.php
內容添加到我的服務提供商陣列稱爲「MFL」
namespace MFL;
use Illuminate\Support\ServiceProvider;
class MFLServiceProvider extends ServiceProvider {
public function register()
{
// Register bindings here, don't use other service providers here
// you can't be sure they are loaded as of yet
$this->app->bind('MFL\Repositories\TransactionInterface', 'MFL\Repositories\TransactionEloquent');
}
public function boot()
{
// Do anything else here with assurance all service providers are
// fully loaded and the application is ready
}
}
使用此方法,您不會污染routes.php
與IoC綁定和喲你可以從邏輯上將你的所有代碼分割成服務。這是我後一種理由的首選方法。
這個答案聽起來正是我一直在尋找。對於前兩個代碼片段,我應該在哪裏放置這些代碼片段?我如何確保他們正確加載?你會建議擁有許多'存儲庫',每個模型一個?最後,「您可以將這個存儲庫綁定到一個新的自定義ServiceProvider中」 - 這兩件事是完全相同的,還是有理由選擇另一個呢?非常感謝! –
@我傾向於在'/ app'內創建一個新的文件夾,其中包含我的應用程序的命名空間,遵循PSR-0規範。然後我使用作曲家PSR-0加載功能。我會爲你添加這個和更多的答案。 –