在尝试为业务对象建模时,需要进行许多权衡.
举个例子,我可以想到一些方法,主要围绕延迟加载注释.如果我有理由相信事情不会变得更复杂,我就是这样做的:
首先,为Article和Comment创建实体,它们只表示数据库中每个表中的数据.写二传手和吸气剂.在Article上实现loadComments()方法.
实现一个或多个Collection类,例如ArticleCollection.您可能有一个服务类可以获取符合某些条件的文章. ArticleService :: fetchArticles()将返回没有加载注释的文章.然后实现ArticleCollection的loadComments()方法,该方法加载集合中所有文章的所有注释.首先,这可以迭代调用loadComments的文章 – 但您可以稍后用单查询实现替换它.
这是Article和ArticleCollection的开头.如果您实现了CommentCollection类,则可以使用Article内部来保存注释等.
/**
* 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;
}
}
以上是非常基本的 – 您可以应用其他设计模式来分解您的数据库访问,因此它不是那么紧密耦合.但我只是想以一种理智的方式描述一种懒惰加载你的评论的策略.
最后一些建议:不要陷入许多框架所做的陷阱,并认为数据库和模型中的表之间存在一些神圣的相关性.模型只是对象.他们可以做不同类型的事情(代表一个简单的事情,如评论或用户),或代表像服务于这些简单事物的服务,或者它们可以是诸如个别事物的组(集合)之类的事物.
一个有趣的练习就是编写类,并用虚拟数据填充它们.尽力完全忘记涉及数据库.支持您需要的用例的工艺对象.然后,完成后,找出如何将数据保存到数据库或从数据库加载数据.