3.9 单表继承

SingleTableInheritance提供了多个相似但独立的类使用一个数据库表的途径。我们不在这讨论这种技术的优缺点,我们只是演示如何在Solar模型系统中使用这种技术。

假设你有三种类型的内容:评论、文章和wiki页面。从本质上讲,它们使用相同的数据元素:作者名、标题、友好的URI地址和内容体。使用单表继承,你可以用一张表保存这些内容,同时用不同的类来表示它们,且对每种内容使用不同的方法。

3.9.1 启用单表继承

为了启用单表继承,你要另外添加一个字段来指明数据表中每一行记录使用哪个类名后缀。然后,你将通过设置$_inherit_col属性的值告诉模型系统刚才添加的字段的名字。这样的话,当你获取数据时,模型会为你创建正确的对象。(默认情况下,模型会查找inherit字段)

<?php
class Acme_Model_Contents extends Acme_Sql_Model
{
    protected method _setup()
    {
        $this->_inherit_col = 'inherit';
    }
}

下面是一个数据表建立单表继承的示例;表名是"contents"。

Table 3.2. 单表继承示例数据

idinheritauthortitleslugbody
1ArticlesRoy GuArticle Subjectarticle-subjectThe text of the article.
2ReviewsSanakanReview Titlereview-titleThe text of the review.
3Wikisz.sjWiki Page NameWiki_Page_NameThe text of the wiki page.

3.9.2 继承模型

现在,我们有一张表"contents"以及对应的模型,我们必须要建立不同继承类型的模型。就像你处理正常的数据表一样,这里我们也使用make-model命令,但是要添另--extends标志,用于指明新建的模型类继承自contents模型。

$ ./script/solar make-model Acme_Model_Articles --extends Acme_Model_Contents
...
$ ./script/solar make-model Acme_Model_Reviews --extends Acme_Model_Contents
...
$ ./script/solar make-model Acme_Model_Wikis --extends Acme_Model_Contents
...
$

3.9.3 获取数据

从继承模型获取记录或记录集就像从非继承模型获取一样。这些类和父模型使用同一张数据表,但是它们会自动限制使用本继承类型的数据行。

<?php
/**
 * @var $model Solar_Sql_Model_Catalog
 */

// fetch all "articles" records from the "contents" table
$only_articles = $model->articles->fetchAll();

// fetch all "reviews" records from the "contents" table
$only_reviews = $model->reviews->fetchAll();

// fetch all "wikis" records from the "contents" table
$only_wikis = $model->wikis->fetchAll();

你甚至可以使用父模型一次性获取所有的(继承类型)数据;记录集中的每个记录都会被实例化为合适的继承类型对象。

<?php
/**
 * @var $model Solar_Sql_Model_Catalog
 */

// fetch all records of all inheritance types from the "contents" table
$list = $model->contents->fetchAll();

// get each record from the collection
foreach ($list as $item) {
    // each item in the collection uses its own
    // inheritance class type
    echo get_class($item) . '<br />';
}

3.9.4 创建和保存

当你创建或保存一个单表继承类型的记录时,记录的继承值会根据你创建记录的模型自动填充。

<?php
/**
 * @var $model Solar_Sql_Model_Catalog
 */

// create a new pre-populated article.
$article = $model->articles->fetchNew(array(
    'author' => 'pmjones',
    'title'  => 'A New Article',
    'slug'   => 'a-new-article',
    'body'   => 'The body of the new article.',
));

// when we save, the property "inherit = 'Article'"
// will be set automatically for us.
$article->save();