我最近在我的CodeIgniter应用程序中深入研究使用ORM,而我所使用的是Propel。现在,这给了我基本上使用Propels类作为'模型'的能力,但这是不好的实践?
所以我的控制器代码如下:
<?php
class Page extends Controller {
function __construct() {
parent::__construct();
}
function index() {
$foo = FooQuery::create()->limit(10)->find();
$data['content'] = array('foo'=>$foo);
$this->load->view('home', $foo);
}
}
?>
我想在继续开发我的应用程序之前解决这个问题。如果你认为这是一个不好的做法,我应该如何做到这一点非常有用。
提前致谢
答案 0 :(得分:7)
是的,这是不好的做法。
模型应包含所有数据逻辑,并将其全部抽象出程序的其余部分。对于应用程序的其余部分,模型应该看起来像黑盒子,它从中获取数据。如果您使用ORM作为模型,则需要leaking the abstraction并将控制器与数据层紧密耦合。
相反,创建模型,并在那里处理ORM。这样,如果您需要调整数据模型,您可以在一个地方(模型层)更改它,并知道抽象将保留。
答案 1 :(得分:4)
使用Propel现在使用的Query
类,我认为与更“正式”模型的区别变得越来越小。如果这将成为您向世界发布的库,那么拥有一个抽象层以便拥有不同的后端将是一个优势,但如果它是一个内部应用程序,我只会使用Query
类作为你的模特。
但请记住,Query
类被创建为感觉像一个实际的对象,并且它们尽可能地隐藏关系部分。你可以利用这个优势。查看this article about rewriting your SQL queries with Query
methods,尤其是第三个答案:越来越多地进入Query
课程,因此您的Controller不会觉得它使用数据库。
// Instead of this code in your controller,
// tightly coupled to your database logic
$books = BookQuery::create()
->filterByTitle('%war%')
->filterByPrice(array('max' => 10)
->filterByPublishedAt(array('max' => time()))
->leftJoin('Book.Author')
->where('Author.Name > ?', $fameTreshold);
// You would use this code in your controller
// and create small methods with the business logic in the BookQuery class
$books = BookQuery::create()
->titleContainsWord('war')
->cheap()
->published()
->writtenByFamousAuthors();
答案 2 :(得分:0)
当你的ORM遵循Active Row模式时,我发现这是偶然的必然之恶。
我经常遇到的问题是模型只代表数据结构的单个实例。将集合检索方法添加到模型中是没有意义的。
这是我历史上使用服务层来处理拉入模型集合的地方。虽然最近老实说我只是写了一个控制器助手对象,它只是抽象我的表对象。
答案 3 :(得分:0)
这很大程度上取决于你在做什么以及为什么。在这个例子中,您在查询中放置了一个限制子句 - 是业务还是显示逻辑?从我的角度来看,很难说它的业务逻辑 - 我得到的10个元素与模型无关 - 这就是我认为在一个页面中使用的数量有多少。如果您希望该规则在控制器之间保持一致,则可以设置一些配置值以强制执行一致性。但是把它放在模型中只会使模型变得不必要(脂肪模型和肥胖模型之间存在差异)
我会说限制,订单和抵消通常不是业务逻辑。即使是一个简单的地方可能会或可能不会取决于具体情况。如果那里有一个连接,那就表明出现了问题。
Jan Fabry的例子非常好。 filterByTitle看起来和titleContainsWord一样。 filterByPublishedAt(array('max'=&gt; time()))比 - &gt; published()差得多。通常,控制器需要了解内部数据结构越少越好。