Инструменты пользователя

Инструменты сайта


eaze:samples:добавление_фотогалереи_в_vt_к_объекту

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Both sides previous revision Предыдущая версия
Следущая версия
Предыдущая версия
eaze:samples:добавление_фотогалереи_в_vt_к_объекту [2011/09/21 09:32]
sergeyfast
eaze:samples:добавление_фотогалереи_в_vt_к_объекту [2011/09/21 11:30] (текущий)
sergeyfast
Строка 147: Строка 147:
   * ''<​nowiki>​{{each(i,​ photo) photos}}</​nowiki>''​ - цикл в шаблоне для отображения фотографий. ''​photos''​ - свойство из элемента массива data.   * ''<​nowiki>​{{each(i,​ photo) photos}}</​nowiki>''​ - цикл в шаблоне для отображения фотографий. ''​photos''​ - свойство из элемента массива data.
   * ''<​nowiki>​{{tmpl( photo , { counter: $item.photoCounter,​ albumIndex: $item.counter.index }) "#​photoTemplate"​}}</​nowiki>''​ - вызов шаблона photoTemplate,​ передача дополнительных параметров для рендеринга.   * ''<​nowiki>​{{tmpl( photo , { counter: $item.photoCounter,​ albumIndex: $item.counter.index }) "#​photoTemplate"​}}</​nowiki>''​ - вызов шаблона photoTemplate,​ передача дополнительных параметров для рендеринга.
 +  * ''​{$prefix}''​ - стандартная переменная для data.tmpl.php (префикс объекта).
  
 Шаблон для отображения конкретной фотографии Шаблон для отображения конкретной фотографии
