Выделив немного свободного времени, я решил отписать о такой интересной вещи, как портфолио для фотографов (либо простейшая фото-галерея). Здесь я постараюсь рассказать о парочке подводных камней, с которыми я столкнулся и как они были решены. Интересно? Что ж, тогда прошу под кат.
Недавно было получено задание реализовать фото-портфолио с бекэндом и фронтэндом. Начав ковырять готовые фреймворки и CMS я пришел к выводу, что лучше всего использовать связку GalleryCMS, Galleria и плагин к Galleria.
Первое же, которое меня не устроило, это проблемы с поддержкой категорий в GalleryCMS. А именно, ее вообще нету. Есть только альбомы, в которые собственно и загружаются фотографии и «фиды». Вот такой простенький backend. Как решить вопрос с категориями? Я посмотрел в сторону «фидов». Оказывается в них можно добавлять больше, чем один альбом. Что ж, я думаю сойдет. Сделаем «фиды» категориями. Но для этого давайте посмотрим в базу данных. Как же все-таки он сохраняет список альбомов в «фид»?
Структура базы в backend’е довольно простая. Всего в ней 8 таблиц. В них хранятся фиды, альбомы, список пользователей, список изображений и есть то, что нам очень поможет — таблица соответствий между фидами и альбомами. Взглянем в таблицу feed_album.
В этой таблице можно увидеть всего 4 поля: id записи, id «фида», id альбома и порядок отображения. Уже становится ясно, что с этой таблицы можно взять какой альбом в какой «категории» («фиде») лежит. А теперь посмотрим в другие таблицы: album и feed.
Здесь есть все — вот оно — решение проблемы. Зная id альбома и id «фида», в котором лежит этот альбом, можно сгенерировать объект. В этом объекте выстроить структуру Категория -> Альбомы. Что ж, приступим к реализации.
Напишем php-скрипт, который будет выдавать ответ (Категория -> Альбомы, Категория -> Альбомы) в JSON.
<?php //считаем, что к базе мы уже подключились include_once './database.php'; //инициализируем массив ответа $response = array(); //выберем сначала таблицу соответствий $result = mysql_query('SELECT * FROM feed_album'); for ($feed_album = array(); $row = mysql_fetch_assoc($result); $feed_album[] = $row); //затем список наших категорий ("фидов") $result = mysql_query('SELECT * FROM feed'); for ($feed = array(); $row = mysql_fetch_assoc($result); $feed[$row['id']] = $row); //а затем еще и список всех альбомов $result = mysql_query('SELECT * FROM album'); for ($album = array(); $row = mysql_fetch_assoc($result); $album[$row['id']] = $row); //пройдемся по таблице соответствий //и заполним наш response foreach ($feed_album as $value) { $response[$feed[$value['feed_id']]['name']][$album[$value['album_id']]['name']] = $album[$value['album_id']]['uuid']; } //в итоге мы получим массив такого вида //Категория //--Альбом = uuid альбома //--Альбом = uuid альбома //Категория и т.д.... echo json_encode($response); ?>
С одной проблемой разобрались. На frontend мы уже получаем список категорий и их альбомов. Как же теперь построим меню, на основе этих данных?
Для этого было написаны 2 функции. Одна забирает посредством AJAX данные с нашего скрипта, а вторая формирует HTML на основе этих данных. Что ж, вот код:
//эта ф-ция генерирует HTML-код buildMenu: function() { //сначала инициализируем строку для кода var html = ''; //аяксом мы сохраняем ответ от php в свойство объекта this.albums //перебрали весь объект с альбомами for (var feed in this.albums) { html += '<li>'; html += '<a href="#">' + feed + '</a>'; html += '<ul>'; for (var album in this.albums[feed]) { //каждый альбом это ссылка, в data-uuid храним uuid альбома, а album и feed - это названия категории и альбома html += '<li><a href="#" data-uuid="' + this.albums[feed][album] + '">' + album + '</a></li><div class="spacer"></div>'; } html += '</ul></li>'; } //в итоге добавляем в наш блок с меню этот html $('#' + Core.Config.idMainMenu).html(html); }, //а эта ф-ция как раз выступает в роли запроса этих альбомов getAlbums: function() { var self = this; $.ajax({ url: Core.Config.ajxGetAlbumsSrc, dataType: 'json', type: 'POST', cache: false, error: function() { Core.Objects.Design.blockAllPage('Ошибка загрузки<br/>Перезагрузите страницу'); }, success: function(response) { //когда получим альбомы, то сохраним и вызовем ф-цию выше self.albums = response; self.buildMenu(); } }); }
Таким образом мы получаем меню, в котором есть категории и альбомы. Вроде все хорошо, но нужно теперь запустить альбом в галерею по щелчку. Начинаем подключать те самые плагины Galleria и плагин к ней. И да, пока не забыл, Galleria использует jQuery, поэтому его нужно тоже подключать.
В итоге реализуем нажатие по ссылкам нашего меню, возьмем uuid, который мы помещаем в data-uuid и бросаем этот uuid на растерзание плагину к Galleria. Вот код обработки нажатия на ссылку:
$('#' + Core.Config.idMainMenu + ' a').click(function() { var uuid = $(this).data('uuid'); if (uuid != undefined && uuid != null && uuid != '') { //эта ф-ция переключает альбом на тот, по которому мы щелкнули //ее я опишу ниже Core.Objects.Gallery.switchAlbum(uuid); } });
Вот код, которые уже загружает информацию о фотографиях в альбоме и выводит в галерею:
switchAlbum: function(uuid) { //gallerycms - это наш плагин к Galleria. $('#' + Core.Config.idMainGallery).gallerycms({ //в url мы должны передать путь к ./backend/index.php/api/feed/json/ + наш uuid альбома //в итоге мы вытянем фотографии с этого альбома и загрузим в нашу галерею url: Core.Config.urlGalleryCMS + uuid, theme: Core.Config.themeMainGallery }); }
Все, проблема решена. Я радуюсь и отдыхаю. Но не тут-то было. При попытке загрузить второй альбом, он снова загружает предыдущий альбом. Все, приехали. Почему он загружает нормально только в первый раз, а вторые разы уже не загружает?
Начал ковырять уже сам код плагина, а в итоге и самой Galleria. Вывод нашелся быстро — после созданий экземпляра галереи, другие фотографии загрузить уже не получится. Нужно брать контроль в свои руки.
Ковыряя код пришел к двум вариантам решения проблемы. Первый вариант — использовать ф-цию load на экземпляре галереи. Она загружает в галерею новые изображения, очищая старые. Второй вариант — использовать ф-цию destroy в экземпляре галереи. Было решено попробовать ф-цию load. Зачем же нам каждый раз уничтожать экземпляр и создавать по новой, правильно?
И после нескольких часов разбора исходников плагина и Galleria пришел к выводу, что проще всего реализовать это не ф-цией load, как все советуют, а очередным запуском run с передачей параметров в json. Давайте отредактируем наш плагин gallerycms к Galleria. Редактируем ф-цию parseAlbum, в которую как раз передается наш uuid альбома:
function parseAlbum() { //объявим массив, в котором будем хранить список изображений для Galleria var json = []; $.getJSON(settings.url, function(data) { $.each(data.images, function(key, image) { //заполняем наш массив объектами с параметрами фотографий json.push({ thumb: image.thumb, image: image.url, title: image.caption }); }); Galleria.loadTheme(settings.theme); //запускаем еще раз галерею, передавая ей наш новый json-объект с фотографиями Galleria.run($this, { dataSource: json }); }); }
Таким образом было реализовано простейшее фото-портфолио с бекэндом и фронтэндом.
P.S. Можно еще переделать немного backend и вместо Feeds написать Категории и т.д. в таком духе. Чтобы у пользователя не осталось сомнений, что здесь есть категории.
P.P.S. За код сильно не ругайте, у каждого свой стиль написания. Буду прислушиваться к вашим пожеланиям.
Спасибо всем, кто дочитал до этого места и, возможно, почерпнул из этого что-то новое или интересное.
ссылка на оригинал статьи http://habrahabr.ru/post/173289/
Добавить комментарий