среда, 21 июля 2010 г.

Делаем "Направленный список чего-нибудь"

Заказчиком была поставлена следующая задача: сделать возможность создавать направленные списки (списки, в которых порядок следования элементов имеет значение), состоящие из произвольных объектов любых моделей проекта. Практическое применение: вывести в определенной последовательности 5 товаров, потом еще 10 товаров (в другой последовательности), затем 7 категорий товаров, и, наконец, 12 новостей (тоже в заранее заданной последовательности). Назовем этот список "рейтингом". Ниже представлена концепция с основными моментами реализации.

# Рейтинг (например, "Пять лучших товаров сезона")
Rating:
  columns:
    name: string(255)
    object_name: string(255)
    
# Собственно, товары (или любые другие объекты)
RatingObject:
  columns:
    rating_id: integer
    object_id: integer
    position: integer
  relations:
    Rating:
      local: rating_id
      foreign: id
      foreignAlias: Objects


Опускаю создание и первичную настройку админ-генератора для рейтинга. Гораздо интереснее, как добавлять (и выводить) в админке элементы рейтинга. Добавление элементов вынесем в компонент rating/objects. Я решил создавать рейтинг в два хода: сначала объект рейтинга, а потом аяксом прикреплять к нему объекты (собственно, создание направленного списка). Поэтому если рейтинг isNew(), то выводим "Будет доступно после сохранения". Шаблон компонента:

<div class="sf_admin_form_row sf_admin_text">
<div>
<label>Объекты</label>
    <div class="content">
<?php if ($form->isNew()): ?>
        Будет доступно после сохранения
      <?php else: ?>
      
        <?php include_partial('objects_list',array('rating'=>$form->getObject())) ?>
        
      <?php endif ?>
    </div>
</div>
</div>
Партиал rating/objects_list довольно прост:

<?php $object_in_rating_name=$rating->object_name ?>

<?php if (count($rating->getObjects())): ?>
  <table>
  <?php foreach($rating->Objects as $object): ?>
    <tr>
      <td><?php echo $object->position ?></td>
      <td><?php echo $object->$object_in_rating_name ?></td>
      <td><a href="">��зменить номер</a> <a href="">Удалить</a></td>
    </tr>
  <?php endforeach ?>
  </table>
<?php endif ?>

Реализацию добавления элемента аяксом оставлю на ваше усмотрение.

Наибольший интерес представляет функция $rating->getObjects(), которая должна вывести не только позиции, но и названия элементов: НЕЧТО->__toString().

Внимание, магия!
<?php
public function getObjects()
  {
    //Вот это круто!! Динамическое создание связи между моделями!
    $rating_object=new RatingObject();
    $rating_object->hasOne($this->object_name,array('local'=>'object_id','foreign'=>'id','foreignAlias'=>'RatingObject'));
    
    return Doctrine_Query::create()
      ->from('RatingObject r')
      ->leftJoin('r.'.$this->object_name.' obj')
      ->where('r.rating_id = ?',$this->id)
      ->orderBy('r.position')
      ->execute();
  }
?>
Вот и все, список создается и выводится. Спасибо за внимание.

Комментариев нет:

Отправить комментарий