Строка 257: Строка 258:
     }     }
 </​code>​ </​code>​
 +
 +Со клиентской частью мы закончили.
 +Данного кода достаточно для управления альбомами без серверной части, только они не будут сохранятся и валидироваться,​ но в ''​$object''​ данные попадут,​ т.к. мы используем полные пути к свойствам объекта (например ''​{$prefix}[albums][${ $item.albumIndex }][photos][${ $item.counter.index }][smallImageId]''​ ) - GetFromRequest соберет объект так, как нужно.
 +
 +Попробуем модифицировать SaveEntityAction таким образом,​ чтобы он сохранял альбомы в базу.
 +
 +===== SaveEntityAction.php =====
 +Прежде всего мы должны помнить о том, что albums у объекта Entity - лист. ''​EntityFactory::​GetById( $id, array( BaseFactory::​WithLists => true ) )''​ выберет только альбомы,​ без фотографий. Фотографии будем выбрать вручную.
 +Создадим метод ''​refillAlbumPhotos()'',​ который добавляет к альбомам фотографии.
 +<code php>
 +protected function refillAlbumPhotos( $object ) {
 +    $photos = EntityPhotoFactory::​Get( array( '​entityId'​ => $object->​entityId ) );
 +    $photos = ArrayHelper::​Collapse( $photos, '​entityAlbumId'​ );
 +
 +    if ( !empty( $photos ) ){
 +        foreach( $object->​albums as $album ) {
 +            if ( isset( $photos[$album->​entityAlbumId] ) ) {
 +                $album->​photos = $photos[$album->​entityAlbumId];​
 +            }
 +        }
 +    }
 +}
 +</​code>​
 +  * дополнительно в EntityPhotoFactory мы добавили поиск по entityId.
 +
 +Далее сделаем так, чтобы фотографии грузились только тогда, когда мы открыли объект для редактирования.
 +<code php>
 +/**
 + * Set Json Albums Data to Template
 + * @return void
 + */
 +protected function beforeSave() {
 +    if ( $this->​action != self::​UpdateAction && !empty( $this->​currentObject->​entityId ) ) {
 +        $this->​refillAlbumPhotos( $this->​currentObject );
 +    }
 +
 +    Response::​setParameter( '​data',​ EntityAlbumUtility::​PrepareAlbumsData( $this->​currentObject ) );
 +}
 +</​code>​
 +  * EntityAlbumUtility::​PrepareAlbumsData() - метод, который подготавливает переменную ''​data''​ для шаблона photos.tmpl.php.
 +
 +Теперь,​ если у объекта есть альбомы и фотографии,​ то мы уже увидим их в шаблоне :).
 +
 +Добавим валидацию альбомов и фотографий.
 +<code php>
 +protected function validate( $object ) {
 +    $errors = parent::​$factory->​Validate( $object );
 +
 +    $albumErrors = EntityAlbumUtility::​ValidateAlbums( $object->​albums );
 +    if ( !empty( $albumErrors ) ) {
 +        $errors['​fields'​]['​photos'​]['​format'​] = '​format';​
 +        Response::​setParameter( '​albumErrors',​ $albumErrors );
 +    }
 +
 +    return $errors;
 +}
 +</​code>​
 +  * fields => photos поможет нам подсветить таб "​Фотографии",​ если на нем были ошибки (''<​div data-row="​**photos**"​...''​ в photos.tmpl.php) и не дать сохранить ошибочный объект в базу.
 +
 +Теперь можно перейти к сохранению. Для этого сначала нужно заполнить $originalObject фотографиями (в оригинальном объекте они нужны для того, чтобы удалить те фотографии,​ которые мы удалили с формы).
 +<code php>
 +protected function beforeAction() {
 +    if ( !empty( $this->​originalObject ) ) {
 +       ​$this->​refillAlbumPhotos( $this->​originalObject );
 +   }
 +}
 +</​code>​
 +
 +add() и update() будут обернуты в транзакцию.
 +<code php>
 +/**
 + * Add Object
 + *
 + * @param Entity $object
 + * @return bool
 + */
 +protected function add( $object ) {
 +    ConnectionFactory::​BeginTransaction();​
 +
 +    $result = parent::​$factory->​Add( $object, array( BaseFactory::​WithReturningKeys => true ) );
 +    $result = $result && EntityAlbumUtility::​SaveAlbums( $object, $this->​originalObject );
 +
 +    ConnectionFactory::​CommitTransaction( $result );
 +
 +    return $result;
 +}
 +
 +
 +/**
 + * Update Object
 + *
 + * @param Entity $object
 + * @return bool
 + */
 +protected function update( $object ) {
 +    ConnectionFactory::​BeginTransaction();​
 +
 +    $result = parent::​$factory->​Update( $object );
 +    $result = $result && EntityAlbumUtility::​SaveAlbums( $object, $this->​originalObject );
 +
 +    ConnectionFactory::​CommitTransaction( $result );
 +    ​
 +    return $result;
 +}
 +</​code>​
 +
 +Последний штрих. При сохранении фоток мы не получаем их идентификаторы,​ из-за этого неправильно работает кнопка "​Применить"​ в режиме редактирование. Исправляется это путем переполучения фотографий только при успешном сохранении.
 +<code php>
 +protected function afterAction( $success ) {
 +    if ( $this->​redirect == '​view'​ && $success ) {
 +        $this->​refillAlbumPhotos( $this->​currentObject );
 +        Response::​setParameter( '​data',​ EntityAlbumUtility::​PrepareAlbumsData( $this->​currentObject ) );
 +    }
 +}
 +</​code>​
 +
 +Не забудьте посмотреть код [[eaze:​samples:​добавление_фотогалереи_в_vt_к_объекту_EntityAlbumUtility.php|EntityAlbumUtility.php]].
 +
 +
 +====== Итог ======
 +Поставленной цели мы добились. Можно было бы конечно сделать массовый загрузчик на flash и потом и мышкой раскидать фотографии по альбомам,​ но для этого нужно написать ещё больше javascript'​а.
 +
 +Осталось рассмотреть плюсы и минусы подхода.
 +
 +===== Плюсы =====
 +  * Не нужно дополнительно обрабатывать получение связанных объектов из формы на PHP (albums, photos).
 +  * Не нужно дублировать шаблон отображения album и photo сначала в PHP, потом на JS. Всего используется один шаблон.
 +  * Минимальное количество кода в SaveEntityAction (в основном - только получение листов второго и последующих уровней).
 +
 +===== Минусы =====
 +  * GetFromRequest на втором уровне получает каждый объект через GetById (соответственно сколько файлов - столько запросов при сохранении). //​можно исправить,​ но сложновато//​
 +  * Если сохранить страницу при выключенном JS - то все фотографии удалятся (потому что не пришли с формы). //​можно исправить через дополнительную переменную,​ которая выставляется через JS//
 +  * При сохранении страницы для не измененных данных каждый раз выполняется UPDATE. //​можно исправить путем добавления проверки на эквивалентность объектов//​
 +
 +//Ещё раз повторюсь,​ что данный пример не претендует на идеальность и универсальность. Он пытается рассказать,​ как работать в VT со сложными объектами. Пожелания и дополнения приветствуются. ;)//
 +
 +
 +
 +
 +
 +
 +
 +
eaze/samples/добавление_фотогалереи_в_vt_к_объекту.1316583158.txt.gz · Последние изменения: 2011/09/21 09:32 — sergeyfast