2013-07-19 27 views
1

假設我有一個網上商店,產品按照整數或小數重量進行庫存和銷售。有不同類型的產品。並非所有項目都是相關的。我需要決定是否應該將它們放在單獨的表中(標準化),還是使用稱爲單表繼承的技術,該技術使我可以將所有產品存儲在同一個表中,但對每種產品使用不同的模型類。Yii:何時使用單表繼承。澄清使用和理解

一個簡單的例子。

水稻將被存放每公斤(十進制),而不是每粒(整數)。 大米會以公斤(十進制)出售,但不能賣出1.5個蘋果(十進制)。

這是單表繼承或我錯過了它是什麼點?

DB實施例

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) 

和attributeLabel爲模型「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 
} 

回答

0

有一件事我可能會改變的是你可以做的是創建一個表名爲measurement然後存儲在measurement_id你的產品表。然後,您可以將其他一些功能移至「測量」模型,而不是將其放在「產品」模型上。然後,當您創建產品時,您可以輕鬆創建所有measurement選件的下拉菜單。儘管如此,我不知道在這種情況下有必然的對錯。

+0

我同意你的意見,但是將這些數據標準化並將其放入單獨表格的傳統方法會在表格中引入額外的連接,每次需要查詢該連接以確定測量/單元類型。 - 放慢數據庫訪問速度,使前端開發成爲一場噩夢。這就是爲什麼我正在考慮使用單表繼承。 – Gravy

+0

對於您的單位,我可能會將該單位存儲爲枚舉或整數映射到所需的特定模型。但總的來說,是的,這種類型的繼承工作正常。有一個不同的類型(你想要另一個表映射的地方),這會變得非常混亂(考慮子類化一個表。小心如果你最終去那裏:-) – acorncom

+0

@Gravy:緩慢的數據庫訪問?夢魘前端發展?我認爲你在那裏有點戲劇化。提供選項的下拉菜單非常標準,如果您有適當的索引,這些小連接只會將微秒添加到數據庫訪問。你永遠不會看到它對抗網絡流量的噪音。我認爲這屬於不成熟優化的範疇,如果它增加了應用程序的複雜性,那麼這是不值得的。 – jmarkmurphy

2

我對做了一些更多的研究單表繼承因爲我對這個術語有點不熟悉,並且認爲這確實值得回答而不是一堆評論。

當您有一組需要保存到數據庫中的類似對象時,單表繼承將發揮作用。您可以將對象拆分爲單獨的表格,或者如果它們足夠相似,可以將它們全部保存在一個帶有字段的表格中,以確定哪個是哪個。對象是不同的,因爲它們需要不同的處理或具有稍微不同的屬性。在你的情況下,我不會考慮不同的度量單位足夠重要,可稱之爲單一表繼承,但更一般地說,你可以有按庫存數量的庫存和按數量庫存的庫存數量,這兩個庫都具有相同的一組屬性,但方法不同處理股票枯竭或成本計算,所以我想你可以在技術上稱它爲單表繼承。但是我認爲這並不重要,因爲處理兩者的方法甚至相似。

這是一個項目類的例子,你可能更符合這個概念。想想製造應用程序。在這種情況下,你有物品,一些是購買的,一些是製造的。這些物品有許多相同的屬性,但是製造物品會包含材料清單,屬性與製造過程有關,而購買的物品有供應商,屬性與購買過程相關。所有這些屬性都可能適合同一個表,有些對於購買的項目是空的,而有些對於製造的項目則爲空,但是使用單表繼承,您可以使用單個查詢或搜索來搜索所有項目與他們一起了解他們獨特的品質。在這種情況下,您可以節省一些時間加入並簡化前端,因爲差異更加明顯,並且SQL聯合可能代價高昂。但只是針對不同的計量單位?可能不值得。

這裏是關於Single Table Inheritance的Yii文檔的鏈接。

+0

你好,謝謝你的回答。我的想法符合你的想法。我確實試圖簡化這個問題,這就是爲什麼我提到度量單位的原因。例如,產品也將按數量或按重量出售。在線系統需要動態地向用戶請求他們希望購買多少,或者他們希望購買多少公斤。因此,模型需要以不同的方式處理。我可能會購買1.5公斤的糖,但我可能不會購買1.5個蘋果。 – Gravy

+0

哦,和研究的+1。 :) – Gravy

+0

仍然沒有代碼重複。爲您的數量字段創建一個自定義驗證器。使用UOM來確定允許的小數精度(我將在UOM文件中使用一個字段),並且如果存在太多的小數位,則拋出一個錯誤。 – jmarkmurphy