Dav*_*ave 6 php oop model-view-controller design-patterns
我在这里贴了一个幽灵,这让我感到沮丧多年.这是一个关于如何构建正确的模型,正确的对象的问题.
让我解释.假设我有一篇文章.文章有标题,评级,正文和评论.
Comment类包含作者,时间戳,文本.
文章可以有0个或更多评论.到现在为止还挺好.这个概念没问题.但...
这是我感到困惑的地方,因为我不需要加载评论信息,当我有大量文章和大量评论时,这会产生显着的性能差异.
我应该建两个型号吗?一个用于Article,一个用于ArticlesInList?我应该将评论的负载委托给延迟模式(这是可能的),只在必要时检索它们吗?
面对和解决这个问题的正确方法是什么?
谢谢.
尝试对业务对象进行建模时需要做出很多权衡。
根据您的示例,我可以想到一些方法,主要围绕延迟加载注释。如果我相当确定事情不会变得更复杂,我会这样做:
首先,为文章和评论创建实体,它们仅表示数据库中每个表中的数据。编写 setter 和 getter。在 Article 上实现 loadComments() 方法。
实现一个或多个 Collection 类,例如 ArticleCollection。您可能有一个服务类来获取符合某些条件的文章。ArticleService::fetchArticles() 将返回没有加载评论的文章。然后实现 ArticleCollection 的 loadComments() 方法,该方法加载集合中所有文章的所有评论。起初,这只能迭代调用 loadComments 的文章——但您可以稍后用单个查询实现替换它。
这是文章和文章集合的开头。如果您实现 CommentCollection 类,您可以在 Article 内使用它来保存评论等。
<?php
/**
* Extends a base model class that provides database-related methods -- not ideal,
* but trying to stay focused here.
*/
class Article extends Model {
private $_data;
private $_fields = array('id','title','body','author');
/**
* Constructor can take an array of values to initialize.
*/
public function __construct($data=null){
if (is_array($data)){
foreach($this->_fields as $field){
$this->_data[$field] = $data[$field];
}
}
}
public function getId(){ return $this->_data['id']; }
// more getters, and setters, here.
public function loadComments(){
$result = $this->query('SELECT * FROM Comment WHERE article_id = ' . $this->getId());
$this->_comments = array();
foreach($result as $c){
//instantiate a new comment (imagine Comment's constructor is very similar to Article's
$this->_comments[] = new Comment($c);
}
}
}
class ArticleCollection extends Model {
/**
* An array of Articles, indexed by article_id
*/
private $_articles = array();
/**
* Naive implementation. A better one would grab all article IDs from $this->_articles, and
* do a single query for comments WHERE article_id IN ($ids), then attach them to the
* right articles.
*/
public function loadComments(){
foreach($this->_articles as $a){
$a->loadComments();
}
}
/**
* Add article to collection
*/
public function addArticle(Article $article){
if (empty($article->id)) throw new \Exception('Can\'t add non-persisted articles to articlecollection!');
$this->_articles[$article->id] = $article;
}
}
Run Code Online (Sandbox Code Playgroud)
上面的内容非常基本——例如,您可以应用其他设计模式来分解数据库访问,这样它就不会那么紧密耦合。但我只是想描述一种以理智的方式延迟加载评论的策略。
最后的一些建议:不要陷入许多框架所做的陷阱,并认为数据库中的表和模型之间存在某种神圣的相关性。模型只是对象。它们可以做不同种类的事情(代表评论或用户等简单事物),或者代表对这些简单事物进行操作的服务之类的事物,或者它们可以是这些个体事物的组(集合)之类的事物。
一项有趣的练习是编写类,并用虚拟数据填充它们。尽最大努力完全忘记将涉及数据库。制作支持您所需用例的对象。然后,完成后,弄清楚如何将数据保存到数据库或从数据库加载数据。