2013-07-19 3 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); 

модели (только продукт и 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 
} 

ответ

0

Одна вещь, я бы, вероятно, изменить то, что вы могли бы сделать, это создать таблицу с именем measurement затем хранить measurement_id в ваш стол продукта. Затем вы можете перенести некоторые из ваших других функций в модель измерения вместо того, чтобы иметь ее в модели продукта. Затем, когда вы создаете продукт, вы можете легко создавать выпадающие списки всех опций measurement. Я не знаю, что в этой ситуации обязательно есть правильный или неправильный путь.

+0

Я согласен с тем, что вы говорите, однако традиционный метод нормализации и размещения этих данных в отдельной таблице приведет к добавлению дополнительного соединения в таблицу, которое необходимо будет запрашивать каждый раз, чтобы определить тип измерения/единицы измерения. - замедляет доступ к базе данных и делает разработку в конце концов кошмаром. Вот почему я рассматривал возможность использования однонаправленного наследования. – Gravy

+0

Для ваших устройств я бы, вероятно, сохранил устройство как перечисление или целое число, которое соответствует конкретной модели. Но в целом, да, этот тип наследования работает нормально. Существует другой тип (где вы хотите, чтобы другая таблица отображалась также), которая становится действительно беспорядочной (подумайте, подклассифицируя таблицу. Будьте осторожны, если вы в конечном итоге собираетесь туда :-) – acorncom

+0

@Gravy: медленный доступ к базе данных? Развитие кошмарного фронта? Я думаю, что вы немного драматичны. Выпадающий список для обеспечения выбора - довольно стандартная плата за проезд, и эти небольшие объединения добавляют только микросекунды к доступу к базе данных, если у вас есть соответствующие индексы. Вы никогда не увидите его против шума сетевого трафика. Я считаю, что это подпадает под категорию преждевременной оптимизации, и если это добавляет сложности вашего приложения, это не стоит усилий. – jmarkmurphy

2

Я сделал немного больше исследований на Одиночный стол Наследование, поскольку я был немного незнакомым с термином и решил, что это действительно заслуживает ответа, а не кучу комментариев.

Наследование отдельных таблиц вступает в игру, когда у вас есть группа похожих объектов, которые необходимо сохранить в базе данных. Вы можете либо разбить объекты на отдельные таблицы, либо если они достаточно похожи, вы можете сохранить их в одной таблице с полем для определения того, что есть. объекты разные, потому что они нуждаются в другой обработке или имеют несколько разные атрибуты.В вашем случае я бы не рассматривал различные единицы измерения, достаточно значимые, чтобы называть их Наследование одного стола, но в целом вы могли бы иметь предметы, запасенные по объему, и предметы, запасенные количеством, которые имеют одинаковый набор атрибутов, но разные методы справиться с истощением запасов или стоимостью, поэтому, я думаю, вы могли бы это назвать технически. Наследование отдельных таблиц. Но я даже не думаю, что это достаточно важно, так как методы обработки этих двух элементов даже схожи.

Вот пример классов предметов, которые, возможно, были бы более похожими на эту концепцию. Подумайте о производственном приложении. В этом случае у вас есть предметы, некоторые купленные, некоторые изготовлены. эти элементы имеют одни и те же атрибуты, но у изготовленного товара есть спецификация материалов и атрибуты, связанные с производственным процессом, в то время как приобретенные товары будут иметь поставщиков и атрибуты, связанные с процессом покупки. вполне возможно, что все эти атрибуты поместились бы в одну и ту же таблицу, некоторые из них были бы нулевыми для купленных предметов, а некоторые были бы нулевыми для изготовленных предметов, но с использованием Single Table Inheritance вы могли бы искать все элементы с одним запросом или заниматься с ними с классом, который знает об их уникальных качествах. В этом случае вы сохраняете некоторое время на объединениях и упрощаете внешний интерфейс, потому что различия намного более поразительны, а союзы SQL могут быть дорогостоящими. Но только для разных единиц измерения? вероятно, не так стоит.

Вот ссылка на документацию Yii на Single Table Inheritance.

+0

Привет, спасибо за ваш ответ. Мои мысли соответствуют вашим. Я попытался немного упростить вопрос, поэтому я говорил об единицах измерения. Например, продукты также будут продаваться по количеству или по весу. Онлайновая система должна будет динамически запрашивать у пользователя, сколько они хотят приобрести, или сколько килограммов они хотят приобрести. Таким образом, модели нужно обрабатывать по-разному. Я могу купить 1,5 кг сахара, но я не могу купить 1,5 яблок. – Gravy

+0

О, и +1 для исследования. :) – Gravy

+0

Все еще нет дублирования кода. Создайте пользовательский валидатор для своего количества. Используйте UOM для определения разрешенной десятичной точности (я бы использовал поле в файле UOM) и выдавал ошибку, если присутствует слишком много десятичных позиций. – jmarkmurphy

Смежные вопросы