3.9. Single Table Inheritance

SingleTableInheritance is a way to use a single database table for multiple similar, but separate, classes. There are pros and cons to this technique which we will not discuss here; we will only show how to use it in the Solar model system.

Let's say you have three kinds of content: reviews, articles, and wiki pages. Essentially, they all have the same data elements: an author name, a title, a "slug" for the URI, and the body text. With single table inheritance, you can use a single table to hold all these pieces of content, and at the same time use different classes to represent them so that you can have different methods for each kind of content.

3.9.1. Enable The Model

To enable single table inheritance, you add another column to indicate what class-name suffix to use for each row in the table. You then tell the model system what that column name is by setting the value of $_inherit_col, and the model will create the right kind of object for you when you fetch from it. (By default, the model will look for a column named inherit.)

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

Here is an example of a database table set up for single table inheritance; the table is called "contents".

Table 3.2. Example Single Table Inheritance Data
id inherit author title slug body
1 Articles pmjones Article Subject article-subject The text of the article.
2 Reviews bolivar Review Title review-title The text of the review.
3 Wikis gir Wiki Page Name Wiki_Page_Name The text of the wiki page.

3.9.2. Extend the Model

Now that we have a "contents" table and a model for it, we need to have models for the different inheritance types in it. Use make-model as you would with a regular table, but add a --extends flag to indicate that the new model classes should extend from our contents model.

$ ./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. Fetching

Fetching records and collections from inheritance models works just as with non-inheritance models. The classes will all use the same table as the parent model, but will automatically restrict themselves to rows of their own inheritance type.

<?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();

You can even fetch all inheritance types at once using the parent model; each record in the fetched collection will be instantiated as its proper inheritance type.

<?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. Creating and Saving

When you create or save a single-table inheritance record, the inheritance value is automatically set for you based on the model you created the record from.

<?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();


Local