Таблицы предназначены для вывода списка документов раздела.
На данный момент поддерживаются следующие типы вывода данных:
AdminDisplay::table()
- обычная таблица (SleepingOwl\Admin\Display\DisplayTable
)AdminDisplay::datatables()
- таблица с выводом данных используя плагин https://datatables.net/ (SleepingOwl\Admin\Display\DisplayDatatables
)AdminDisplay::datatablesAsync()
(SleepingOwl\Admin\Display\DisplayDatatablesAsync
)AdminDisplay::tree()
- вывод данных в виде дерева (SleepingOwl\Admin\Display\DisplayTree
)
Пример использования:
$model->onDisplay(function () {
$display = AdminDisplay::table();
...
return $display;
});
SleepingOwl\Admin\Display\Extension\Columns
Типы столбцов и их описание можно посмотреть здесь
$display->setColumns([
...
AdminColumn::link('title')->setLabel('Title'),
AdminColumn::datetime('created_at')->setLabel('Created')->setFormat('d.m.Y'),
...
]);
// or
$display->getColumns()->push(
AdminColumn::text('title')
);
SleepingOwl\Admin\Display\Extension\ColumnFilters
$display->setColumnFilters([
...
AdminColumnFilter::text()->setPlaceholder('Full Name'),
...
]);
// or
$display->getColumnFilters()->push(
AdminColumnFilter::text()->setPlaceholder('Full Name')
);
Позволяет оптимизировать запросы к БД в случае использования связей с другими моделями. Подробности
$display->with('country', 'companies');
SleepingOwl\Admin\Display\Extension\Apply
Вы можете изменять запрос по желанию
$display->setApply(function ($query) {
$query->orderBy('title', 'asc');
});
// or
$display->setApply([
...
function ($query) {
$query->orderBy('title', 'asc');
},
...
]);
// or
$display->getApply()->push(function ($query) {
$query->orderBy('title', 'asc');
});
SleepingOwl\Admin\Display\Extension\Scopes
Вы можете применить Eloquent scopes к выводимым данным:
$display->setScopes('last');
//or
$display->setScopes(['last', 'trashed']);
// or
$display->getScopes()->push('last');
SleepingOwl\Admin\Display\Extension\Actions
Использует тип колонки таблицы Action
$table = AdminDisplay::table()
->setActions([
AdminColumn::action('export', 'Export')->setIcon('fa fa-share')->setAction(route('news.export')),
])
->setColumns([
AdminColumn::checkbox(),
...
]);
// Изменить разсположение положения кнопок на странице
$table->getActions()
->setPlacement('panel.buttons')
->setHtmlAttribute('class', 'pull-right');
В классах таблиц используется трейт:
- HtmlAttributes, с помощью которого для них можно настраивать HTML атрибуты.
- Assets, с помощью которого для них можно подключать ассеты.
Добавление нового расширения к виду
SleepingOwl\Admin\Display\Display::extend(string $name, \SleepingOwl\Admin\Contracts\Display\DisplayExtensionInterface $extension): return $extension
Получение списка всех расширений
SleepingOwl\Admin\Display\Display::getExtensions() return \Illuminate\Support\Collection|array<mixed,\SleepingOwl\Admin\Contracts\Display\DisplayExtensionInterface>
SleepingOwl\Admin\Display\Display::with(array|array<mixed,string> $relations): return self
Указание заголовка для таблиц
SleepingOwl\Admin\Display\Display::setTitle(string $title): return self
Указание заголовка кнопки добавления записи
SleepingOwl\Admin\Display\DisplayTable::setNewEntryButtonText(string $title): return self
Изменения шаблона вывода данных
SleepingOwl\Admin\Display\Display::setView(string|\Illuminate\View\View $view): return self
$table->setView(view('display.custom.table.view'));
// Будет произведен поиск по пути sleeping_owl::default.display.custom.table.view
$table->setView('display.custom.table.view');
Получение объекта расширения
SleepingOwl\Admin\Display\Display::getActions(): return SleepingOwl\Admin\Display\Extension\Actions
$actions = $table->getActions();
$actions->setHtmlAttribite('class', 'custm-class');
$actions->push(AdminColumn::action());
// Установка места вывода кнопок
$actions->setPlacement(...);
SleepingOwl\Admin\Display\Display::setActions(array|...SleepingOwl\Admin\Contracts\ActionInterface): return self
Получение объекта расширения
SleepingOwl\Admin\Display\Display::getApply(): return SleepingOwl\Admin\Display\Extension\Apply
SleepingOwl\Admin\Display\Display::setApply(array|...\Closure): return self
Получение объекта расширения
SleepingOwl\Admin\Display\Display::getScopes(): return SleepingOwl\Admin\Display\Extension\Scopes
SleepingOwl\Admin\Display\Display::setScopes(array|...(string|array)): return self
Получение объекта расширения
SleepingOwl\Admin\Display\Display::getFilters(): return SleepingOwl\Admin\Display\Extension\Filters
SleepingOwl\Admin\Display\Display::setFilters(array|...SleepingOwl\Admin\Contracts\FilterInterface): return self
Переопределение класса репозитория. (Класс должен реализовывать интерфейс SleepingOwl\Admin\Contracts\RepositoryInterface
)
SleepingOwl\Admin\Display\Display::setRepositoryClass(string $repository): return self
SleepingOwl\Admin\Display\DisplayTable
Передача в URL кнопки создания новой записи дополнительных параметров
SleepingOwl\Admin\Display\DisplayTable::setParameters(array $parameters): return self
Передача в URL кнопки создания новой записи дополнительного параметра
SleepingOwl\Admin\Display\DisplayTable::setParameter(string $key, mixed $value): return self
Вывод данных с постраничной навигацией
SleepingOwl\Admin\Display\DisplayTable::paginate(integer $perPage, string $pageName): return self
$table->paginate(20, 'custom_page');
Отключение постраничной навигации
SleepingOwl\Admin\Display\DisplayTable::disablePagination(): return self
Проверка на использование постраничной навигации
SleepingOwl\Admin\Display\DisplayTable::usePagination(): return boolean
Получение объекта расширения
SleepingOwl\Admin\Display\DisplayTable::getColumns(): return SleepingOwl\Admin\Display\Extension\Columns
$columns = $table->getColumns();
$columns->push(AdminColumn::text());
$columns->setControlColumn(new \App\Display\Columns\CustomControlColumn());
$columns->setView(...);
Указание списка столбцов для выводимой таблицы. В качестве аргумента можно передать как массив колонок так и объект SleepingOwl\Admin\Contracts\ColumnInterface
SleepingOwl\Admin\Display\DisplayTable::setColumns(array|...SleepingOwl\Admin\Contracts\ColumnInterface): return self
$table->setColumns(AdminColumn::text(...), AdminColumn::datetime(..));
$table->setColumns([
AdminColumn::text(),
AdminColumn::datetime(..)
]);
Получение объекта расширения
SleepingOwl\Admin\Display\DisplayTable::getColumnFilters(): return SleepingOwl\Admin\Display\Extension\ColumnFilters
$filters = $table->geColumnFilters();
$filters->push(AdminColumnFilter::text());
$filters->setPlacement(...);
SleepingOwl\Admin\Display\DisplayTable::setColumnFilters(array|...SleepingOwl\Admin\Contracts\ColumnFilterInterface): return self
Вывод строки в таблице для агрегации результатов:
SleepingOwl\Admin\Display\DisplayTable::setColumns(array|...SleepingOwl\Admin\Contracts\ColumnInterface): return self
$table->setColumnsTotal([
'Total: ',
'<number_total>',
...
],
$table->getColumns()->all()->count()
);
Вторым параметром добавляем количество столбцов в таблице.
Для того, чтобы применить фильтр для текущей query можно сделать следующий запрос:
$totalQuery = <Model>::query();
$table->getFilters()->initialize();
$table->getFilters()->modifyQuery($totalQuery);
Из $totalQuery уже можно скомпоновать агрегированные данные
Получение объекта расширения с выводом агрегированной строки внизу таблицы
$display->getColumnsTotal()->setPlacement('table.footer')
SleepingOwl\Admin\Display\DisplayDatatables
Указание параметров для таблицы
SleepingOwl\Admin\Display\DisplayDatatables::setDatatableAttributes(array $datatableAttributes): return self
Указание правила сортировки данных. https://datatables.net/examples/basic_init/table_sorting.html
SleepingOwl\Admin\Display\DisplayDatatables::setOrder(array $order): return self
$display->setOrder([[1, 'asc']]);
SleepingOwl\Admin\Display\DisplayDatatablesAsync
SleepingOwl\Admin\Display\DisplayDatatablesAsync::setName(string $name): return self
SleepingOwl\Admin\Display\DisplayDatatablesAsync::setDistinct(boolean $distinct): return self
SleepingOwl\Admin\Display\DisplayTree
Используется для вывода данных в виде дерева с поддержкой сортировки (drag & drop). Данный вид поддерживает работу с https://github.com/etrepat/baum, https://github.com/lazychaser/laravel-nestedset, а также самый простой вариант, когда дерево строится на основе parent_id
(Также в таблице должно быть поле order
для сортировки)
Использование других библиотек работы с деревом: При использовании etrepat/baum возможны проблемы с наследованием секций связанными с моделью Дерева.
Для решения рассмотрим пример использования другой ветки https://github.com/gazsp/baum. За работу с каждым типом дерева отвечает отдельный класс https://github.com/LaravelRUS/SleepingOwlAdmin/tree/development/src/Display/Tree
Для поддержки своего типа дерева необходимо добавить свой класс, для удобства его можно наследовать от SleepingOwl\Admin\Display\Tree\NestedsetType и реализовать те методы, которые он попросит.
В случае использования gazsp/baum метод получения всего дерева с сортировкой по левому индексу будет отличаться от etrepat/baum и наш класс будет выглядеть так:
<?php
namespace Admin\Tree;
use Illuminate\Database\Eloquent\Model;
use SleepingOwl\Admin\Display\Tree\BaumNodeType;
/**
* @see https://github.com/etrepat/baum
*/
class CustomBaumNodeType extends BaumNodeType
{
/**
* Get tree structure.
*
* @param \Illuminate\Database\Eloquent\Collection $collection
*
* @return mixed
*/
public function getTree(\Illuminate\Database\Eloquent\Collection $collection)
{
return $collection->toSortedHierarchy();
}
}
А дальше при инициализации DisplayTree мы указываем этот класс
AdminDisplay::tree(\Admin\Tree\CustomBaumNodeType::class)->...
Сортировка:
Данный класс регистрирует роут admin.display.tree.reorder
, который отвечает за сортировку данных. При необходимости вы можете переопределить данный роут в app/Admin/routes.php
.
Route::post('{adminModel}/reorder', ['as' => 'admin.display.tree.reorder', function (ModelConfigurationInterface $model) {
if ($model->getClass() == 'App\Post') {
// ...
} else {
$model->fireDisplay()->getRepository()->reorder(
Request::input('data')
);
}
}]);
При добавлении дерева в таб может некорректно работать сортировка
Указание заголовка для документов
SleepingOwl\Admin\Display\DisplayTree::setValue(string $value): return self
Указание ключа поля
SleepingOwl\Admin\Display\DisplayTree::setParentField(string $parentField): return self
Указание ключа поля
SleepingOwl\Admin\Display\DisplayTree::setOrderField(string $orderField): return self
SleepingOwl\Admin\Display\DisplayTree::setRootParentId(null|string $rootParentId): return self
Передача в URL кнопки создания новой записи дополнительных параметров
SleepingOwl\Admin\Display\DisplayTree::setParameters(array $parameters): return self
Передача в URL кнопки создания новой записи дополнительного параметра
SleepingOwl\Admin\Display\DisplayTree::setParameter(string $key, mixed $value): return self
SleepingOwl\Admin\Display\DisplayTree::setReorderable(boolean $reorderable): return self
Получение объекта расширения (На данный момент не используется)
SleepingOwl\Admin\Display\DisplayTree::getTree(): return SleepingOwl\Admin\Display\Extension\Tree
Переопределение класса репозитория. (Класс должен реализовывать интерфейс SleepingOwl\Admin\Contracts\TreeRepositoryInterface
)
SleepingOwl\Admin\Display\DisplayTree::setRepositoryClass(string $repository): return self
Класс SleepingOwl\Admin\Display\Display
от которого наследуются все классы реализующие вывод данных позволяет расширять свое поведение. Расширения могут как влиять на вывод данных, модифицируя запрос перед получением списка записей из БД либо вывод HTML кода в шаблон.
Сейчас класс для вывода таблицы работает полностью за счет расширений, а именно, вызывая метод setColumns
или getColumns
, setColumnFilters
или getColumnFilters
вы обращаетесь к классам расширений.
Использовать расширения можно как при создании нового типа Display
, так и с существующими типами.
Для работы расширений необходимо свой класс наследовать от SleepingOwl\Admin\Display\Display
. Класс расширения должен реализовывать интерфейс SleepingOwl\Admin\Contracts\Display\DisplayExtensionInterface
Пример нового класса:
// Новый класс
namespace App\Display;
class CustomDisplay extends \SleepingOwl\Admin\Display\Display
{
/**
* Display constructor.
*/
public function __construct()
{
parent::__construct();
$this->extend('custom_extension', new \App\Display\Extension\CustomExtension());
}
}
Пример добавления расширения для существующего типа:
$display = AdminDisplay::table();
$display->extend('custom_extension', new \App\Display\Extension\CustomExtension());
После инициализации расширения работа с ним осуществляется следующим образом:
// Получение объекта
$table->getCustomExtension()->...
// В случае если в классе расширения определен метод set(), возможна передача в него данных
$table->setCustomExtension(...)
Расширения делятся на два типа:
- Модификация запроса
- Вывод HTML кода в шаблон Display
- При реализации интерфейса
Illuminate\Contracts\Support\Renderable
вывод будет выполнен в общем стеке расширений - При реализации интерфейса
SleepingOwl\Admin\Contracts\Display\Placable
вывод будет выполнен в месте указанном в методеgetPlacement
- При реализации интерфейса
По умолчанию любое расширение может модифицировать запрос, который выполняет класс Display перед выводом данных. В момент выполнения запроса происходит вызов метода modifyQuery
во всех расширениях и передача в него объекта \Illuminate\Database\Eloquent\Builder
.
Пример
public function modifyQuery(\Illuminate\Database\Eloquent\Builder $query)
{
$query->orderBy('column', 'desc');
}
Если расширение реализует интерфейс Illuminate\Contracts\Support\Renderable
, то будет произведен вывод расширения в общем стеке расширений, т.е. для всех расширений будет последовательно вызван метод render
https://github.com/LaravelRUS/SleepingOwlAdmin/blob/development/resources/views/default/display/table.blade.php#L28
Перед выводом происходит сортировка расширений по значению, взятому из метода getOrder
Если расширение реализует интерфейс SleepingOwl\Admin\Contracts\Display\Placable
, то HTML код расширения будет помещен в определенном месте, указанном в методе getPlacement
Места, где можно разместить код реализованы через @yield
https://github.com/LaravelRUS/SleepingOwlAdmin/blob/development/resources/views/default/display/table.blade.php
При необходимости таблицу можно использовать в форме для вывода связанных записей.
Допустим у нас есть галерея (раздел Gallery
) и фотографии в ней (Photo
). У каждой фотографии есть category_id
- идентификатор категории. После создания категории, в форме редактирования нужна возможность добавлять фотографии в эту категорию.
// Create And Edit
$model->onCreateAndEdit(function($id = null) {
$form = AdminForm::panel()->addHeader(
AdminFormElement::text('title', 'Название галереи')->required(),
);
if (!is_null($id)) { // Если галерея создана и у нее есть ID
$photos = AdminDisplay::table()
->setModelClass(Photo::class) // Обязательно необходимо указать класс модели в которой хранятся фотографии
->setApply(function($query) use($id) {
$query->where('category_id', $id); // Фильтруем список фотографий по ID галереи
})
->setParameter('category_id', $id) // При нажатии на кнопку "добавить" - подставлять идентификатор галереи
->setColumns(
AdminColumn::link('name', 'Назавние фотографии'),
AdminColumn::image('thumb', 'Фотгорафия')
->setHtmlAttribute('class', 'text-center')
->setWidth('100px')
)
$form->addBody($photos);
}
});