Показать сообщение отдельно

  #4  
Старый 20.02.2009, 10:42
Kuzya
Участник форума
Регистрация: 27.04.2008
Сообщений: 224
Провел на форуме:
140661

Репутация: 313
По умолчанию

3. Фотогаллерея.
Следующая часть статьи будет посвящена написанию фотогаллереи. Функционал у неё будет тоже не очень большой, но по количеству рассмотренных инструментов, вместительный. В нашей фотогаллерее будет следующее. Пользовательская часть будет позволять просматривать списки фотоальбомов и их содержимое. Так же нами будет написана имитация рейтинговых оценок альбомов. В админ-части у нас будет авторизация, возможность добавления/удаления фотоальбомов. Возможность их редактирования, включающая в себя добавление в альбом фотографии как по одиночке так и пакетно (архивами). Так же будет возможность архивного бэкапа всех фотографий.
В отличие от предыдущего примера мы будем использовать для обработки видов шаблонизатор (Templater parser — http://code-igniter.ru/user_guide/libraries/parser.html). Нужно сказать что его функционал очень скуден (по сравнению с использованием альтернативного синтаксиса PHP в отображениях) и рассмотреть его я решил только потому что это часть инструментария CI. Хотя здесь жаловаться не на что, разработчики в документации чётко написали - «Класс Template Parser не полнофункциональный шаблонизатор. Мы специально оставили его очень простым, чтобы сохранить максимум производительности.». Для обращений же к базе данных мы теперь будем использовать не прямые запросы и метод «query», а паттерн «Active Record» (http://code-igniter.ru/user_guide/database/active_record.html). Он очень прост и удобен в работе, а так же позволяет максимально сэкономить и время разработчика и количество кода. В добавок ко всему интерфейс AR интуитивно понятный и разобраться в чужом коде (работающем с AR) можно даже без документации. Так же, как я писал выше, мы поработаем с ZIP-архивами (создание/распаковка). Пока что в арсенале CI нет функций для извлечения ZIP-архивов, поэтому мы немного дополним его библиотекой PclZip, но всему своё время.
Возьмёмся за начальные приготовления. Как я уже писал в начале статьи — для нового приложения мы будем использовать «чистую» копию CI. В корне приложения создайте папку «photos» - в ней будут храниться фотографии из наших альбомов. Шаблон для этого примера у нас останется тот же. Оставьте в корне сайта файл стилей и директорию «images». В папку видов скопируйте прошлые шаблоны «header» и «footer», только удалите вызов функции добавления смайлов в шаблоне «header». Так же оставьте в этой папке файл «.htaccеss» который мы рассматривали в самом начале статьи.
В уже созданной в первом примере базе данных выполните следующий код.

Код:
CREATE TABLE `albums` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(100) character set utf8 NOT NULL,
  `t_name` varchar(100) character set utf8 NOT NULL,
  `about` text character set utf8 NOT NULL,
  `rating` int(11) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `t_name` (`t_name`)
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 PACK_KEYS=0 AUTO_INCREMENT=0 ;

INSERT INTO `albums` VALUES (NULL, 'First album', 'first_album', 'This is text about the first our album!', 0);
INSERT INTO `albums` VALUES (NULL, 'Second album', 'second_album', 'This is text about the second album!', 0);
INSERT INTO `albums` VALUES (NULL, 'Third album', 'third_album', 'This is text about the third album!', 0);
Это таблица содержащая данные фотоальбомов. Имеет она 5 полей. Поле «id» содержит порядковый номер альбома, «name» - его название, поле «t_name» название альбома в транслите (оно будет использоваться нами для ЧПУ), «about» - описание альбома и «rating» - его рейтинг. Вторая таблица будет содержать информацию о фотографиях, содержащихся в этих альбомах.

Код:
CREATE TABLE `photos` (
  `id` int(11) NOT NULL auto_increment,
  `album_id` int(11) NOT NULL,
  `file_name` varchar(50) character set utf8 default NULL,
  PRIMARY KEY  (`id`),
  KEY `album_id` (`album_id`)
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 PACK_KEYS=0 AUTO_INCREMENT=0 ;
Тут всё ещё проще. Поле «id» содержит порядковый номер фотографии, «album_id» - номер альбома которому эта фотография принадлежит и «file_name» - имя файла фотографии. Для настройки подключения к MySQL откройте файл «application/config/database.php» и впишите те данные которые обсуждались выше. Далее откройте файл «application/config/autoload.php» и добавьте библиотеку «database» в автозагрузку. После этого откройте файл «application/config/config.php» и замените содержимое ячейки «base_url» на имя вашего хоста.
Перейдём к созданию администраторской панели. Все её контроллеры будут содержаться в директории «admin», находящейся в папке контроллеров. Никаких трудностей при доступе к ним это не создаст, нужно будет только в URI перед именем контроллера указывать имя этой директории. Подробнее о размещении контроллеров в поддиректориях Вы можете почитать в соответствующем разделе документации (http://code-igniter.ru/user_guide/general/controllers.html), под-раздел «Организация ваших контроллеров в подпапках». Первый контроллер который мы создадим - «Albums». Из названия видно что он будет отвечать за работу с альбомами. Установите его в файле «application/config/routes.php» контроллером по умолчанию как в предыдущем примере. И для пользовательской и для администраторской части главные контроллеры будут называться «Albums». Пусть он пока побудет пустой. Его метод «index» в будущем должен отображать список имеющихся у нас фотоальбомов. Что бы этот список получить нам нужно создать модель. Назовём её «Albums_model» и напишем в ней функцию «getAlbumsArray». Она просто будет выбирать все записи из таблицы «albums» и возвращать результат в виде массива. Для выборки данных в «Active Record» есть метод «get» который получает всё (если не указаны конкретные поля) из указанной таблицы.

PHP код:
function getAlbumsArray()
{
    
$albums = Array();
    
// Берём все данные из таблицы `albums`
    
$query $this->db->get('albums');
    
// Для результата используем всё ту же функцию result_array 
    // возвращающую запись в виде ассоциативного массива.
    
foreach($query->result_array() as $album)
        
$albums[] = $album;

    return 
$albums;

Добавим загрузку этой модели в конструктор контроллера «Albums». А функцию «getAlbumsArray» мы вызовем в методе «index» и присвоим возвращённое значение переменной «albums». Так же после вызова вышеупомянутой функции добавьте строку дампа переменной — так мы проверим всё ли правильно работает.

PHP код:
class Albums extends Controller
{
    function 
__construct()
    {
        
parent::Controller();

        
$this->load->model('Albums_model');
    }

    function 
index()
    {
        
$albums $this->Albums_model->getAlbumsArray();
        
var_dump($albums);
    }

Если при обращении к странице видно дамп пассива с тремя ячейками то всё нормально, удалите строку дампа и приступим к работе с видами. Как я уже писал ранее, для отображения шаблонов мы будем использовать встроенный парсер. Для того что бы не вызывать его каждый раз в ручную, откройте конфигурационный файл автозагрузки и в список загружаемых автоматически библиотек впишите класс «parser». Теперь нужно создать шаблон для отображения списка альбомов. Ему мы передадим наш массив полученный от функции «getAlbumsArray». Так как это массив двумерный то его придётся обработать с помощью парных переменных (про них можно прочитать в документации к парсеру).

Код:
<BODY BGCOLOR=#FFFFFF LEFTMARGIN=0 TOPMARGIN=0 MARGINWIDTH=0 MARGINHEIGHT=0>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
  <tr>
    <td height="137" valign="top" background="/images/bgt.gif">
      <table width="100" border="0" cellspacing="0" cellpadding="0">
        <tr>
          <td><img src="/images/head.jpg" width=378 height=96 alt=""></td>
          <td><img src="/images/thead.gif" width=372 height=31 alt=""><br>
            <img src="/images/name.jpg" width=372 height=27 alt=""><br>
            <a href=" "><img src="/images/slogan.jpg" width=372 height=18 border=0 alt=""><br>
            </a><img src="/images/index_05.jpg" width=372 height=20 alt=""></td>
        </tr>
      </table>
    </td>
  </tr>
</table>
<table width="750" border="0" cellspacing="0" cellpadding="0" class="styles">
  <tr>
    <td width="81" valign="top"><img src="/images/rc.gif" width=55 height=24 alt=""></td>
    <td width="669">
    {albums}
      <p>&nbsp;</p>
      <p align="left">
          <a class='stylesbold' href='/admin/albums/album_edit/{id}/'>{name}</a>
          /
          <a class='stylesbold' href='/admin/albums/album_del/{id}/'>Удалить</a>
          </p>
      <p align="left">{about}</p>
    {/albums}
    </td>
  </tr>
</table>
Для хранения шаблонов админ-панели создайте в директории видов папку «admin». В ней сохраните этот шаблон под именем «admin_albums_list.php». В контроллер, в код метода «index», впишем формирование массива «data» для передачи данных шаблону и вызов трёх отображений — «header», «footer» и «admin_albums_list».

PHP код:
// Формируем данные для шаблона
$data = Array();
$data['albums'] = $albums;

// Обрабатываем шаблоны
$this->parser->parse('header',Array());
$this->parser->parse('admin/admin_albums_list',$data);
$this->parser->parse('footer',Array()); 
Обратимся снова по ссылке http://ci/admin/albums/ . Там должна отобразиться страница со списком альбомов из базы, и с ссылками на их редактирование/удаление. Вы, наверное, озадачены тем что шаблонам «header» и «footer» передаются пустые массивы вторым параметром. Дело в том что если второй параметр вообще не передавать то парсер начинает выдавать список ошибок. Конечно это неудобно, но легко исправляется. Если Вы в будущем будете использовать «Tempalte parser», то для того чтобы не указывать каждый раз за место данных пустой массив замените строку 45 в файле «libraries/Parser.php»
c

PHP код:
function parse($template$data$return FALSE
на

PHP код:
function parse($template$data = Array(), $return FALSE
и всё. Я же в этой статье буду передавать каждый раз пустой массив потому что планов по вторжению в код CI у меня не было с самого начала и из изменений инструментария CI я описываю только расширение функционала.

Добавим к списку альбомов форму добавления нового, вот её код.

Код:
<br /><br />
<form action='/admin/albums/album_add/' method='POST'>
    <table width="100%" border="0" cellspacing="0" cellpadding="0">
        <tr>
            <td width="81" valign="top"><img src="/images/rc.gif" width=55 height=24 alt=""></td>
            <td>
                <span class='stylesbold'>Название альбома:</span>
            </td>
            <td>
                <input type='text' name='name' value=''/>
            </td>
        </tr>
        <tr>
            <td width="81" valign="top"><img src="/images/rc.gif" width=55 height=24 alt=""></td>
            <td>
                <span class='stylesbold'>Его описание:</span>
            </td>
            <td>
                <textarea name='about' cols='20' rows='5'></textarea>
            </td>
        </tr>
        <tr>
            <td width="81" valign="top"><img src="/images/rc.gif" width=55 height=24 alt=""></td>
            <td colspan='2'>
                <input type='submit' value='Добавить' />
            </td>
        </tr>
    </table>
</form>
Сохраните эту форму под именем «admin_album_add_form.php» в папке где хранятся шаблоны админ-части и добавьте её обработку перед обработкой вида «footer». Следующим шагом проработаем удаление. Из кода отображения списка альбомов видно что он называется «album_del» и передаётся ему через URI один параметр — номер альбома в базе. В этом методе мы просто вызовем запрос на удаление и после него вызовем метод «index», чтобы он отобразил список оставшихся альбомов. Сам запрос на удаление мы разместим в модели. Назовём его «delAlbumQuery», ему нужно будет передать лишь один параметр — номер альбома который требуется удалить. Запрос к базе мы совершим с помощью метода «delete», которому нужно первым параметром передать имя таблицы, из которой удаляется строка, а вторым массив условий в форме «поле => значение».

PHP код:
function delAlbumQuery($album_id)
{
    
$this->db->delete('albums',Array('id'=>$album_id));

Ну и сам код функции «album_del» в контроллере.

PHP код:
function album_del($album_id)
{
    
$album_id intval($album_id);
    
// Вызываем функцию удаления
    
$this->Albums_model->delAlbumQuery($album_id);

    
self::index();

Для проверки попробуйте теперь удалить один из существующих альбомов.
Далее нам нужно заняться функцией добавления фотоальбомов. К ней будет отправлять данные наша форма. Метод который нам нужен называется album_add. В нём у нас будут формироваться данные нового альбома и передаваться в модель, методу который будет эти данные вставлять. На этапе контроллера нам нужно сформировать следующие данные — имя альбома, его транслитерационное имя для ЧПУ и описание. Первое и третье свойства можно свободно получить, а вот для того что бы получить имя альбома в транслите мы напишем отдельную функцию которую сделаем расширением хэлпера «String». В папке «application/helpers» создайте файл «MY_string_helper.php» и впишите в него одну функцию - «translit». Вот её код:

PHP код:
function translit($str)
{

    
$upper = Array(
        
'#А#','#Б#','#В#','#Г#','#Д#','#Е#','#Ё#','#Ж#','#З#','#И#',
        
'#Й#','#К#','#Л#','#М#','#Н#','#О#','#П#','#Р#','#С#','#Т#',
        
'#У#','#Ф#','#Х#','#Ц#','#Ч#','#Ш#','#Щ#','#Ъ#','#Ы#','#Ь#',
        
'#Э#','#Ю#','#Я#');

    
$lower = Array(
        
'а','б','в','г','д','е','ё','ж','з','и','й','к','л','м','н','о','п','р','с','т',
        
'у','ф','х','ц','ч','ш','щ','ъ','ы','ь','э','ю','я');

    
$str preg_replace($upper,$lower,$str);

    
$from = Array(
        
'#а#','#б#','#в#','#г#','#д#','#е#','#ё#','#ж#','#з#','#и#',
        
'#й#','#к#','#л#','#м#','#н#','#о#','#п#','#р#','#с#','#т#',
        
'#у#','#ф#','#х#','#ц#','#ч#','#ш#','#щ#','#ъ#','#ы#','#ь#',
        
'#э#','#ю#','#я#');

    
$to   = Array(
        
"a""b""v""g""d","e""yo""zh""z""i","j""k""l""m""n",
         
"o""p""r""s""t","u""f""h""c""ch",
         
"sh""sh""""y""","je""ju""ja");

    
$str preg_replace($from,$to,$str);

    
$str str_replace(' ','_',$str);
    
$str str_replace('+','_',$str);
    
$str str_replace('-','_',$str);

    
$str preg_replace('#[^0-9a-z_]#mi','',$str);

    
$str trim($str);

    return 
$str;

Думаю код в комментариях не нуждается, несмотря на размеры он очень простой. Вот через эту функцию мы и пропустим русскоязычное имя альбома что бы получить его в транслитерационном виде.
Добавлением данных в базу будет заниматься метод «addAlbumQuery» модели. Ему мы передадим все 3 параметра которые формируются в контроллере. Для вставки мы используем метод «insert» которому требуется передать первым параметром имя таблицы, а вторым массив полей вставляемой записи и их значений.

PHP код:
function addAlbumQuery($name,$t_name,$about)
{
    
// Формируем массив полей и их значений
    
$fields_array = Array(
        
'id'=>'',
        
'name'  =>$name,
        
't_name'=>$t_name,
        
'about' =>$about,
        
'rating'=>0
    
);

    
$this->db->insert('albums',$fields_array);

Сам же код функции album_add достаточно прост:

PHP код:
function album_add()
{
    
// Загружаем расширенный нами хэлпер "string"
    
$this->load->helper('string');
    
// Формируем массив данных для добавления
    
$name   $this->input->post('name',true);
    
$t_name translit($name);
    
$about  $this->input->post('about',true);
    
// Вызываем метод добавления
    
$this->Albums_model->addAlbumQuery($name,$t_name,$about);
    
// Выводим список альбомов, там уже присутствует новый альбом
    
self::index();

Попробуйте добавить новый альбом и заглянув в БД убедитесь что все данные сформированы правильно. Следующая на очереди функция редактирования альбома. Как раз при редактировании мы сделаем добавление фотографий. Вообще на странице редактирования будут отображаться следующие данные — имя альбома, описание, количество фотографий в нём и сами фотографии. Каждую фотографию можно будет по отдельности удалить. Форма редактирования свойств альбомов будет точь-в-точь как форма добавления новых, а после неё уже будет отдельная форма с 2 полями для загрузки фотографий — по отдельности и архивом. Прежде всего напишем функции модели необходимые для редактирования. Первая из них должна получать данные указанного альбома. Она очень проста.

PHP код:
function getAlbumData($album_id)
{
    
$this->db->where('id',$album_id);
    
$query $this->db->get('albums');
    
$row $query->result_array();

    return 
$row['0'];

В первой строке мы используем метод where для создания условия к SELECT-запросу. Ему нужно лишь передать имя поля и его значение, которое требуется использовать при выборке. Следующим шагом мы напишем метод «album_edit» в контроллере «Albums». Для начала он будет просто получать данные с помощью вышеописанной функции и выводить их в браузер. В коде этого метода нет ничего сложного, мы просто получим все данные требуемого альбома по его номеру и передадим их обработчику при отображении видов.

PHP код:
function album_edit($album_id)
{
    
$album_id intval($album_id);
    
// Получаем данные альбома
    
$album $this->Albums_model->getAlbumData($album_id);
        
    
// Обрабатываем шаблоны 
    
$this->parser->parse('header',Array());
    
$this->parser->parse('admin/admin_album_edit_form',$album);
    
$this->parser->parse('footer',Array());

Из кода видно что методу должен быть передан номер редактируемого альбома. Если Вы обращали внимание на код отображения их списка, то должны были заметить что `id` альбома передаётся этому методу при клике на ссылку.
http://ci/admin/albums/album_edit/1/
http://ci/admin/albums/album_edit/2/
http://ci/admin/albums/album_edit/3/
Теперь нам осталось лишь создать вид формы редактирования.

Код:
<table width="100%" border="0" cellspacing="0" cellpadding="0">
  <tr>
    <td height="137" valign="top" background="/images/bgt.gif">
      <table width="100" border="0" cellspacing="0" cellpadding="0">
        <tr>
          <td><img src="/images/head.jpg" width=378 height=96 alt=""></td>
          <td><img src="/images/thead.gif" width=372 height=31 alt=""><br>
            <img src="/images/name.jpg" width=372 height=27 alt=""><br>
            <a href=" "><img src="/images/slogan.jpg" width=372 height=18 border=0 alt=""><br>
            </a><img src="/images/index_05.jpg" width=372 height=20 alt=""></td>
        </tr>
      </table>
    </td>
  </tr>
</table>
<center>Редактирование альбома &quot;{name}&quot;</center>
<br /><br />
<form action='/admin/albums/album_save/{id}/' method='POST'>
    <table width="100%" border="0" cellspacing="0" cellpadding="0">
        <tr>
            <td width="81" valign="top"><img src="/images/rc.gif" width=55 height=24 alt=""></td>
            <td>
                <span class='stylesbold'>Название альбома:</span>
            </td>
            <td>
                <input type='text' name='name' value='{name}'/>
            </td>
        </tr>
        <tr>
            <td width="81" valign="top"><img src="/images/rc.gif" width=55 height=24 alt=""></td>
            <td>
                <span class='stylesbold'>Его описание:</span>
            </td>
            <td>
                <textarea name='about' cols='20' rows='5'>{about}</textarea>
            </td>
        </tr>
        <tr>
            <td width="81" valign="top"><img src="/images/rc.gif" width=55 height=24 alt=""></td>
            <td colspan='2'>
                <input type='submit' value='Сохранить' />
                <br /><br />
            </td>
        </tr>
        </form>
</table>
После этого при клике на имя альбома Вы должны попадать на форму его редактирования. Далее мы добавим к этой форме информацию о количестве фотографий в фотоальбоме. Для этого в модели создадим простой метод.
Он будет просто производить подсчёт записей в таблице с помощью функции «COUNT» в SQL-запросе.

PHP код:
function getPhotosCount($album_id)
{
    
$this->db->select('COUNT(id) as count');
    
$query $this->db->get('photos');
    
$row $query->result_array();

    return 
$row[0]['count'];

Используемый здесь метод «select» нужен для указания списка полей используемых при выборке. Но указываем мы не одно поле а фуникцю с выражением «as», для того что бы извлекать результат не из обычного а из ассоциативного массива, что намного удобнее. Обратимся вновь к контроллеру. В метод редактирования мы просто добавим одну строку после получения всех данных о альбоме из базы.

PHP код:
$album['photos_count'] = $this->Albums_model->getPhotosCount($album_id); 
А в шаблон добавим html-код который отобразит новый параметр «photos_count». Это будет новая строка таблицы, вставьте её между полем описания и кнопкой сохранения.

Код:
<tr>
    <td width="81" valign="top"><img src="/images/rc.gif" width=55 height=24 alt=""></td>
    <td>
        <span class='stylesbold'>Количество фотографий в альбоме:</span>
    </td>
    <td>
        <span class='stylesbold'>{photos_count}</span>
    </td>
</tr>