/
v.bolshakov
/
AIEcosystem-Testing
Обзор
Документация
Войти
/
v.bolshakov
/
AIEcosystem-Testing
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
dev
common/traits/Select2Trait.php
277 строк
9 KB
Developer
Initial commit
03 авг 2026, 17:43
03 авг 2026, 17:43
7433917
Код
Авторство
О чём код?
<?php namespace common\traits; use common\interfaces\TitleInterface; use common\interfaces\TitleOrderInterface; use common\models\base\BaseModel; use Yii; use yii\data\Pagination; use yii\db\Query; use yii\helpers\ArrayHelper; use yii\web\Response; /** * Trait для выбора данных для динамических Select * * @author Dmitry E. Semenov <sde.tomsk@gmail.com> * @copyright Self (c) 2020 */ trait Select2Trait { /** * ActiveRecord - Модель с которой работаем */ protected $model = null; /** * ActiveQuery - который используется для вывода в списке */ protected $query = null; /** * Название поля для индекса * @var string */ public $pk = 'id'; /** * Название поля для заголовка * @var string */ public $title = 'text'; /** * Имена тиульных полей значения которых выбираются при поиске * Если не заданы - будет использоваться результат выполнения $this->model->getTitleFields() * @var array */ public $titleFields = []; /** * Имена полей по которым осуществляется фильтрация данных * Если не заданы - будет использоваться результат выполнения $this->model->getSearchFields() * @var array */ public $searchFields = []; /** * Произвольные параметры сортировки * @var null|mixed */ public $orderByCondition; /** * Использование сортировки * @var bool */ public $useOrderBy = true; /** * Параметр фильтрации данных - TRUE только к начала, FALSE - любое вхождение * @var bool */ public $filter_from_begin = true; /** * Разбивать поиск по словам и столбцам или нет * @var bool */ public $split_filter = true; /** * Признак, означаем о том что искать все слома разом или каждое слово * @var bool */ public $strong_filter = false; /** * Функция обратного вызова для форматирования ответа * @var null */ public $format_callback = null; /** * Группировать данные в результате (необходимо реализовать группировку в format_callback) * @var bool */ public $format_callback_grouping = false; /** * Использовать алиас в запросе * @var null */ public $with_alias = true; /** * Скрывать название * @var bool */ public $hide = false; /** * Использовать поведения для подзапросов * @var bool */ public $useBehaviors = true; /** * @inheritdoc */ public function afterAction($action, $result) { $callback = Yii::$app->request->get('callback'); if ($callback) { Yii::$app->response->format = Response::FORMAT_JSONP; } else { Yii::$app->response->format = Response::FORMAT_JSON; } if ($this->query instanceof Query) { // количество элементов на странице if ($per_page = (int)Yii::$app->request->get('page_limit') AND $per_page > 0) { $pageSize = $per_page; } else { $pageSize = null; } // выбираем только активные колонки if ($this->model instanceof TitleInterface) { $selectFields = $this->titleFields ?: $this->model->getTitleFields(); if ($this->with_alias) { $selectFields = $this->attachAlias($selectFields); } $selectFields = ArrayHelper::merge($selectFields, $this->attachAlias($this->model->primaryKey())); $this->query->select(array_unique($selectFields)); } if ($this->useOrderBy) { if ($this->orderByCondition) { // сортировка описанная через контроллер $this->query->orderBy($this->orderByCondition); } elseif ($this->query instanceof TitleOrderInterface) { // сортирофка как описано в модели запроса $this->query->getOrderBy($this->model); } else { // простая сортировка $this->query->first(); } } if ($term = Yii::$app->request->get('q')) { // фильтрация данных $searchFields = $this->searchFields ?: $this->model->getSearchFields(); $this->query->filterData($searchFields, $term, [ 'from_begin' => $this->filter_from_begin, 'with_alias' => $this->with_alias, 'split_search' => $this->split_filter, 'strong_filter' => $this->strong_filter ]); } $countQuery = clone $this->query; $pagination = new Pagination(['totalCount' => $countQuery->count(), 'pageSize' => $pageSize]); $models = $this->query ->offset($pagination->offset) ->limit($pagination->limit); // выбираем данные $items = $models->all(); // формируем результат $result = $this->buildResult($items); $total_items = $pagination->totalCount; } else { // формируем результат $result = $this->buildResult($this->query); $total_items = count($result); } return parent::afterAction( $action, [ 'result' => $result, 'total' => (int)$total_items, 'source' => YII_DEBUG ? (isset($models) ? $models->createCommand()->rawSql : null) : null, ] ); } /** * Формирование результата * @return array */ protected function buildResult($items) { $result = []; $id = $this->pk; $title = $this->title; if ($this->format_callback) { if ($this->format_callback_grouping) { // произвольное форматирование вывода $result = call_user_func_array($this->format_callback, [$id, $title, $items]); } else { // форматирование вывода по строкам foreach ($items as $key => $item) { $result[] = call_user_func_array($this->format_callback, [$id, $title, $item, $key]); } } } else { if ($this->model instanceof TitleInterface) { /** @var BaseModel $item */ foreach ($items as $item) { $the_title = Yii::t('app', $item->getTitle()); if ($item->hasMethod('getHtmlTitle') and $html = $item->getHtmlTitle()) { $result[] = [ $id => $item->getId(), $title => $the_title, 'html' => $html ]; } else { $result[] = [ $id => $item->getId(), $title => $the_title ]; } } } else { /** @var BaseModel $item */ foreach ((array)$items as $item) { $result[] = [ $id => $item->getId(), $title => (string)$item ]; } } } return $result; } /** * Добавить алиас модели ко всем элементам массива * @param array $fieldsArray - массив полей для формирования запроса к БД * @return array */ protected function attachAlias(array $fieldsArray) { try { $alias = $this->model->getAlias(); } catch (\Exception $e) { $alias = false; } if ($alias) { array_walk($fieldsArray, function (&$elem) use ($alias) { $elem = "{$alias}.{$elem}"; }); } return $fieldsArray; } }