vorst.ru - Пример использования расширения по загрузке фото
Статьи из рубрики upload

Как отсортировать картинки мышкой

Сортировка строк мышкой

Василий оставил комментарий в конце января: "Напишите, пожалуйста, статью, как массово загружать изображения через ajax с возможностью сортировки перетаскиванием."

Речь о расширении yii2-byone-uploader, которое может загружать, сжимать, обрезать картинки для любой модели. Я писал о нем уже пару раз.

На тот момент этой функциональности не было. Собирался я долго. Но вот, наконец добавил требуемое. Теперь спешу написать несколько слов о процессе. Демо (при редактировании).


Как добавить атрибут к загруженному файлу

Добавление описания к файлу

Иногда важно определить дополнительную информацию для загружаемого файла. Например это может быть описание. В расширении yii2-byone-uploader возможность добавить описание к файлу уже предусмотрена.

Кроме описания может быть добавлено и любое другое свойство. В предыдущем примере использовалось свойство when типа radio с двумя значениями - "до" и "после". Как добавить новое свойство?


Как сделать галерею фотографий "До и После"

Показ фотографий до и после момента времени

Представьте, что вы продаете курс похудания. Вам нужно наглядно представить результат вашего курса. Фото "До" и "После", что может быть лучшей иллюстрацией?

Как и в предыдущем примере примем, что участников ограниченное количество. Например 4. Забудем про похудающих - слишком скучно. Будем "работать" с кинозвездами. Для каждого можно загрузить только 4 фотографии. Таким образом всего 16 фото. Если загружены все 16 и кому-то захочется добавить "свои" фото, то придется что-то удалить. Демо.


Делаем демо для загрузки фото

Загрузка жестко определенного количества файлов

Чтобы показать, как работает загрузка изображений, нужно разрешить загружать изображения на свой сайт. Но, в этом случае, дисковое пространство может быть быстро исчерпано и нужно как-то удалять оставленный посетителями "мусор".

Например, можно устроить, что-то вроде надписи в столовой - "Уберите, пожалуйста, за собой посуду" (демо).



Поиск



Делаем демо для загрузки фото

Загрузка жестко определенного количества файлов

Чтобы показать, как работает загрузка изображений, нужно разрешить загружать изображения на свой сайт. Но, в этом случае, дисковое пространство может быть быстро исчерпано и нужно как-то удалять оставленный посетителями "мусор".

Например, можно устроить, что-то вроде надписи в столовой - "Уберите, пожалуйста, за собой посуду" (демо).


    Поделиться

Если ограничить количество загружаемых файлов небольшой цифрой, то очень скоро каждый следующий посетитель будет вынужден удалять файлы предшественников, прежде, чем сам сможет загрузить файлы.

Так и сделаем. Для загрузки будем использовать расширение yii2-byone-uploader. Это расширение, которое хранит информацию обо всех загруженных в приложении файлах, в одной модели - OneFile.

Модель

В модели, которой нужна загрузка файлов, не создается поле с типом file, а "подмешивается" поведение, которое сохраняет информацию о загруженных файлах.

Создадим модель sample\models\Photo.php категорий фотографий. В каждую категорию можно грузить несколько, например 5 фотографий.

namespace sample\models;
use yii\base\Model;
use sergmoro1\uploader\FilePath;
use sergmoro1\uploader\models\OneFile;
class Photo extends Model
{
  public $id;
  public $category;

Модель не связана с таблицей базы данных. Она будет существовать только в памяти. Этого достаточно, ведь информация о загруженных файлах будет хранится в "реальной" модели. Подмешаем эту модель.

  public $sizes = [
    'original' => ['width' => 600, 'height' => 450, 'catalog' => 'original'],
    'main' => ['width' => 400, 'height' => 300, 'catalog' => ''],
    'thumb' => ['width' => 120, 'height' => 90, 'catalog' => 'thumb'],
  ];
  public function behaviors()
  {
    return [
      'FilePath' => [
        'class' => FilePath::className(),
        'file_path' => '/files/photo/',
      ]
    ];
  }

Массив $sizes задает подкаталоги и размеры в которых будет сохраняться загруженное изображение. В поведении определяется основной каталог для хранения файлов модели.

Теперь нужно определить, какие именно файлы относятся к модели.

