PHPackages                             dg482/red - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Admin Panels](/categories/admin)
4. /
5. dg482/red

ActiveLibrary[Admin Panels](/categories/admin)

dg482/red
=========

Automatic assembly and configuration of the user interface for administering resources

0263PHP

Since May 30Pushed 4y ago1 watchersCompare

[ Source](https://github.com/dg482/red)[ Packagist](https://packagist.org/packages/dg482/red)[ RSS](/packages/dg482-red/feed)WikiDiscussions main Synced 6d ago

READMEChangelogDependenciesVersions (2)Used By (0)

Набор методов для сборки интерфейса администрирования
=====================================================

[](#набор-методов-для-сборки-интерфейса-администрирования)

[![Build Status](https://camo.githubusercontent.com/42983bf82667117bf3cce431a83bc833cf4ab421d3fbcb8738cd64fa98cb3672/68747470733a2f2f7472617669732d63692e636f6d2f64673438322f7265642e7376673f746f6b656e3d5a5336416557454757716a3265374e6461596947266272616e63683d6d61696e)](https://travis-ci.com/dg482/red)[![codecov](https://camo.githubusercontent.com/ca74d11131f3a03e06287bd9785d5b53bfe71877525bd114fdc1832f16368912/68747470733a2f2f636f6465636f762e696f2f67682f64673438322f7265642f6272616e63682f6465762f67726170682f62616467652e7376673f746f6b656e3d51493334443836454f58)](https://codecov.io/gh/dg482/red)

Данный пакет предназначен для определения Ресурсов, построения Таблиц, Форм и Меню навигации.

Пакет **не является** самостоятельным решением для сборки раздела администрирования. Предполагается его использование в составе интеграций к фреимворкам [Laravel](https://github.com/fast-dog/adm) и Yii.

Определение используемых сущностей
----------------------------------

[](#определение-используемых-сущностей)

### Ресурсы

[](#ресурсы)

Ресурсы предназначены для выполнения базовых операций **CRUD** с заданной моделью. Во время инициализации ресурса определяется адаптер БД, реализующий `\Dg482\Red\Adapters\Interfaces\AdapterInterfaces`, с помощью которого производится получение списка полей таблицы модели и инициализация полей ресурса.

Через адаптер вызываются команды **C**reate, **R**ead, **U**pdate, **D**elete. Расширение командного интерфейса предусмотрено за счет выполнения действий, каждое действие может определять собственную команду адаптера.

###### Схема выполнения запроса к БД через команду адаптера

[](#схема-выполнения-запроса-к-бд-через-команду-адаптера)

[![](/assets/ResourceDiagram.png)](/assets/ResourceDiagram.png)

Ресурс должен содержать определение модели, правила проверки ввода данных, название полей с учетом локализации, параметры, отвечающие за визуальное оформление пунктов меню.

В методе `Resource::initResource()` определяются основные параметры:

- `Resource::setTitle()` - заголовок в пункте меню, таблице элементов ресурса
- `Resource::setIcon()` - иконка в пункте меню
- `Resource::setLabels()` - подписи к полям в таблице и форме, если подписи не заданы будут использованы **комментарии** к колонкам БД
- `Resource::setHiddenFields()` - определение скрытых полей (**Внимание!** поля будут пропущены при сборке таблицы или формы, что бы присвоить полю тип `hidden` необходимо переопределить поле в форме ресурса)
- `Resource::setAssets()` - метод определяет хранилище файлов, реализацию интерфейса `ResourceAssetsInterface` для работы с медиа материалами (изображениями, файлами документации и тд) прикрепляемыми к модели ресурса.

Метод `Resource::getFormModel()` должен вернуть форму модели, расширяющую базовую реализацию `Dg482\Red\Builders\Form\BaseForms`

###### Ресурс WebinarResource

[](#ресурс-webinarresource)

```
namespace App\Resources\Webinar;

use App\Models\Webinar;
use App\Resources\Webinar\Forms\WebinarItemForm;
use Dg482\Red\Builders\Form\BaseForms;
use Dg482\Red\Resource\Resource;

/**
 * Class WebinarResource
 * @package App\Resources\Webinars
 */
class WebinarResource extends Resource
{
    /**
     * Определение модели
     * @var string
     */
    protected string $resourceModel = Webinar::class;

    /**
     * Метод инициализации параметров ресурса
     *
     * @param  string  $context
     * @return Resource
     */
    public function initResource(string $context = ''): Resource
    {
        // определение параметров отображения
        $this->setIcon('video-camera') // иконка в пункте меню
            ->setTitle('Вебинары')// название пункта меню
            ->setLabels([// подписи полей формы, колонок в таблице
                'title' => 'Название',
                'url' => 'Ссылка на Вебинар',
            ])
            ->setHiddenFields([// скрытые поля
                'deleted_at',
            ])
            ->setContext(__CLASS__);

        // определение правил проверки ввода с учетом интеграции с фреимворком, в данном случае правила для Laravel
        $this->validators = [
            'title' => ['required', 'max:80'],
        ];

        $this->setAssets(new WebinarStorage);

        return $this;
    }

    /**
     * Метод возвращает форму ресурса в которой определены вспомогательные методы для работы с полями
     *
     * @return BaseForms
     */
    public function getFormModel(): BaseForms
    {
        if (!$this->formModel) {
            $this->setForm(new WebinarItemForm(new $this->resourceModel));
        }

        return parent::getFormModel();
    }
}
```

 **Хранилище WebinarStorage для ресурса WebinarResource (Laravel)**```
namespace App\Resources\Webinar\Assets;

use App\Models\Files\Storage;
use Dg482\Red\Interfaces\ResourceAssetsInterface;

/**
 * Class WebinarStorage
 *
 * В контексте данного примера класс WebinarStorage расширяет Storage
 * который является типовой реализацией работы с моделью БД для регистрации файлов.
 * От проекта к проекту данная реализация может отличаться поэтому
 * в качестве примера рассматриваются только методы интерфейса ResourceAssetsInterface.
 *
 * @package App\Resources\Webinar\Assets
 */
class WebinarStorage extends Storage implements ResourceAssetsInterface
{
    /**
     * Удаление файла
     *
     * @return bool
     */
    public function remove(): bool
    {
        \Illuminate\Support\Facades\Storage::disk('public')->delete($this->{self::PATH});

        return $this->delete();
    }

    /**
     * Получение модели по идентификатору привязки к файлу
     * @param  int  $id
     * @return ResourceAssetsInterface
     */
    public function get(int $id): ResourceAssetsInterface
    {
        $item = $this->where([
            Storage::OWNER_TYPE => Storage::TYPE_CATALOG,
            'id' => $id,
        ])->first();

        return $item ?? new self();
    }

    /**
     * Сохранение привязки загруженного файла
     *
     * @param  array  $parameter
     * @return bool
     */
    public function store(array $parameter): bool
    {
        $item = self::create([
            Storage::OWNER_TYPE => Storage::TYPE_CATALOG,
            Storage::OWNER_ID => $parameter[Storage::OWNER_ID],
            Storage::PATH => $parameter[Storage::PATH],
            Storage::STORAGE => Storage::STORAGE_LOCAL,
            Storage::FILE => $parameter[Storage::FILE] ?? $parameter[Storage::PATH],
        ]);

        return $item->id > 0 ?? false;
    }
}
```

 **Форма WebinarItemForm для ресурса WebinarResource (Laravel)**```
namespace App\Resources\Webinar\Forms;

use App\Models\Webinar;
use Dg482\Red\Builders\Form\BaseForms;
use Dg482\Red\Builders\Form\Fields\Field;
use Dg482\Red\Builders\Form\Fields\HiddenField;
use Dg482\Red\Builders\Form\Fields\DateField;
use Dg482\Red\Exceptions\EmptyFieldNameException;
use Illuminate\Database\Eloquent\Builder;
use Carbon\Carbon;

/**
 * Определение формы для работы с моделью Webinar, содержит методы модификации полей по умолчанию
 *
 * @package App\Resources\Webinars\Forms
 */
class WebinarItemForm extends BaseForms
{
    /**
     * Category constructor.
     * @param  Webinar  $model
     */
     public function __construct(Webinar $model)
     {
        $this->setTitle('Вебинар');// заголовок формы
        $this->setFormName('webinar/item'); // идентификатор формы
        $this->setModel($model); // определение модели в контексте формы
     }

    /**
     * Переопределение поля Дата создания
     *
     * При переопределение происходит корректировка отображения поля в форме
     * и определение замыкания вызываемого при построение запроса из таблицы ресурса определяющего
     * условие фильтрации по полю.
     *
     * @param  Field  $field
     * @return Field
     * @throws EmptyFieldNameException
     */
    public function formFieldCreatedAt(Field $field): Field
    {
        return (new DateField)
            ->setFilterFn(function (Builder &$builder, array $request) use ($field) {// замыкание для условия запроса к БД
                if (!empty($request['created_at'])) {
                    if (count($request['created_at']) === 1) {// если передано одно значение
                        $date = Carbon::createFromFormat('Y-m-d', current($request['created_at']));
                        // фильтруем в диапазоне начала и конца даты
                        $builder->whereBetween('created_at', [
                            $date->startOfDay()->format(Carbon::DEFAULT_TO_STRING_FORMAT),
                            $date->endOfDay()->format(Carbon::DEFAULT_TO_STRING_FORMAT),
                        ]);
                    } elseif (!empty($request['created_at'][0]) && !empty($request['created_at'][1])) {
                        $start = Carbon::createFromFormat('Y-m-d', $request['created_at'][0]);
                        $end = Carbon::createFromFormat('Y-m-d', $request['created_at'][1]);
                        // фильтруем в диапазоне начала и конца дат
                        $builder->whereBetween('created_at', [
                            $start->startOfDay()->format(Carbon::DEFAULT_TO_STRING_FORMAT),
                            $end->endOfDay()->format(Carbon::DEFAULT_TO_STRING_FORMAT),
                        ]);
                    }
                }
            })
            ->setFilterMultiple()// возможность выбора диапазона значений
            ->hideForm() // скрываем отображение в форме
            ->setField($field->getField()) // определение поля
            ->setName($field->getName())// определение названия
            ->setValue($field->getValue()->getValue());
    }

    /**
     * Переопределение поля url
     *
     * @param  Field  $field
     * @return Field
     */
     public function formFieldUrl(Field $field): Field
     {
        return $field->hideTable();// скрыть поле в таблице
     }

    /**
     * Переопределение типа поля id
     * @param  Field  $field
     * @return Field
     * @throws \Dg482\Red\Exceptions\EmptyFieldNameException
     */
     public function formFieldId(Field $field): Field
     {
        return (new HiddenField)
                ->setField($field->getField())
                ->setValue($field->getValue()->getValue())
                ->hideTable();
     }
}
```

Также ресурсы можно использовать как статичные генераторы произвольного интерфейса.

###  Health Score

19

—

LowBetter than 10% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity11

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity31

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1058411?v=4)[Andrey Martynov](/maintainers/dg482)[@dg482](https://github.com/dg482)

---

Top Contributors

[![dg482](https://avatars.githubusercontent.com/u/1058411?v=4)](https://github.com/dg482 "dg482 (140 commits)")

### Embed Badge

![Health badge](/badges/dg482-red/health.svg)

```
[![Health](https://phpackages.com/badges/dg482-red/health.svg)](https://phpackages.com/packages/dg482-red)
```

###  Alternatives

[jeroennoten/laravel-adminlte

Easy AdminLTE integration with Laravel

4.0k4.8M43](/packages/jeroennoten-laravel-adminlte)[dmstr/yii2-adminlte-asset

AdminLTE backend theme asset bundle for Yii 2.0 Framework

1.1k1.8M67](/packages/dmstr-yii2-adminlte-asset)[dwij/laraadmin

LaraAdmin is a Open source Laravel Admin Panel / CMS which can be used as Admin Backend, Data Management Tool or CRM boilerplate for Laravel with features like CRUD Generation, Module Manager, Media, Menus, Backups and much more

1.6k68.7k](/packages/dwij-laraadmin)[filament/spatie-laravel-media-library-plugin

Filament support for `spatie/laravel-medialibrary`.

1764.8M125](/packages/filament-spatie-laravel-media-library-plugin)[bezhansalleh/filament-exceptions

A Simple &amp; Beautiful Pluggable Exception Viewer for FilamentPHP's Admin Panel

193195.9k13](/packages/bezhansalleh-filament-exceptions)[filament/infolists

Easily add beautiful read-only infolists to any Livewire component.

1220.8M36](/packages/filament-infolists)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
