Новые типы столбцов в списках OctoberCMS

В плагинах OctoberCMS обычно мы имеем дело с моделями. Допустим, есть у нас вот такой список моделей как на картинке. Это список моделей Photo, принадлежащих одной модели Album. Сделать такой список легко — пара строчек в контроллере и он создастся автоматически.

Как можно заметить, список в данном случае не сильно удобный: у многих фотокарточек нет названия. Через это вообще невозможно понять, где какая фотография находится. В общем, хотелось бы, чтобы в таблице были картинки. Ну и заодно чтоб можно было отметить ту картинку, которая выбрана обложкой альбома.

Список столбцов задается (по умолчанию) в файле columns.yaml для отображаемой модели. Туда можно добавлять новые столбцы, но их набор довольно ограничен. Зато, как написано на этой же странице документации, можно добавлять свои типы столбцов. И сейчас мы рассмотрим эту возможность, чуть-чуть подробнее, чем в доках.

Начнем со столбца Is Front, в котором мы отметим фотокарточку, выбранную обложкой альбома. Зарегистрируем новый тип столбца в Plugin.php:

public function registerListColumnTypes() {
  return [
    'is_front' => [$this, 'evalIsFrontListColumn'],
  ];
}

Метод registerListColumnTypes() регистрирует новые типы столбцов и должен возвращать массив с их описанием. В данном случае для нового типа is_front мы возвращаем массив, в котором указано что значение столбца вычисляется методом evalIsFrontListColumn, который мы реализуем здесь же, в Plugin.php. Также вместо массива можно передать инлайн-функцию.

В любом случае, функция-обработчик принимает 3 аргумента и выглядит вот так:

public function evalIsFrontListColumn($value, $column, $record) {
  return ($value == $record->id) ? 'Yes' : '';
}

Здесь $value — это значение поля модели для данной строки списка, $column — настройки столбца, а $record — объект модели, для которой вычисляется значение.

Чтобы использовать этот столбец, добавим его в columns.yaml модели вот так:

front:
    label: Front
    relation: album
    select: front_id
    type: is_front

Здесь мы говорим, что добавляем столбец front, который в качестве значения должен взять поле front_id из отношения album (то есть из модели Album, с которой фотокарточка связана через belongsTo). Именно значение front_id и попадет в $value обработчика столбца. То есть в коде мы сравниваем front_id и id данной модели фотографии, и если они равны — значит эта фотография и есть обложка альбома.

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

public function registerListColumnTypes() {
  return [
    'is_front' => [$this, 'evalIsFrontListColumn'],
    'image' => [$this, 'evalImageListColumn'],
  ];
}

И вот его обработчик:

function evalImageListColumn($value, $column, $record) {
    if ($record->has('image')) {
      $thumb = $record->image->getThumb(
        isset($column->config['width']) ? $column->config['width'] : 200,
        isset($column->config['height']) ? $column->config['height'] : 200,
        ['mode' => 'auto']
      );
    } else {
      // in case the file attachment was manually deleted for some reason
      $thumb = '';
    }
    return "<img src=\"$thumb\" />";
  }

Тут все просто: поскольку $record — это готовая модель фотографии, мы берем картинку, генерируем thumbnail и возвращаем тег <IMG>. Нам даже не нужны данные из $value. Стоит обратить внимание на использование объекта $column, в котором содержатся все настройки столбца. В частности, в $column->config попадут все поля, которые мы захотим добавить в описание столбца в yaml-файле (мы добавили настройки для ширины и высоты уменьшенной картинки):

id:
    label: Photo
    type: image
    width: 100
    height: 100

Обратите внимание, что мы создали столбец с именем id. Тут есть такой нюанс: все столбцы в списках моделей должны быть реальными полями либо в отображаемой модели, либо в одной из связанных с ней (как в предыдущем столбце is_front). В данном случае, нам не нужно в обработчике ничего делать со значением столбца, так как картинку мы получаем из самой модели. Поэтому можно просто указать id модели.

И вот что получится в результате:

Так уже удобнее. Все описанное здесь можно увидеть живьём в плагине PhotoAlbums.

Комментарии