1

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

一个简单的例子。

大米的储存量是每公斤(十进制)而不是每粒(整数)。大米将按公斤(十进制)出售,但您不能出售 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);

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

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”的属性标签类似于

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

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

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

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

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

2 回答 2

2

我对单表继承进行了更多研究,因为我对这个术语有点陌生,并且认为这确实值得一个答案而不是一堆评论。

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

这是一个项目类的例子,你可能更符合这个概念。想想制造应用程序。在这种情况下,您有一些物品,有些是购买的,有些是制造的。这些项目具有许多相同的属性,但制造的项目将具有材料清单和与制造过程有关的属性,而购买的项目将具有供应商以及与购买过程相关的属性。很可能所有这些属性都适合同一个表,有些属性对于购买的商品为空,有些对于制造的商品为空,但使用单表继承,您可以使用单个查询搜索所有商品,或进行交易与知道他们独特品质的班级一起。在这种情况下,您可以节省一些连接时间并简化前端,因为差异更加显着,而且 SQL 联合的成本可能很高。但只是针对不同的计量单位?可能不那么值得。

这是关于Single Table Inheritance的 Yii 文档的链接。

于 2013-07-19T17:22:37.207 回答
0

我可能会改变的一件事是您可以做的是创建一个名为的表,measurement然后将其存储measurement_id在您的产品表中。然后,您可以将一些其他功能移至测量模型,而不是将其放在产品模型上。measurement然后,当您创建产品时,您可以轻松创建所有选项的下拉菜单。我不知道在这种情况下一定有正确或错误的方式。

于 2013-07-19T13:14:21.287 回答