Yii:何时使用单表继承。澄清用法和理解

时间:2013-07-19 13:03:43

标签: php yii single-table-inheritance yii-cmodel

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

一个简单的例子就是。

  

每千克(十进制)储存大米,而不是每粒(整数)。   大米将按公斤(十进制)出售,但你不能卖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');
    }

和模型“EveryUnit”的规则类似于

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
}

2 个答案:

答案 0 :(得分:2)

我对单表继承做了一些研究,因为我对这个术语有点不熟悉,并且已经确定这确实值得回答而不是一堆评论。

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

以下是项目类的示例,您可能更符合此概念。想想制造业应用。在这种情况下,您有物品,有些是购买的,有些是制造的。这些物品共享许多相同的属性,但是制造物品将具有物料清单,以及与制造过程有关的属性,而所购买的物品将具有供应商,以及与购买过程相关联的属性。很可能所有这些属性都适合同一个表,有些属性对于购买的项目是null,而有些属性对于制造的项目是null,但是使用单表继承,您可以使用单个查询或交易搜索所有项目与他们一起了解他们独特的品质。在这种情况下,您可以在连接上节省一些时间并简化前端,因为差异更加明显,并且SQL联合会成本很高。但仅针对不同的计量单位?可能不值得。

以下是Single Table Inheritance上的Yii文档的链接。

答案 1 :(得分:0)

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