Yii:何时使用单表继承.阐明用法和理解


Yii: When to use single table inheritance. Clarifying usage and understanding

假设我有一个在线商店,通过该商店,产品可以按整数数量或小数重量储存和销售。有不同类型的产品。并非所有项目都是相关的。我需要决定是将它们放在单独的表中(规范化),还是使用一种称为单表继承的技术,该技术使我能够将所有产品存储在同一个表中,但对每种类型的产品使用不同的模型类。

一个简单的例子是。

大米的库存是每公斤(十进制),而不是每粒(整数)。大米按公斤(十进制)出售,但你不能卖1.5个苹果(十进制)。

这就是单表继承的作用吗?还是我错过了它的作用?

数据库示例

CREATE TABLE `product` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`unit` varchar(100) NOT NULL,
`stock` decimal(10,3) NOT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `product` (`name`, `unit`, `stock`)
VALUES 
('Rice', 'Kilo', 10.00),
('Apple', 'Each', 500),
('Orange', 'Each', 230),
('Flour', 'Kilo', 55.3),
('Coke', 'Litre', 123.5);

型号(为简便起见,仅显示产品和Kilo单位类型)

class Product extends CActiveRecord {
    ...
        STUFF
    ...
    protected function instantiate($attributes)
    {
        switch($attributes['unit'])
        {
            case 'Kilo':
                $class='KiloUnit';
                break;
            case 'Each':
                $class='EachUnit';
                break;
            case 'Litre':
                $class='LitreUnit';
                break;
            default:
                $class=get_class($this);
        }
        $model=new $class(null);
        return $model;
    }
}
class KiloUnit extends Product {
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }
    public function defaultScope()
    {
        return array(
            'condition'=>"type='Kilo'",
        );
    }
    public function rules(){
        array('stock', 'numerical'),
    }
    public function attributeLabels()
    {
        return array('stock' => 'Kilo');
    }

模型"EachUnit"的规则类似

array('stock','numerical', 'integerOnly'=>true)

模型"EachUnit"的attributeLabel类似

return array('stock' => 'Quantity');

这样,如果我想使用所有产品,我可以使用以下内容:

$products = Product::model()->findAll();
foreach($products as $p)
{
   do something
}

如果我只想处理以公斤为单位的产品

$products = KiloUnit::model()->findAll();
foreach($products as $p)
{
   do something
}

我对单表继承做了更多的研究,因为我对这个词有点不熟悉,我认为这确实值得一个答案,而不是一堆评论。

当您有一组类似的对象需要持久化到数据库中时,单表继承就发挥了作用。您可以将对象拆分为单独的表,或者如果它们足够相似,您可以将它们全部保存在一个带有字段的表中,以标识哪个是哪个。对象之所以不同,是因为它们需要不同的处理或具有稍微不同的属性。在您的情况下,我不会认为不同的度量单位足够重要,可以称之为单表继承,但更一般地说,您可以按数量库存项目和按数量库存的项目,它们都具有相同的属性集,但处理库存或成本消耗的方法不同,所以我想从技术上讲,您可以将其称为单表继承。但我甚至认为这还不够重要,因为处理这两者的方法甚至相似。

这里有一个项目类的例子,您可能更符合这个概念。想想制造应用程序。在这种情况下,您有一些物品,有些是购买的,有些是制造的。这些物品共享许多相同的属性,但制造的物品会有一份材料清单,以及与制造过程有关的属性,而购买的物品会具有供应商,以及与购买过程相关的属性。很有可能所有这些属性都适合同一个表,有些属性对于购买的项目为null,有些属性对制造的项目为null,但使用单表继承,您可以用一个查询搜索所有项目,或者用一个知道其独特特性的类来处理它们。在这种情况下,您可以在连接上节省一些时间,并简化前端,因为差异要显著得多,而且SQL联合可能成本高昂。但只是针对不同的度量单位?可能没那么值钱。

这里有一个链接到Yii关于单表继承的文档。

我可能会改变的一件事是,您可以创建一个名为measurement的表,然后在产品表中存储一个measurement_id。然后,您可以将一些其他功能移到测量模型中,而不是将其放在产品模型中。然后,当您创建产品时,您可以轻松创建所有measurement选项的下拉列表。不过,我不知道在这种情况下一定有对错之分。