Пример работы расширения для загрузки фотографий - vorst.ru

До и После


галерея фотографий, загруженных до и после момента времени

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

До и После

галерея фотографий, загруженных до и после момента времени

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

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


Опять будем использовать расширение yii-byone-uploader. Это расширение хранит все файлы в одной модели и модель имеет поле defs в котором могут храниться json определения любых переменных.

По умолчаниюю доступно поле description, но можно добавить любое другое. Например when со значениями - 0 ("До"), 1 ("После").

Модель

Подключение поведения такое же, как в предыдущем примере. Фото, однако, квадратное.

А отличие sample\models\Stout.php в том, что необходимо найти, среди фото, принадлежащих модели, фотографии "До" и "После".

<?php
namespace sample\models;
use yii\helpers\Html;
use yii\base\Model;
use sergmoro1\uploader\FilePath;
use sergmoro1\uploader\models\OneFile;
class Stout extends Model
{
  const BEFORE = 0;
  const AFTER = 1;
  public $id;
  public $name;
  public $sizes = [
    'original' => ['width' => 600, 'height' => 600, 'catalog' => 'original'],
    'main' => ['width' => 240, 'height' => 240, 'catalog' => ''],
    'thumb' => ['width' => 90, 'height' => 90, 'catalog' => 'thumb'],
  ];
  public function behaviors()
  {
    return [
      'FilePath' => [
        'class' => FilePath::className(),
        'file_path' => '/files/stout/',
      ]
    ];
  }
  public function findOne($id)
  {
    return new Stout(['id' => $id]);
  }
  public function getFiles()
  {
    return OneFile::find()
      ->where('parent_id=:parent_id AND model=:model', [
        ':parent_id' => $this->id,
        ':model' => 'sample\models\Stout',
      ])
      ->all();
  }
  private function getMainImage($when)
  {
    $image = false;
    foreach($this->files as $i => $file)
      if($file->vars->when == $when)
      {
        $image = $this->getImage('', $i);
        break;
      }
      return $image;
  }
  public function getBefore()
  {
    return $this->getMainImage(self::BEFORE);
  }
  public function getAfter()
  {
    return $this->getMainImage(self::AFTER);
  }
}

Сделано это простым перебором среди всех, принадлежащих модели, файлов.

Контроллер

Действия всего два и они не отличаются от действий предыдущего примера. Несколько "странноватый" вид метода getModel обусловлен тем, что модель - это массив, а не объект, как обычно.

<?php
namespace sample\controllers;
use Yii;
use yii\web\Controller;
use yii\data\ArrayDataProvider;
use sample\models\Stout;
class StoutController extends Controller
{
  public $models = [
    ['id' => 1, 'name' => 'Jean-Paul Belmondo'],
    ['id' => 2, 'name' => 'Claudia Cardinale'],
    ['id' => 3, 'name' => 'Monica Bellucci'],
    ['id' => 4, 'name' => 'Adriano Celentano'],
  ];
  public $_model;
  public function actionIndex()
  {
    $dataProvider = new ArrayDataProvider([
      'models' => $this->models,
    ]);
    return $this->render('index', [
      'dataProvider' => $dataProvider,
    ]);
  }
  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 Stout([
        'id' => $model['id'], 
        'name' => $model['name'],
      ]);
    }
    return $this->_model;
  }
}

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

sample\views\stout\index.php проще не куда.

<?php
use yii\widgets\ListView;
?>
<?= ListView::widget([
  'dataProvider' => $dataProvider,
  'layout' => "{items}",
  'itemView' => '_stout',
]); ?>

Вся магия в sample\views\stout\_stout.php. Но эффекты не так важны и их описание мы опустим. Главное, как выводятся фотографии

<div class='col-sm-6'>
  <div class='photo-block'>
    <div class='photo-column pull-left'>
      <div class='mark'>before</div>
        <?= ($image = $model->getBefore())
          ? Html::img($image, ['class'=>'grow'])
          : '<i class="fa fa-3x fa-user"></i>'
        ?>
      </div>
      <div class='photo-column pull-left'>
        <div class='mark'>after</div>
          <?= ($image = $model->getAfter())
            ? Html::img($image, ['class'=>'grow'])
            : '<i class="fa fa-3x fa-user"></i>'
          ?>
      </div>
      <div class='footer'>
        <?= $model->name ?>
      </div>
  </div>
  <p class='text-center'>
    <?= Html::a(\Yii::t('app', 'Update'), ['update', 'id' => $model->id]) ?>
  </p>
</div>

и как вводятся sample\views\stout\update.php.

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

Все! Если предположить, что значение поля when определяется средствами расширения, то можно считать, что алгоритм вывода фотографий "До" и "После" ясен и пора посмотреть, что получилось. Демо.

Заключение

Использовать расширение yii-byone-uploader просто. Но интересно то, что можно добавлять дополнительные поля данных, не меняя модели. Как было добавлено поле when можно узнать в следующей статье.

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