我目前正试图弄清楚如何正确实施MVC原则。让我们举一个简单的博客。我有一个包含两个表的数据库:博客和评论。博客表包含标题,内容,日期等字段。评论包含自动名称,日期,内容等。
让我们从更简单的项目开始。我有几点看法。像:
控制器对我来说也很清楚:
然后是模特。我真的不知道应该如何实现这些。 Zend Framework快速入门页面推荐了一个非常小的模型,它只包含私有属性以及特定项的getter和setter。他们建议在Mapper中使用数据库逻辑。
但这是我的问题。假设我想要获取最新的博客项目。你会如何实现这个?你在哪里写函数fetchRecentItems()?在映射器中?似乎这应该只包含基本的CRUD语句。在另一个模型中,比如BlogService?在控制器?
有人可以帮助我吗?我很想看到一个快速的伪代码示例。
(我试着总结一下我的知识,让我的思考过程更加清晰。如果我理解错了,请纠正我。谢谢!)
答案 0 :(得分:5)
这取决于你真正想要走多远。我个人会使用一个Service类,与映射器类交互,从控制器调用。所以你的课可能看起来像:
class Yourapp_Service_Blog
{
protected $_mapper;
public function setMapper($mapper)
{
$this->_mapper = $mapper;
return $this;
}
public function getMapper()
{
return $this->_mapper;
}
public function fetchRecentItems($items)
{
$select = $this->getMapper()->getDbTable()->select();
$select->order('createdAt DESC')
->limit($numItems);
return $this->getMapper()->fetchAll($select);
}
}
然后在你的控制器中:
class BlogController extends Zend_Controller_Action
{
public function indexAction()
{
$service = new Yourapp_Service_Blog();
$service->setMapper(new Yourapp_Model_GuestbookMapper());
$this->view->posts = $service->fetchRecentItems(6);
}
}
这开始看起来像很多代码来做一件简单的事情,但是当你开始看到类之间的共同元素时,你可以重构一点来改进。例如。如果您有多个看起来像这样的服务类,您可以将get / set映射器函数移动到它们扩展的基本服务类中。您可以向getMapper()函数添加一些逻辑,如果没有提供正确的映射器,它将根据类名确定正确的映射器,从而节省您每次都必须传递它。
这里没有“正确”的答案,这些模式作为常见编程问题的解决方案而存在。根据您认为适合您的应用的情况,尽可能多地使用它们。
答案 1 :(得分:2)
完全同意服务层的想法,尽管它实际上取决于什么对你有用。
我们的方法是使用这样一个层作为下面的螺母和螺栓的外观 - 它以一种对必须对其进行编码的人有意义的方式描述我们的应用程序API。针对此API的编码可以使用户隐藏他们不关心的内容,例如数据存储和检索。
我们对这种方法的好处是它在语义上有意义,正确的关注点分离使控制器变薄并确保模型的可移植性(不是我曾经不得不使用它,但谁知道) ,它易于测试,可扩展 - 我们可以轻松地在顶层构建其他层(例如Web服务)等。
我听说你来自哪里,就像我不久前在那里一样。很长一段时间,我对如何使用Zend Framework实现模型感到困惑。我正在寻找一个约定或某人来描述它应该如何完成。
随着时间的推移我学到的是没有正确的答案,这就是ZF绝对认可的地方。当没有“一刀切”的方法时,规定一种机制是没有意义的。
总之,没有“适当”的方式来实现该模型。正如我所说,我认为这只是为了找到适合自己情况的事情。
我建议Google使用“Zend Framework Service Layer”并尽可能多地阅读 - 我认为您可能对此感兴趣。很多时候你最终都会回到Stack Overflow,但通常也有好的博客文章和文章链接。
祝你好运。答案 2 :(得分:1)
开发MVC应用程序不仅有一种方法。一般来说,控制器,视图和模型应该是或应该做什么,有很多不同的方法。
我想一个好主意是看看其他人是如何做到的。
看看CakePHP: Models / Views / Controllers
通常,控制器将数据放入模型中(或创建模型),视图使用该模型来呈现页面。