Фотогалерея в подробностях
Я часто сталкиваюсь с одним и тем же вопросом, который задают многие люди: “как создать фотогалереи в WordPress?” В различных блогах или на сайтах пользователям обычно рекомендуют установить отдельный плагин для создания галерей. Однако на самом деле плагин вам совершенно не нужен, ведь WordPress включает в себя всю необходимую функциональность. Все, что вам требуется – это немного поработать со своей темой.
Сразу сделаю небольшое примечание: Мэтт (Matt Mullenweg) является автором одной из самых опрятных и удобных реализаций фотогалереи. Время от времени я буду ссылаться на фотогалереи от Мэтта в своей записи, поэтому не лишним будет сначала ознакомиться с бесподобной галереей на сайте Мэтта, прежде чем приступать к созданию собственных галерей на своем сайте. Возможно, вы почерпнете с сайта Мэтта что-нибудь интересное для себя.
Концепция галерей
Первое, что вы должны знать, – как именно в WordPress организованы галереи. По своей сути, галерея – это всего лишь запись с набором прикрепленных изображений.
При создании новой записи или при ее редактировании вы можете воспользоваться настройкой, позволяющей вам загружать изображения или иные файлы. Когда вы загружаете файл через стандартный загрузчик, WordPress создает запись только для этого файла. Эта запись имеет post_type, равный “attachment”. Изображения, в отличие от иных прикреплений, получают некоторую дополнительную обработку: они могут выводиться в нескольких размерах, могут быть добавлены к записям и т.д. Вы, скорее всего, уже знакомы с этим. Спешу предположить, что вы уже сталкивались и с вложением галерей в запись, которое происходит с помощью шорткода “gallery”.
С чем же вы тогда не знакомы? Давайте копнем поглубже! К примеру, WordPress не просто изменяет размеры тех изображений, которые вы загружаете, но еще и получает метаданные и другую информацию об изображениях. WordPress захватывает EXIF данные изображения и хранит их как postmeta пункты для прикрепленных записей. По своей сути прикрепленная запись является дочерним элементом родительской записи, содержащей в себе галерею. Таким образом, вся галерея – это сумма прикрепленных записей, являющихся дочерними элементами главной записи.
Не волнуйтесь, работать с этим гораздо проще, чем кажется на первый взгляд.
Создание шаблона для изображений
Первое, что вы должны будете сделать, – это отредактировать свою тему (или создать дочернюю тему, как вам удобнее). Вам понадобится создать файл “image.php”.
(Небольшое примечание: даже если вы тщательно изучите исходники WordPress, вы не найдете в них загрузки файла “image.php”, поскольку она происходит иным образом. Фактически выполняется поиск mime-типа для прикрепления, представленного в виде имени файла. Если вы загружали файл JPG, то в таком случае mime-тип будет задан как “image/jpeg”. WordPress сначала попытается отыскать файл image.php, затем jpeg.php, затем image_jpeg.php, и, наконец, будет использовать attachment.php как универсальную основу. Этот процесс выполняется для всех прикреплений и всех mime-типов. Таким образом, в вашей теме может присутствовать video.php для видео прикреплений, audio.php для аудио прикреплений и т.д.)
image.php – это шаблон, который будет загружаться для “отдельных изображений”. Галерея выводит на экран миниатюры, щелчок по которым перенесет вас на прикрепленную страницу для выбранного изображения. Самый простой способ создать страницу для изображений – это скопировать файл для отдельных записей и переименовать его (берем single.php, копируем и переименовываем в image.php). Если в вашей теме отсутствует файл single.php, тогда для этих же целей можно воспользоваться файлом index.php.
Настройка шаблона для изображений
Поскольку наш файл должен будет работать с изображениями, нам понадобится расширить его возможности. Также нам потребуется создать специальные навигационные элементы, отсутствующие у других записей.
Для начала, у нас есть родитель, который является записью, содержащей в себе галерею. Допустим, нам необходимо вывести на экран название этой записи. Как это осуществить? Легко – мы можем сослаться на родителя с помощью $post->post_parent. Таким образом, код, подобный get_the_title($post->post_parent), приведет к тому, что мы получим заголовок, который впоследствии всегда можно будет вывести на экран с помощью echo. Аналогично, использование get_permalink($post->post_parent) позволит нам получить ссылку на галерею. Давайте применим это в нашем шаблоне для изображений:
echo "<a href='" . get_permalink($post->post_parent). "'>Go back to ". get_the_title($post->post_parent) ."</a>";
Для навигации у нас есть специальные функции – previous_image_link и next_image_link, – которые позволят нам отображать ссылки к предыдущим и следующим изображениям, находящимся в галерее. Каждая из функций принимает два параметра. Первый из них – это размер предыдущего или последующего изображения, которое мы хотим вывести на экран (false – если мы вообще не хотим показывать миниатюры). Второй параметр – это текст, который будет использован в качестве ссылки. Для того чтобы отобразить несколько текстовых навигационных ссылок, нам понадобится следующий код:
echo previous_image_link(false,'Previous Photo'); echo next_image_link(false,'Next Photo');
Если бы мне понадобились изображения вместо текстовых ссылок, я всего лишь изменил бы значение false на ‘thumbnail’, чтобы вывести на экран миниатюры изображений. Или на ‘medium’. Или на любое другое значение размера, которое я бы предпочел.
Теперь нам нужно вывести изображение на экран. Об этом позаботится функция wp_get_attachment_image:
echo wp_get_attachment_image( $post->ID, 'medium' );
Второй параметр здесь – это размер изображения. Вместо “medium” мы могли бы использовать ‘large’, ‘full’, ‘thumbnail’ или любой другой из размеров изображения. Если вы хотите, чтобы изображение было кликабельным (меняло свой размер по щелчку), вам понадобится заключить его в тег A и связать его с полноразмерным изображением.
Не стоит забывать, что прикрепленные записи – это по-прежнему записи! Все поля, которые можно заполнить в загрузчике изображений, доступны вам для использования. К примеру, “Title” (заголовок) хранится в обычном поле Post Title, таким образом, вы можете легко вызвать его с помощью the_title(). Значение Description (описание) хранится в поле Content и может быть отображено благодаря the_content(). Значение Caption (подпись) хранится в поле Excerpt и может быть выведено на экран с помощью the_excerpt(). Вы можете пользоваться этим в случае необходимости.
EXIF информация
Пример одной из страниц с отдельным изображением в блоге Мэтта: http://ma.tt/2011/05/balloon-ride/mcm_9033/.
Выглядит довольно неплохо. Прокрутите страницу немного вниз и посмотрите на правую панель, которая называется INFO. Там расположена полезная информация об изображении. Мэтт ничего не добавлял вручную, вся информация о файле была выведена с помощью WordPress.
Чтобы получить доступ к этой информации, вам понадобится добавить в файл image.php следующий код:
$imagemeta = wp_get_attachment_metadata();
Если вы исследуете этот массив, то увидите, что он содержит в себе ширину, высоту, имена файлов для различных размеров сгенерированных миниатюр и т.д. Также он содержит в себе массив, названный “image_meta”. Этот массив включает в себе всю информацию, которую система WordPress смогла вытащить из изображения. Теперь, когда вы знаете это, нам останется лишь должным образом вывести ее на экран.
К примеру, чтобы вывести на экран название фотокамеры, нам понадобится следующий код:
if ($imagemeta['image_meta']['camera']) { echo "Camera: " . $imagemeta['image_meta']['camera']; }
Существуют и другие параметры фотокамеры, такие как апертура, фокусное расстояние, параметры ISO и скорость затвора. Большинство из них выводится на экран напрямую, за исключением скорости затвора, которую обычно тяжело вывести на экран, поскольку она является дробным значением, представленным как десятичное число. Нам же требуется именно дробное представление, поэтому приходится проводить некоторые преобразования. Следующий код поможет справиться с этим:
if ($imagemeta['image_meta']['shutter_speed']) { echo 'Shutter: '; // shutter speed handler if ((1 / $imagemeta['image_meta']['shutter_speed']) > 1) { echo "1/"; if (number_format((1 / $imagemeta['image_meta']['shutter_speed']), 1) == number_format((1 / $imagemeta['image_meta']['shutter_speed']), 0)) { echo number_format((1 / $imagemeta['image_meta']['shutter_speed']), 0, '.', '') . ' sec'; } else { echo number_format((1 / $imagemeta['image_meta']['shutter_speed']), 1, '.', '') . ' sec'; } } else { echo $imagemeta['image_meta']['shutter_speed'].' sec'; } }
Чересчур громоздко, я знаю, но этот код справляется со своей задачей.
Форматирование галереи в потоке
Теперь нам понадобится сделать так, чтобы записи хорошо смотрелись и в обычном потоке блога. Темы Twenty-Ten и предстоящая Twenty-Eleven помогут нам реализовать это. Ранее Twenty-Ten использовала для этого рубрику “gallery”, однако вскоре на замену неудобной рубрике пришли форматы записей.
Таким образом, очевидно, что ваша тема должна поддерживать формат записей Gallery. Сделать это довольно просто: достаточно добавить в файл functions.php следующий код, отвечающий за поддержку галерей:
add_theme_support( 'post-formats', array( 'gallery') );
Добавлять этот код необходимо только в том случае, если тема не поддерживает форматы записей. Теперь, когда это сделано, вы можете выбрать галерею в качестве формата записей. Вам понадобится отредактировать свою тему, чтобы использовать этот флаг в качестве индикатора для различного отображения элементов.
Я буду исходить из предположения, что вы знакомы с has_post_format(‘gallery’), и знаете, как использовать “.home .format-gallery” CSS для необходимого представления записей.
Как вывести на экран выбранное изображение из галереи в основном потоке блога? Для этого нужно сделать два основных шага.
Для начала вам нужно создать запись, к примеру: http://ma.tt/2011/05/20/. Вот как это сообщение фактически будет выглядеть в редакторе:
Небольшой текст, который связан с путешествиями на аэростате < !--more-- > [ gallery ]
Другими словами, Мэтт вначале разместил описание, после которого идет тег more, а затем уже и сама галерея. Здесь мы можем столкнуться с эффектом разделения текстового описания и галереи. Галерея не будет выводиться на главной странице, потому что она следует уже после тега more. Таким образом, вызов the_content() на потоковых страницах приведет к отображению одного лишь описания.
Наконец, можно легко настроить функцию Featured Image так, чтобы вы могли выбирать, какое изображение выводить на экран в потоке. Все, что должен сделать пользователь, это загрузить свою галерею, выбрать одно из изображений и установить его в качестве featured image. Таким образом, это изображение будет основным представителем галереи.
if ( has_post_thumbnail() ) { // используем миниатюру ("featured image") $thumb_id = get_post_thumbnail_id(); the_post_thumbnail( $size ); // устанавливаем необходимый размер }
Блок div позволяет разместить изображение по правой стороне, по левой стороне, или в любой другой позиции, которая вам больше всего подходит. С помощью функции get_children и дополнительного кода вы всегда можете установить в качестве представителя по умолчанию первое изображение в галерее, если пользователь не сделал выбор.
else { $attachments = get_children( array( 'post_parent' => get_the_ID(), 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'menu_order ID', 'numberposts' => 1) ); foreach ( $attachments as $thumb_id => $attachment ) echo wp_get_attachment_image($thumb_id, $size); // размер, который вам требуется } }
Использование таких приемов позволяет получить части галереи и вывести их на экран разнообразными способами.
Создание специального шаблона страниц для галерей
Страница для галерей в блоге Мэтта индивидуально настроена. Она отображает галереи необычным образом. На странице расположена крупная копия featured image, которая дополнена несколькими минатюрами чуть ниже описания. Также на этой странице выводится число изображений, находящихся в каждом “альбоме”. Все это построено на базе специально разработанного шаблона.
Давайте для начала создадим шаблон страниц:
/* Template Name: Gallery */
В самом верху нашего шаблона мы добавим специальный запрос таксономии, который получит все записи в галерее (либо все записи в рубрике gallery, что сделано для обратной совместимости). Ниже представлен код, отвечающий за это:
$args = wp_parse_args($query_string); query_posts(array( 'tax_query' => array( 'relation' => 'OR', array( 'taxonomy' => 'post_format', 'terms' => array('post-format-gallery'), 'field' => 'slug', ), array( 'taxonomy' => 'category', 'terms' => array('gallery'), 'field' => 'slug', ), ), 'paged' => $args['paged'], ) );
Сначала мы получаем нормальные параметры, а затем перезаписываем их с помощью нашего собственного запроса. Единственный параметр, который мы используем из нормального набора – это номер страницы, необходимый для разбиения материалов по нескольким страницам.
Наш перезаписанный запрос использует усовершенствованный запрос таксономии. В данном случае он будет выбирать любые записи в формате gallery или любые сообщения в рубрике gallery. Передавая его в query_posts, мы перезапишем наш запрос основной страницы, и, таким образом, наш основной цикл выведет на экран только записи из галереи.
После этого останется лишь вопрос, что мы хотим вывести на экран.
Наш основной цикл является довольно простым. Чтобы вывести на экран featured image, мы используем по существу тот же самый код, что и раньше, только для крупного размера.
Чтобы вывести на экран описание, мы используем the_content(). Единственная вещь, которую мы должны сделать, – это обнулить значение глобальной переменной $more, чтобы воспрепятствовать выводу полной галереи и ограничиться выводом ее части до тега !–more–.
Получение количества изображений – более сложный процесс. В WordPress нет функции, позволяющей облегчить ваш труд. Поэтому нам понадобится сделать SQL запрос:
echo $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts WHERE post_parent = '$post->ID' AND post_type = 'attachment'" ) .' PHOTOS IN THIS SET';
Четыре миниатюры вы можете вывести при помощи одного хитрого приема: с помощью get_children. Более того, в этом имеется определенная выгода. Нам не надо, чтобы featured image выводилось в тех четырех миниатюрах. А поскольку мы уже вывели на экран это изображение (см. код выше), у нас осталась переменная $thumb_id. Таким образом, мы будем использовать ее, чтобы не получить вновь это изображение. Пример:
$attachments = get_children( array( 'post_parent' => get_the_ID(), 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'menu_order ID', 'numberposts' => 4, 'exclude' => $thumb_id ) ); foreach ( $attachments as $img => $attachment ) { echo '<a href="'.get_permalink($img).'">'.wp_get_attachment_image( $img, $size ).'</a>'; }
С помощью параметра exclude мы получим первые четыре изображения в галерее, исключив наше featured image, если оно находилось в их числе.
Небольшой апдейт
Andrew Nacin подсказал мне, что можно объединить получение тех четырех дочерних элементов и счетчика прикреплений в отдельный новый объект WP_Query:
$images = new WP_Query( array( 'post_parent' => get_the_ID(), 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'menu_order ID', 'posts_per_page' => 4, 'post__not_in' => array($thumb_id), 'update_post_term_cache' => false, ) );
Это приведет к созданию второго запроса, который можно будет циклически выполнить, чтобы показать дочерние элементы:
foreach ($images->posts as $image) { echo '<a href="'.get_permalink($image->ID).'">'.wp_get_attachment_image( $image->ID, $size ).'</a>'; }
В качестве дополнительной выгоды можно отметить ведение первичного подсчета изображений через SQL_CALC_FOUND_ROWS, который используется в полномасштабных запросах. Однако счетчик будет отставать на единицу, поскольку мы исключили featured thumbnail. Поэтому, мне необходимо добавить следующий код:
echo ($images->found_posts+1) . ' PHOTOS IN THIS SET';
Такой подход позволяет объединить два действия в одном запросе и избавляет от необходимости использовать прямой SQL запрос.
(Примечание: я также установил ‘update_post_term_cache’ в false, чтобы исключить выполнение дополнительного запроса для размещения термов этих записей в кэше внутренней памяти. Это спасает нас от набора ненужных запросов, тем более, я не прибегаю здесь к термам. Использование полных объектов WP_Query вместо более простых, таких как get_children, может оказаться несколько сложным, однако в конечном счете позволит значительно сэкономить время при грамотном их применении.)
Размеры
На протяжении всей записи я использовал $size в качестве универсальной переменной для размещения размера. Как мы с вами знаем, по умолчанию WordPress создает изображения разных размеров. В числе доступных размеров: миниатюры, средний, большой и полный (последний представляет собой естественные размеры загруженного изображения без изменений).
Однако WordPress позволяет создавать и другие размеры. В разных участках галереи Мэтта вы будете видеть изображения, выведенные на экран в различных размерах. Эти размеры являются произвольными: они установлены в файле functions.php:
add_image_size( 'nav-thumbnail', 100, 100, true ); add_image_size( 'random-thumbnail', 200, 150, true ); add_image_size( 'gallery-thumbnail', 250, 200, false ); add_image_size( 'gallery-large', 660, 500, false ); add_image_size( 'gallery-pagethumb', 70, 70, true );
Функция add_image_size получает высоту, ширину и флаг, который указывает, необходимо или нет обрезать изображение. Таким образом, те крошечные миниатюры в галерее имеют размер “gallery-pagethumb”, равный 70х70 пикселей, и являются урезанными. Если мне где-либо понадобятся эти размеры, я просто передам необходимый параметр вместо $size.
Очевидно, что добавление слишком многих размеров является нежелательным, потому что это отнимает определенное время на их создание (они создаются в процессе загрузки изображений) и требует дополнительного пространства памяти для их хранения. Мы надеемся, что в следующей версии WordPress эта проблема будет решена.
Заключение
В этой статье мы привели основы создания привлекательных галерей, без плагинов, без специальных загрузчиков; этим галереям можно придать любую стилизацию, в которой вы нуждаетесь, чтобы они соответствовали вашей теме. Играйте с этим. Экспериментируйте. В WordPress существует огромное количество функций для работы с галереями. Откройте wp-includes/media.php и посмотрите, сколько разных названий функций там упоминается. Вы будете удивлены.
Источник: http://ottopress.com/2011/photo-gallery-primer/