  public function getFiles()
  {
    return OneFile::find()
      ->where('parent_id=:parent_id AND model=:model', [
        ':parent_id' => $this->id,
        ':model' => 'sample\models\Photo',
      ])
      ->all();
  }

Контроллер

Будем считать, что категории фотографий неизменны и их количество фиксировано. Пусть их всего будет 4. Проще всего задавать их в виде массива sample\controllers\PhotoController.php.

<?php
namespace sample\controllers;
use Yii;
use yii\web\Controller;
use yii\data\ArrayDataProvider;
use sample\models\Photo;
class PhotoController extends Controller
{
  public $models = [
    ['id' => 1, 'category' => 'Street'],
    ['id' => 2, 'category' => 'Office'],
    ['id' => 3, 'category' => 'Factory'],
    ['id' => 4, 'category' => 'Nature'],
  ];
  public $_model;

Теперь легко вывести список категорий.

  public function actionIndex()
  {
    $dataProvider = new ArrayDataProvider([
      'models' => $this->models,
    ]);
    return $this->render('index', [
      'dataProvider' => $dataProvider,
    ]);
  }

Представление

Список в демо немного сложнее, но полное описание только утомит читателя, поэтому приведем только часть, а именно вывод миниатюры sample\views\photo\index.php.

<?= GridView::widget([
  'dataProvider' => $dataProvider,
  'layout' => "{items}\n{summary}\n{pager}",
  'columns' => [
    'id',
    [
      'header' => \Yii::t('app', 'Image'),
      'format' => 'html',
      'options' => ['style' => 'width:120px'],
      'value' => function($data) {
        $model = new Photo(['id' => $data['id'], 'category' => $data['category']]);
        $count = count($model->files);
        return $count == 0 
          ? '<i class="fa fa-3x fa-photo"></i>'
          : Html::img($model->getImage('thumb', $count - 1));
      }
    ],

Выводится последняя загруженная миниатюра. Теперь можно посмотреть, как это работает.

Да и главное!

Как будут загружаться изображения?

В представлении sample/views/photo/update.php вызовем виджет ByOne.

<?php
use sergmoro1\uploader\widgets\Byone;
?>
<?= Byone::widget([
  'model' => $model,
  'secure' => false,
  'maxFiles' => 5,
  'appendixView' => '/photo/appendix',
  'cropAllowed' => true,
]) ?>

А в контроллере sample/controller/PhotoController.php добавим соответствующее действие.

  public function actionUpdate($id)
  {
    return $this->render('update', [
      'model' => $this->getModel($id),
    ]);
  }
  public function getModel($id)
  {
    if($this->_model === null)
    {
      $model = $this->models[$id - 1];
      $this->_model = new Photo(['id' => $model['id'], 'category' => $model['category']]);
    }
    return $this->_model;
  }

Заключение

При подключении расширения yii2-byone-uploader нет необходимости определять поле file в модели, обрабатывать submit и даже определять form. Полная документация, демо.

Комментарии

  • Напишите, пожалуйста, статью, как массово загружать изображения через ajax с возможностью сортировки перетаскиванием, прикрепляя их к другой модели. Нигде ничего путного не найти. Например я хочу сделать изображения для объявления перетаскиванием в объявление(dropzone) (то есть уже должен быть ID у модели объявления, к которому привязать все изображения.) Кроме того пользователь должен иметь возможность тут же сортировать изображения, перетаскивая мышкой. Спасибо Василий
  • -- Попробую. Спасибо! SergeyMorozov
  • And I thought I was the sensible one. Thanks for setting me startghi. Jenibelle
  • -- Thanks ) SergeyMorozov

...

Оставить комментарий

Только авторизованные пользователи могут оставлять комментарии. Пожалуйста авторизуйтесь или пройдите регистрацию.