最近我开始研究Laravel 4
及其功能。我想实现Repository模式以在那里移动模型逻辑。在这一点上,我面临着一些如何组织它的不便或误解。一般问题我有这样的事情:是否有可能实现和应用这种模式在Laravel
没有头痛,并且它是否值得?使用Laravel实现库模式
这个问题会被分成几个部分,这引起了我的困惑。
1)Laravel提供了将模型绑定为控制器参数的方便方式,例如,我做这种方式:
// routes.php
Route::bind('article', function($slug)
{
return Article::where('slug', $slug)->first();
});
Route::get('articles/{article}', '[email protected]');
// controllers/ArticlesController.php
class ArticlesController extends BaseController {
public function getArticle(Article $article)
{
return View::make('article.show', compact('article'));
}
}
如果我想使用Repository
模式,那么我不能使用这种方法,因为在这种情况下,控制器将清楚地了解车型Article
存在? 无论将是正确的重新写该示例中使用Repository模式这样:
// routes.php
Route::get('articles/{slug}', '[email protected]');
// controllers/ArticlesController.php
class ArticlesController extends BaseController {
private $article;
public function __construct(ArticleRepository $article) {
$this->article = $article;
}
public function getArticle($slug)
{
$article = $this->article->findBySlug($slug);
return View::make('article.show', compact('article'));
}
}
2)假设,我的代码与上面使用的Repository
是正确的。现在,我想在每次显示文章视图计数器时增加文章视图,但是,我想在Event
中进行此处理。也就是说,代码如下:
// routes.php
Route::get('articles/{slug}', '[email protected]');
// controllers/ArticlesController.php
class ArticlesController extends BaseController {
private $article;
public function __construct(ArticleRepository $article) {
$this->article = $article;
}
public function getArticle($slug)
{
$article = $this->article->findBySlug($slug);
Events::fire('article.shown');
return View::make('articles.single', compact('article'));
}
}
// some event subscriber
class ArticleSubscriber {
public function onShown()
{
// why implementation is missed described bellow
}
public function subscribe($events)
{
$events->listen('article.shown', '[email protected]');
}
}
在这一点上我再次对如何实现事件处理感到困惑。我无法直接将$article
模型传递给事件,因为它再次违反了OOP的原则,我的订阅者将知道文章模型的存在。所以,我不能这样做:
// controllers/ArticlesController.php
...
\Events::fire('article.shown', $article);
...
// some event subscriber
...
public function onShown(Article $article)
{
$article->increment('views');
}
...
在另一方面,我没有看到任何意义,引入subscriber
库ArticleRepository
(或用户的构造器注入的话),因为首先我应该找一个文章,然后更新计数器,最终,我会得到额外的查询(在构造函数之前,因为我这样做)到数据库:
// controllers/ArticlesController.php
...
Events::fire('article.shown', $slug);
...
// some event subscriber
...
private $article;
public function __construct(ArticleRepository $articleRepository)
{
$this->article = $articleRepository;
}
public function onShown($slug)
{
$article = $this->articleRepository->findBySlug($slug);
$article->increment('views');
}
...
此外,处理的Event
后(即增加的观看次数) ,控制器必须知道更新的模型,因为在视图中我想显示更新的视图计数器。事实证明,我仍然需要从Event
返回一个新的模型,但我不想Event
已成为处理特定操作(为此有存储库),并返回一些价值的常见方法。此外,您可能会注意到我的最后onShow()
方法再次违背Repository
模式的规则,但我不知道如何把这个逻辑到仓库:
public function onShown($slug)
{
$article = $this->articleRepository->findBySlug($slug);
// INCORRECT! because the Event shouldn't know that the model is able to implement Eloquent
// $article->increment('views');
}
我可以以某种方式通过发现模型回到仓库并增加她的柜台(这与Repository
模式的方法相矛盾吗?)?事情是这样的:
public function onShown($slug)
{
$article = $this->articleRepository->findBySlug($slug);
$this->articleRepository->updateViews($article);
}
// ArticleRepository.php
...
public function updateViews(Article $article) {
$article->increment('views');
}
...
结果,我会尽量制定所有更紧凑:
我不得不拒绝直接传递模型,由DI提供的控制器和其他设施如果我将使用
Repository
模式?是否可以使用存储库来存放模型的状态,并通过它的实体之间(例如,从过滤器控制器从控制器到
Event
和背面)避免淫秽重复调用数据库,是这方法将是正确的(模型持久性)?
这样的事情,这些是我的问题。我想听听答案,想法和意见。也许,我应用模式的方法不正确?现在它比解决数据映射问题更令人头疼。
此外,我读过有关仓库实现的一些文章:
- http://heera.it/laravel-repository-pattern#.VFaKu8lIRLe
- http://vegibit.com/laravel-repository-pattern
,但它并没有解决我的误解