Предполагая, что у меня есть интернет-магазин, в котором продукты хранятся и продаются либо целым числом, либо десятичным весом. Существуют разные типы продуктов. Не все элементы связаны. Мне нужно решить, следует ли помещать их в отдельные таблицы (нормализовать) или использовать метод, называемый однонаправленным наследованием таблицы, который позволяет мне хранить все продукты в одной таблице, но использовать разные классы моделей для каждого типа продукта.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);
модели (только продукт и 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');
}
и правила для модели 'в каждой ячейке' будет что-то вроде
array('stock','numerical', 'integerOnly'=>true)
и 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
}
Я согласен с тем, что вы говорите, однако традиционный метод нормализации и размещения этих данных в отдельной таблице приведет к добавлению дополнительного соединения в таблицу, которое необходимо будет запрашивать каждый раз, чтобы определить тип измерения/единицы измерения. - замедляет доступ к базе данных и делает разработку в конце концов кошмаром. Вот почему я рассматривал возможность использования однонаправленного наследования. – Gravy
Для ваших устройств я бы, вероятно, сохранил устройство как перечисление или целое число, которое соответствует конкретной модели. Но в целом, да, этот тип наследования работает нормально. Существует другой тип (где вы хотите, чтобы другая таблица отображалась также), которая становится действительно беспорядочной (подумайте, подклассифицируя таблицу. Будьте осторожны, если вы в конечном итоге собираетесь туда :-) – acorncom
@Gravy: медленный доступ к базе данных? Развитие кошмарного фронта? Я думаю, что вы немного драматичны. Выпадающий список для обеспечения выбора - довольно стандартная плата за проезд, и эти небольшие объединения добавляют только микросекунды к доступу к базе данных, если у вас есть соответствующие индексы. Вы никогда не увидите его против шума сетевого трафика. Я считаю, что это подпадает под категорию преждевременной оптимизации, и если это добавляет сложности вашего приложения, это не стоит усилий. – jmarkmurphy