вторник, 19 июня 2012 г.

Вложенные категории

Сейчас категории каталога представляют собой список. Выглядит это вот так:
  • Категория 1
  • Категория 2
  • Категория 3
  • ...
  • Категория n
Сейчас нет возможности создавать кодкатегории для товаров. Покажу, как добавить этот функционал. Чтобы стало вот так:
  • Категория 1
    • Категория 1 1
    • Категория 1 2
    • Категория 1 n
  • Категория 2
    • Категория 2 1
      • Категория 2 1 1
      • Категория 2 1 n
        • ...
          • ...
  • Категория 3
  • Категория n
Для начала надо подумать над структурой хранения данных: где хранить информацию о родительской категории для каждой из категорий. Можно воспользоваться методом «nested set» в Yii есть специальный метод для этого. Но я покажу другой способ: просто создать дополнительное свойство parent_id в таблице tbl_category.
ALTER TABLE `tbl_category` ADD `parent_id` INT( 11 )  AFTER `id` ;

ALTER TABLE `tbl_category` ADD INDEX ( `parent_id` ) ;
Где и хранить данные о родительской категории. Теперь надо изменить модель Category. В файле Z:\home\catalog.loc\www\catalog\protected\models\сategory Добавляю новое поле в связи модели, чтобы модель стала связана сама с собой по полю parent_id'
/**
* —return array relational rules.
*/
public function relations()
{ 
return array(
'assortiment'=>array(self::HAS_MANY, 'assortiment', 'category_id'),
'parent'=>array(self::BELONGS_TO, 'category', 'parent_id'),
);
 }
Еще в этом же файле добавлю Лейбл для нового поля
/**
* —return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
'id' => Yii::t('main-ui', 'Id'),
'name_ru' => Yii::t('main-ui', 'name_ru'),
'name_en' => Yii::t('main-ui', 'name_en'),
'name_et' => Yii::t('main-ui', 'name_et'),
'shown' => Yii::t('main-ui', 'Show in catalog?'),
'icon' => Yii::t('main-ui', 'Image'),
'del_img'=>Yii::t('main-ui', 'Delete image?'),
'parent_id'=>Yii::t('main-ui', 'Parent id'),
);
}
И критерий для поиска:
/**
* Retrieves a list of models based on the current search/filter conditions.
* —return CActiveDataProvider the data provider that can 
return the models based on the search/filter conditions.
*/
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id);
$criteria->compare('name_'.Yii::app()->language,$this->
{name_.Yii::app()->language},true);
$criteria->compare('shown',$this->shown,true);
$criteria->compare('parent_id',$this->parent_id,true);
return new CActiveDataProvider(get_class($this), array(
'criteria'=>$criteria,
));
}
Теперь надо изменить форму Category чтобы можно было выбирать значение для parent_id. В файле Z:\home\catalog.loc\www\catalog\protected\views\category\_form
<FIELDSET class="category">   <!-- Элемент украшения-->
<?php echo  '<LEGEND  ALIGN=\"left\"><b>'
.Yii::t('main-ui', 'Category').'</b></LEGEND>';?> 
<div class="row">
<!-- Category::All() уже использовали для генерации выпадающего списка 
при создании товара-->
<?php
echo $form->dropDownList($model,'parent_id', 
Category::All(),
array('empty' => Yii::t('main-ui', '(Select a category)'))
 );?>     
<?php echo $form->error($model,'parent_id'); ?>
</div>
   </FIELDSET>
Вот, пока и все — любой категории можно назначить родительскую категорию. В следующий раз сделаю вывод категорий в соответствии с получившейся иерархией.
Продолжение следует.

3 комментария:

  1. Это очень не практично лучше использовать nested set.

    ОтветитьУдалить
    Ответы
    1. nested set для меня еще очень сложно..

      Удалить
  2. nested set вообще шлак. куда удобнее создавать схему вида предок-потомок. очень желательно выкладывать код проекта (благо облачных хранилищ тьма - тот же google drive)

    ОтветитьУдалить