Assuming that I have an online store whereby products are stocked and sold by either integer quantity or decimal weight. There are different types of products. Not all items are related. I need to decide whether I should put them in separate tables (normalise) or use a technique called single table inheritance which enables me to store all products in the same table, but use Different model classes for each type of product.
A simple example being.
Rice would be is stocked per kilo (decimal) as opposed to per grain (integer). Rice would be sold by the kilo (decimal) but you cannot sell 1.5 apples (decimal).
Is this what single table inheritance is for or have I missed the point of what it is for?
DB Example
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);
Models (Only Product and Kilo unit type shown for simplicity)
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');
}
and rules for model 'EachUnit' would be something like
array('stock','numerical', 'integerOnly'=>true)
and attributeLabel for model 'EachUnit' would be something like
return array('stock' => 'Quantity');
That way, If I wish to work with all products, I can use the following:
$products = Product::model()->findAll();
foreach($products as $p)
{
do something
}
If I only wish to deal with products with kilo as unit type
$products = KiloUnit::model()->findAll();
foreach($products as $p)
{
do something
}