Компоненты

Поля с автоподбором (autocomplete)

В случае большого количества элементов для выбора значения поля в выпадающем списке, например подкатегорий или городов, удобно заменить select на поле с автоподбором вариантов.
Реализовать такой тип поля позволяет метод autocomplete(field_name, field_title, callback_search, callback_default, placeholder)

$form->autocomplete(
    'subcat_id',                      # атрибут `name` поля формы                
    $this->langAdmin('Подкатегория'), # заголовок поля
    function ($query) {               # callback автоподбора вариантов
        $result = [];
        if (!empty($query)) {
            $filter = [
                ':q' => ['title LIKE :q', ':q' => '%'.$query.'%'],
            ];
            $data = $this->model->catsListing($filter); # получаем подходящие данные из модели
            foreach ($data as $v) {
                $result[] = [$v['id'], $v['title']];
        }    
        return $result;
    },
    function ($id) {  # callback ранее сохраненного значения 
        $data = $this->model->catData($id);
        return ! empty($data['title']) ? $data['title'] : '';
    }, 
    $this->langAdmin('Введите название подкатегории') # placeholder
);

Третьим параметром метода autocomplete() является callback автоподбора вариантов:

  • принимает в качестве аргумента $query - строка поиска,
  • требует наличия необходимого метода модели, который и будет осуществлять поиск по таблице БД,
  • возвращать должен массив в формате [[$id_1, $title_1], [$id_2, $title_2], ...].

Следующим параметром является callback ранее сохраненного значения при редактированиии записи из списка:

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

Теги

Теги позволяют задать дополнительные характеристики в виде ключевых слов к объекту, что удобно использовать при поиске по списку. Подробнее о создании компонента Tags ($tagsComponent) вы можете узнать из статьи. Для добавленния тегов и вывода их в список в админ-контроллере создаем достаточно простой метод:

/**
 * Список тегов
 */
public function tags()
{
    # получаем объект компонента работы с тегами \bff\db\Tags
    $tagsComponent = $this->initTags(); 

    return $tagsComponent->manage();
}

Ключевым является вызов метода manage() - управляет списком, формой добавления и редактирования тегов.

Связываем объект, к примеру публикацию, с тегами. Для этого в форме добавления/редактирования публикации создаем поле выбора тегов при помощи метода компонента формы tagsComponent($tagsComponent, field_title, field_width) .

$form->tagsComponent(
    $tagsComponent,            # компонент работы с тегами
    $this->langAdmin('Теги'),  # заголовок поля
    675                        # ширина поля в px
);

Есть альтернативный вариант использования поля тегов в форме объекта(публикации) - метод компонента формы
tags(field_name, field_title, сallback_autocomplete, callback_default, is_rotate, placeholder).

$form->tags(
    'post_tags',               # атрибут `name` поля формы       
    $this->langAdmin('Теги'),  # заголовок поля
    function ($query) {        # callback автоподбора тегов
        $result = [];
        if (!empty($query)) {
            $filter = [
                ':q' => ['title LIKE :q', ':q' => '%'.$query.'%'],
            ];
            $data = $this->model->tagsListing($filter); # получаем подходящие данные из модели
            foreach ($data as $v) {
                $result[] = array($v['id'], $v['title']);
            }
        }
        return $result;
    },
    function ($ids) { # callback ранее сохраненных значений
        $data = $this->model->tagsListing(['id' => $ids]);
        foreach ($data as & $v) {
            $v['value'] = $v['id'];
        }
        return $data;
    },
    true,
    'Введите название, например (one)'
);

Удобство такого способа работы с тегами состоит в том, что есть возможность управлять автоподбором тегов в сallback_autocomplete, таким образом теги могут храниться в таблице БД любого вида и форма создания и список тегов может быть задан любым удобным способом. Аналогично полю автозаполнения сallback_autocomplete для поля тегов

  • принимает в качестве аргумента $query - строку поиска,
  • требует наличия необходимого метода модели, который и будет осуществлять поиск по таблице тегов в БД,
  • возвращать должен массив в формате [[$id_tag_1, $title_tag_1], [$id_tag_2, $title_tag_2], ...].

Следующим параметром является callback_default ранее сохраненных тегов для связанной сущности публикации, актуально при редактировании:

  • принимает в качестве аргумента $ids - ids ранее сохраненных тегов в формате [$tag_id_1, $tag_id_2, $tag_id_3, ...],
  • требует наличия необходимого метода модели, который и будет возвращать данные по искомым тегам,
  • обязательно наличие данных по тегам в формате [[ 'title' => $title, 'value' => $id ], ...]

При таком подходе храним теги объекта в виде массива в поле 'post_tags' основной таблицы объектов(публикаций) типа TEXT, при этом название поля может быть любым, главное учесть соответствие с ключем поля в форме.

Конструктор контента Publicator

В качестве конструктора контента рекомендуем использовать Publicator, позволяющий форматировать текст, загружать изображения, добавлять видео, делать цитаты и заголовки.
Подробнее о создании компонента Publicator ($publicatorComponent) и задании его настроек $publicatorSettings вы можете узнать из статьи.

Рассмотрим публикатор как поле формы в админ-панели. Объявление такого конструктора выполняется довольно просто, использовав метод
publicator(field_name, field_search_name, is_lang, controls, settings)
Параметрами являются название поля в БД, в котором будут храниться непосредственно данные из конструктора в виде строки json, а также требуется наличие в таблице БД поля для осуществления поиска по текстовому содержимому контента, данные поля должны быть типа TEXT.

$form
    ->publicator(
        'content',       # данные(поле) конструктора
        'content_search' # данные(поле) для текстового поиска 
    );

Приведем пример как можно задавать разрешенные типы блоков конструктора в форме, оставив возможность добавлять только текст и изображения:

$form->publicator(
    'content',                                  # данные(поле) конструктора
    'content_search',                           # данные(поле) для текстового поиска 
    true,                                       # использовать мультиязычность
    [                                           # разрешенные блоки
        \bff\db\Publicator::blockTypeText,
        \bff\db\Publicator::blockTypePhoto,
    ], 
    $publicatorSettings                         # настройки компонента 
);

Динамические свойства (Dynprops)

Динамические свойства позволяют комплексно добавлять свойства к объекту и удобно использовать их в разрезе фильтрации по списку. Подробнее о данном компоненте вы можете прочитать в данной статье.

Выбор динамических свойств

Выбор динамических свойств осущеcтвляется в форме создания/редактирования объекта в связке с обязательным выбором категории объекта. Так при создании объекта выбираем к какой категории он будет относиться, далее задаем значения свойств выбранной категории. В форме связываем выбор категории с добавлением поля типа "Динамические свойства" при помощи метода dynprops(object_dp, field_owner), параметрами являются объект компонента Dynprops $dynpropsComponent и наименование поля выбранной категории (cat_id):

$form->select('cat_id', $this->langAdmin('Категория'), false, function($field) use($form) {
    # получаем список категорий и формируем список в виде HTML::options
    $data = $this->model->catsListing();
    $result = [];
    if ( ! $form->recordID()) {
        # для нового объекта добавляем пункт "Выбрать"
        $result[] = '<option value="0">'.$this->langAdmin('Выбрать').'</option>';
    }
    $val = $field->value();
    foreach ($data as $v) {
        # помечаем выбранную категорию (при редактировании)
        $result[] = '<option value="'.$v['id'].'"'.($val == $v['id'] ? ' selected="selected"' : '').'>'.$v['title'].'</option>';
    }
    return join('', $result);
);

# Указываем на необходимость отобразить дин.свойства категории при выборе из списка, передаем объект компонента и название поля выбора категории
$form->dynprops($dynpropsComponent, 'cat_id');

Сохраняются выбранные динамические свойства вместе с остальными полями публикации в обработчике сохранения формы:

$form->onSave(function($id, $data) {
    return $this->model->postSave($id, $data);
});

Добавление динамических свойств в список категорий

В списке категорий, возможность добавлять динамические свойства доступна в колонке Действие (рядом с редактированием и удалением). Осуществляется при помощи метода onDynprops(dynpropsObject), параметром является ранее созданный компонент динамических свойств:

$list->onDynprops($dynpropsComponent);