Yii: Фотогалерея через поведение (доработка расширения imagesgallerymanager)
Делаю фотогалерею на Yii через поведение. Для Yii2 это расширение описано тут - http://yiico.ru/blog/501-fotogaleryeya-dlya-yii2-rasshirenie-zxbodya-yii2-gallery-manager
Давненько копилось желание организовать фотогалерею на Yii. Сделал это опираясь на существующие на сегодняшний день расширения для Yii. Так как сам проект начал делать на Yii-app от Chris83, то ожидал как-то использовать yii-imagemanager, который входит в yii-app. Но стало понятно, что оно обрабатывает отдельно фотографии и не предлагает галереи фото.
Попалось расширение от Bogdan Savluk - imagesgallerymanager (на bitbucket). Оно позволяет через поведение подвесить менеджер загрузки (+редактирования информации к фотке) прямо к нужной модели. Несколько доработал это расширение, чтобы фотографии сохранялись на сервере по папкам (название папок формируется по псевдониму записи (можно заменить и на значение любого поля в записи модели) - например, у меня это alias у группы). Папки создаются сами в директории gallery, и при удалении последней картинки из папки, сама папка тоже удаляется.


Устанавливаем сначала imagesgallerymanager (для него понадобится расширение yii-image).
config/main.php
'import' => array(
...
'ext.galleryManager.*',
'ext.galleryManager.models.*',
'ext.image.*',
...
// application components
'components' => array(
...
'image' => array(
'class' => 'application.extensions.image.CImageComponent',
// GD or ImageMagick
'driver' => 'GD',
// ImageMagick setup path
'params' => array('directory' => '/opt/local/bin'),
),
// controllers mappings
'controllerMap' => array(
...
'image' => array('class' => 'vendor.crisu83.yii-imagemanager.controllers.ImageController'),
'gallery' => array('class' => 'ext.galleryManager.GalleryController'),
),
...
public function behaviors()
{
return array(
'galleryBehavior' => array(
'class' => 'GalleryBehavior',
'idAttribute' => 'gallery_id',
'versions' => array(
'small' => array(
'centeredpreview' => array(200, 200), //array(98, 98),
),
'medium' => array(
'resize' => array(800, null),
)
),
'name' => true,
'description' => true,
)
);
}
...
...
<h2>Product galley</h2>
<?php
if ($model->galleryBehavior->getGallery() === null) {
echo '<p>Before add photos to product gallery, you need to save product</p>';
} else {
$this->widget('GalleryManager', array(
'gallery' => $model->galleryBehavior->getGallery(),
'controllerRoute' => '/gallery'
));
}
?>
...
Дорабатываю расширение imagesgallerymanager для сохранения фоток по папкам.
...
public function behaviors()
{
return array(
'galleryBehavior' => array(
'class' => 'GalleryBehavior',
'imagePath' => 'gallery/'.$this->alias,
'idAttribute' => 'gallery_id',
'versions' => array(
'small' => array(
'centeredpreview' => array(200, 200),
),
'medium' => array(
'resize' => array(800, null),
)
),
'name' => true,
'description' => true,
)
);
}
...
class GalleryBehavior extends CActiveRecordBehavior
{
/** @var string Model attribute name to store created gallery id */
public $imagePath = ''; // вот она
/** @var string Model attribute name to store created gallery id */
public $idAttribute;
...
class GalleryController extends Controller
{
public $galleryDir = 'gallery';
public function filters()
{
...
public function actionDelete($galleryphotospath = null) // !! id передаётся через POST, а galleryphotospath — через GET
{
$id = $_POST['id'];
//$galleryphotospath = $_POST['galleryphotospath'];
/** @var $photos GalleryPhoto[] */
$photos = GalleryPhoto::model()->findAllByPk($id);
// foreach ($photos as $photo) {
// if ($photo !== null) $photo->delete();
foreach ($photos as $photo) {
if ($photo !== null) {
$photo->galleryDir = $photo->galleryDir."/".$galleryphotospath;
$photo->delete();
}
...
public function actionAjaxUpload($gallery_id = null, $galleryphotospath = null)
{
$model = new GalleryPhoto();
$model->galleryDir = $model->galleryDir."/".$galleryphotospath;
$model->gallery_id = $gallery_id;
$imageFile = CUploadedFile::getInstanceByName('image');
$model->file_name = $imageFile->getName();
$model->save();
$this->createDirectory($_SERVER['DOCUMENT_ROOT'].Yii::app()->urlManager->baseUrl. '/' .$model->galleryDir);
$model->setImage($imageFile->getTempName());
header("Content-Type: application/json");
echo CJSON::encode(
...
... public $gallerypath; ...
...
$photos = array();
foreach ($this->gallery->galleryPhotos as $photo) {
$photo->galleryDir = $photo->galleryDir."/".$this->gallerypath;
$photos[] = array(
'id' => $photo->id,
'rank' => $photo->rank,
'name' => (string)$photo->name,
'description' => (string)$photo->description,
'preview' => $photo->getPreview(),
);
}
$opts = array(
'hasName' => $this->gallery->name ? true : false,
'hasDesc' => $this->gallery->description ? true : false,
'uploadUrl' => Yii::app()->createUrl($this->controllerRoute . '/ajaxUpload', array('gallery_id' => $this->gallery->id, 'galleryphotospath' => $this->gallerypath)),
'deleteUrl' => Yii::app()->createUrl($this->controllerRoute . '/delete', array('galleryphotospath' => $this->gallerypath)),
'updateUrl' => Yii::app()->createUrl($this->controllerRoute . '/changeData'),
'arrangeUrl' => Yii::app()->createUrl($this->controllerRoute . '/order'),
'nameLabel' => Yii::t('galleryManager.main', 'Name'),
'descriptionLabel' => Yii::t('galleryManager.main', 'Description'),
'photos' => $photos,
);
...
...
public function delete()
{
$this->removeFile(Yii::getPathOfAlias('webroot') . '/' . $this->galleryDir . '/' . $this->getFileName('') . '.' . $this->galleryExt);
$this->removeFile(Yii::getPathOfAlias('webroot') . '/' . $this->galleryDir . '/_' . $this->getFileName('') . '.' . $this->galleryExt);
$this->removeImages();
@unlink(Yii::getPathOfAlias('webroot') . '/' .$this->galleryDir. '/.DS_Store');
//array_map("unlink", glob(Yii::getPathOfAlias('webroot') . '/' .$this->galleryDir. '/.DS_Store')); // MAC OS X создаёт файл .DS_Store, который мешает удалять папку rmdir, так как она должна быть пустой, чтобы сработала функция rmdir
// если в папке gallery/alias_группы нет изображений, то удалять нахрен эту папку
if($this->regExpFile("/jpg$/", Yii::getPathOfAlias('webroot') . '/' .$this->galleryDir, $regType='P', $case='') === false) {
rmdir(Yii::getPathOfAlias('webroot') . '/' .$this->galleryDir);
}
return parent::delete();
}
...
function regExpFile($regExp, $dir, $regType='P', $case='') {
# Two parameters accepted by $regType are E for ereg* functions
# and P for preg* functions
$func = ( $regType == 'P' ) ? 'preg_match' : 'ereg' . $case;
# Note, technically anything other than P will use ereg* functions;
# however, you can specify whether to use ereg or eregi by
# declaring $case as "i" to use eregi rather than ereg
$open = opendir($dir);
while( ($file = readdir($open)) !== false ) {
if ( $func($regExp, $file) ) {
return true;
}
} // End while
return false;
} // End function
// <h2>Product galley</h2>
<h2>Фотографии коллектива</h2>
<?php
if ($model->galleryBehavior->getGallery() === null) {
echo '<p>Before add photos to product gallery, you need to save product</p>';
} else {
$this->widget('GalleryManager', array(
'gallery' => $model->galleryBehavior->getGallery(),
'controllerRoute' => '/gallery',
'gallerypath' => $model->alias,
));
}
?>
-- -----------------------------------------------------
-- Table `tbl_gallery`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `tbl_gallery` (
`id` INT NOT NULL AUTO_INCREMENT ,
`versions_data` TEXT NOT NULL ,
`name` TINYINT(1) NOT NULL DEFAULT 1 ,
`description` TINYINT(1) NOT NULL DEFAULT 1 ,
PRIMARY KEY (`id`) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `tbl_gallery_photo`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `tbl_gallery_photo` (
`id` INT NOT NULL AUTO_INCREMENT ,
`gallery_id` INT NOT NULL ,
`rank` INT NOT NULL DEFAULT 0 ,
`name` VARCHAR(512) NOT NULL DEFAULT '',
`description` TEXT NULL,
`file_name` VARCHAR(128) NOT NULL DEFAULT '',
PRIMARY KEY (`id`) ,
INDEX `fk_gallery_photo_gallery1` (`gallery_id` ASC) ,
CONSTRAINT `fk_gallery_photo_gallery1`
FOREIGN KEY (`gallery_id` )
REFERENCES `tbl_gallery` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
А теперь выводим галерею на странице группы (тоже через поведение)
<?php css('css/colorbox.css'); ?>
<?//php Yii::app()->clientScript->registerCssFile(Yii::app()->request->baseUrl . "/css/colorbox.css", CClientScript::POS_END); ?>
<?php js('js/jquery.colorbox-min.js'); ?>
<script>
jQuery(document).ready(function () {
jQuery('a.gallery').colorbox({ opacity:0.5 , rel:'group1', loop:false });
jQuery('a.<?php echo $model->alias;?>').colorbox({ opacity:0.5 , rel:'group1', loop:false });
});
</script>
...
<?php if(isset($model->gallery_id) && $model->gallery_id != "0") : ?>
<section id="photo">
<h3>Фото</h3>
<?php
$this->widget('GalleryViewer', array(
'gallery' => $model->galleryBehavior->getGallery(),
'controllerRoute' => '/gallery',
'gallerypath' => $model->alias,
));
?>
</section>
<?php endif; ?>
...
<?php
class GalleryViewer extends CWidget
{
/** @var Gallery Model of gallery to manage */
public $gallery;
/** @var string Route to gallery controller */
public $controllerRoute = false;
public $assets;
public $gallerypath;
public $htmlOptions = array();
/** Render widget */
public function run()
{
/** @var $cs CClientScript */
$photos = array();
foreach ($this->gallery->galleryPhotos as $photo) {
$photo->galleryDir = $photo->galleryDir."/".$this->gallerypath;
/*$photos[] = array(
'id' => $photo->id,
'rank' => $photo->rank,
'name' => (string)$photo->name,
'description' => (string)$photo->description,
'preview' => $photo->getPreview(),
);*/
}
$this->render('galleryViewer', array('photos'=>$this->gallery->galleryPhotos, 'groupalias'=>$this->gallerypath));
}
}
<ul class="thumbnails">
<?php foreach($photos as $photo): ?>
<li class="span3"><a class="<?php echo $groupalias; ?> thumbnail" href="<?php echo $photo->url; ?>"><img src="<?php echo $photo->getUrl("small"); ?>" alt="<?php echo $photo->name; ?>" /></a></li>
<?php endforeach; ?>
</ul>
almix
Разработчик Loco, автор статей по веб-разработке на Yii, CodeIgniter, MODx и прочих инструментах. Создатель Team Sense.
Вы можете почитать все статьи от almix'а.
- 14 Разработка приложения на Yii. Урок 14: Выводим список категорий как новый виджет на сайте (29.04.2015)
- 13 Разработка приложения на Yii. Урок 13: Внедряем категории для статей. (29.04.2015)
- 12 Разработка приложения на Yii. Урок 12: Профилирование приложения, включаем кеширование. (20.01.2015)
- 11 Yiico. Видеокурс по разработке сайта на Yii. Урок 11: Отладка приложения, включаем журналирование. (20.01.2015)
- 10 Yiico. Видеокурс по разработке сайта на Yii. Урок 10: Если ваше приложение находится не в корневой папке, а во вложенной. (19.10.2014)
- 9 Разработка сайта на Yii с нуля. Урок 9. Выборка статей определённого автора. (13.08.2014)
- 8 Разработка сайта на Yii с нуля. Урок 8. Вызов в моделях функции, общей для них. Как избегать дублирования кода? (25.07.2014)
- 7 Разработка сайта на Yii с нуля. Урок 7. Изменение количества выводимых записей на странице в CGridView. Включаем сессии Yii. (04.09.2013)
- 6 Разработка сайта на Yii с нуля. Урок 6. Автоматич. отправка оповещений об одобренных комментариях на email автора комментария (11.08.2013)
- 5 Разработка сайта на Yii с нуля. Урок 5. Переименовываем blog в yiico. Изменяем "Home" в breadcrumbs. Включаем Gzip-сжатие. (09.08.2013)
- 4 Курс по Yii с нуля. Урок 4. Дорабатываем простую работу с пользователями: хранение пароля при редактировании пользователя. (13.04.2013)
- 3 Курс по Yii с нуля. Урок 3. Создаём новых пользователей. Организуем простую систему авторизации. Аутентификация, пароли, соли. (20.07.2014)
- 2 Yii + Git (github) на Mac. (24.03.2013)
- 2 Курс по Yii с нуля. Урок 2. Переносим и настраиваем Yii и проект нашего сайта на рабочем сервере. Избавляемся от index.php в url (09.07.2014)
- 1 Курс по Yii с нуля. Урок 1. Устанавливаем Yii на локальном компьютере. Заводим проект будущего сайта. (10.03.2013)
- 0 Composer – пакетный менеджер PHP. Что и как? (22.07.2014)
- 0 MySQL: проверить содержится ли значение в поле столбца (в столбце хранится строка значений через запятую) (22.05.2014)
- 0 Yii: Статичные страницы (создание, редактирование, удаление) (28.04.2014)
- 0 Yii: Расширение ECKEditor = Связка ckeditor + kcfinder (визуальный редактор с бесплатным файловым менеджером) (28.04.2014)
- 0 Yii: Bootstrap tabs, делаем активной вкладку на которую выполняется переход по ссылке (20.03.2014)
- 0 Yii: Доступ к атрибуту модели из файла шаблона (Вызов в шаблоне какого-либо атрибута модели). (17.02.2014)
- 0 Yii: Множественный автокомплит с помощью CJuiAutoComplete (автокомплит нескольких значений в одно поле) (07.02.2014)
- 0 Yii: Фотогалерея через поведение (доработка расширения imagesgallerymanager) (08.03.2016) ← вы тут
- 0 Yii: Установка и настройка Yii-app заготовки приложения от Crisu83 (09.03.2014)
- 0 Twitter Bootstrap Carousel Crossfade (09.09.2013)



2 комментариев
Спасибо Вам, что поделились своим кодом - как раз собирался переделывать галерею под Yii .
Если не сложно, уточните по расширению image
У вас в коде упоминается два (от z_bodya и crisu83 )причем первый объявлен компонентом, а второй указан в controllerMap
Заранее благодарен, Александр.