Перейти до вмісту
en English

Версія v1.6.5 Попередні версії: документація на GitHub

Поля

На цій сторінці

Поля повертає метод Entity::fields(Request $request): array. Усі поля створюються через Field::make(...) і налаштовуються ланцюжком методів.

Text::make('Назва', 'name')->sortable()->rules('required', 'max:255'),

Перший аргумент назва поля в інтерфейсі, другий атрибут моделі. Якщо атрибут не вказано, він виводиться з назви: Str::snake(Str::lower($name)) ('Created At' дає created_at). Назва з не-ASCII символами без явного атрибута кидає InvalidArgumentException, тому для українських підписів завжди передавайте атрибут другим аргументом.

Типи полів

Усі класи з простору імен Maxcxam\Larsadmin\Fields.

Поле Компонент Особливості
ID id-field ID::make() дає назву ID і атрибут id; показується лише на index і detail
Text text-field inputType('email') задає HTML-тип поля (email, url, tel)
Textarea textarea-field приховане на index; rows(int), за замовчуванням 5
Number number-field min(), max(), step()
Boolean boolean-field trueValue(), falseValue() задають, що зберігається; за замовчуванням true/false
Date date-field форма віддає Y-m-d; displayFormat('d.m.Y') для index і detail
DateTime datetime-field форма віддає Y-m-d\TH:i:s; успадковує displayFormat()
Password password-field лише на формах; хеш ніколи не надсилається в браузер; змінюється, тільки якщо введено новий (Hash::make)
Select select-field options(array|Closure), мапа значення => підпис
File file-field завантаження файлу на диск; multiple(), приватні файли з підписаними посиланнями, див. Файли й зображення
Image image-field як File, лише растрові зображення, з мініатюрами; див. Файли й зображення
BelongsTo, HasMany, BelongsToMany див. Зв'язки

Формат відображення дат за замовчуванням береться з перекладу larsadmin::ui.formats.date та larsadmin::ui.formats.datetime (для en: Y-m-d і Y-m-d H:i:s), тобто залежить від мови панелі.

Приклад: усі типи разом

Приклад (app/Larsadmin/Post.php):

public function fields(Request $request): array
{
    return [
        ID::make()->sortable(),
        Text::make('Заголовок', 'title')->sortable()->rules('required', 'max:255'),
        Textarea::make('Текст', 'body')->nullable(),
        Select::make('Статус', 'status')->sortable()->rules('required')->options([
            'draft' => 'Чернетка',
            'review' => 'На перевірці',
            'live' => 'Опубліковано',
        ]),
        Boolean::make('Опубліковано', 'published'),
        Number::make('Перегляди', 'views')->min(0)->default(0)->sortable(),
        Date::make('Перевірити до', 'review_due')->nullable(),
        DateTime::make('Дата публікації', 'published_at')->nullable()->sortable(),
    ];
}

Select розуміє enum: для BackedEnum береться value, для UnitEnum name. Опції можна віддати замиканням, яке виконується один раз на екземпляр поля:

Select::make('Статус', 'status')->options(fn () => Status::pluck('label', 'code')->all());

Спільні методи

Метод Дія
sortable(bool $sortable = true) дозволяє сортування за колонкою на index (потрібне й для Entity::$sort)
nullable(bool $nullable = true) порожній рядок зберігається як null; додає правило nullable
readonly(bool|Closure $readonly = true) поле не заповнюється й не валідується (див. «Видимість»)
help(string) підказка під полем
placeholder(string) плейсхолдер
default(mixed|Closure) значення на формі створення; замикання отримує Request
withMeta(array) додаткові дані в серіалізованому полі
resolveUsing(callable) змінює значення, яке бачить форма: fn ($raw, $record, $attribute)
displayUsing(callable) змінює відображення на index/detail: fn ($raw, $record, $attribute)
fillUsing(callable) повністю замінює запис значення: fn ($request, $record, $attribute)
sensitive(bool $sensitive = true) журнал аудиту записує лише факт зміни поля, без значень; на форми й перегляд не впливає. Password маскується завжди; позначайте й поля з accessor-ом, що розшифровує значення, і JSON-колонки із секретами (Журнал аудиту)

fillUsing може повернути замикання fn (Model $record). Воно виконається після збереження запису в тій самій транзакції (зручно для залежних даних).

Text::make('Slug', 'slug')->fillUsing(function ($request, $record, $attribute) {
    $record->slug = Str::slug($request->input('title'));
});

Якщо задано fillUsing, неявні правила типу (див. нижче) не додаються.

Видимість

За замовчуванням поле видно на index, detail, створенні та редагуванні.

Метод Ефект
hideFromIndex() ховає зі списку
hideFromDetail() ховає з перегляду
hideWhenCreating() ховає з форми створення
hideWhenUpdating() ховає з форми редагування
showOnIndex(), showOnDetail(), showWhenCreating(), showWhenUpdating() показує у відповідному контексті
onlyOnIndex() лише у списку
onlyOnDetail() лише на перегляді
onlyOnForms() лише на формах створення й редагування
exceptOnForms() на index і detail, але не на формах
canSee(Closure) fn (Request $request): bool; поле існує лише для тих, кому дозволено

Методи hide* і show* приймають bool|Closure (за замовчуванням true). Замикання отримує fn (Request $request, ?Model $record): bool. hide* приховує, коли замикання повертає true, show* показує. На index $record дорівнює null: видимість там визначається для запиту, а не для рядка.

Text::make('Нотатка', 'note')
    ->hideWhenUpdating(fn (Request $request, ?Model $post) => $post?->status === 'live');

Тільки для читання

readonly(bool|Closure $readonly = true): замикання має вигляд fn (Request $request, Model $record): bool (під час створення $record це нова модель).

Select::make('Статус', 'status')->options(['draft' => 'Чернетка', 'live' => 'Опубліковано'])
    ->readonly(fn (Request $request, Model $post) => $post->status === 'live');

Безпека

Приховане, readonly і заборонене через canSee поле пропускається на сервері під час заповнення й валідації: значення такого поля, надіслане вручну, ігнорується. Поле, для якого canSee повернув false, відсутнє в усіх контекстах (колонки, перегляд, форми, заповнення, валідація, сортування).

Яке поле де показується

Поле / налаштування index detail create update
звичайне поле так так так так
ID так так ні ні
Textarea ні так так так
Password ні ні так так
exceptOnForms() так так ні ні
onlyOnForms() ні ні так так
HasMany, BelongsToMany ні так (панель) ні ні
canSee() повернув false ні ні ні ні

Приклад (app/Larsadmin/User.php):

DateTime::make('Створено', 'created_at')->exceptOnForms()->sortable(),

Колонки списку

Метод Опис
width(string|int) ширина: int це пікселі; рядок виду 120px, 20%, 12rem, 10em, 8ch. Інші одиниці й формати кидають InvalidArgumentException
align('left'|'center'|'right') вирівнювання; за замовчуванням left, для Number right, для Boolean center
wrap() дозволити перенесення тексту в комірці
truncate(?int $chars = null) обрізати довгий текст з трикрапкою: після $chars символів (мінімум 1) або за шириною колонки, якщо null
hideByDefault() колонка прихована, доки користувач не ввімкне її в меню «Колонки» (Інтерфейс)

wrap() і truncate() виключають одне одного: діє той, що викликано останнім.

Групування полів

Поля на формах і сторінці перегляду можна згрупувати в панелі (Layout\Panel) і вкладки (Layout\Tabs). fullWidth() розтягує поле на обидві колонки двоколонкової панелі. Див. Блоки полів.

Комбінований приклад

public function fields(Request $request): array
{
    return [
        ID::make()->sortable()->width(70),
        Text::make('Заголовок', 'title')->sortable()->truncate(60)->rules('required', 'max:255'),
        Textarea::make('Текст', 'body')->nullable()->wrap(),
        Select::make('Статус', 'status')->sortable()->width('9rem')
            ->options(['draft' => 'Чернетка', 'live' => 'Опубліковано'])
            ->readonly(fn (Request $request, Model $post) => $post->status === 'live'),
        Number::make('Перегляди', 'views')->min(0)->default(0)->sortable()->align('center'),
        Text::make('Внутрішній код', 'code')->nullable()->hideByDefault()->hideWhenCreating(),
        Text::make('Нотатка модератора', 'moderator_note')->nullable()
            ->canSee(fn (Request $request) => $request->user()->can('moderate')),
        DateTime::make('Створено', 'created_at')->exceptOnForms()->sortable(),
    ];
}

Валідація

Text::make('Email', 'email')->inputType('email')->sortable()
    ->rules('required', 'email', 'max:255', 'unique:users,email,{{id}}'),
Метод Коли діє
rules(...) створення й оновлення
creationRules(...) лише створення
updateRules(...) лише оновлення

Аргументи: рядки, об'єкти правил, замикання або один масив. Кожен виклик замінює набір, заданий цим самим методом раніше.

Конвеєр правил (|)

Рядки з | розбиваються на окремі правила: rules('required|max:255') еквівалентно rules('required', 'max:255'). Виняток: рядок, що містить regex: або not_regex:, не розбивається, бо шаблон може містити |. Такі правила передавайте окремими аргументами:

Text::make('Код', 'code')->rules('required', 'regex:/^(a|b)\d+$/');

Плейсхолдер {{id}}

У рядкових правилах {{id}} замінюється ключем поточного запису, а під час створення значенням NULL. Це дає unique без власних правил для редагування:

Text::make('Слаг', 'slug')->rules('required', 'max:255', 'unique:categories,slug,{{id}}'),

Неявні правила типу

Перед вашими правилами автоматично додаються правила, що випливають з типу поля:

Поле Неявні правила
Text, Textarea, Password nullable, string
Number numeric, а також min:N / max:N з min() / max()
Boolean boolean
Date, DateTime date
Select Rule::in(...) по ключах опцій
BelongsTo required (або nullable) і перевірка RelatableExists
File, Image правила для кожного завантаженого файлу, див. Файли й зображення

Для Number, Boolean, Date, Select правило nullable додається, лише якщо викликано nullable(). Тож Date::make(...) без nullable() вимагає значення навіть без явного required.

Порядок: неявні правила, rules(), потім creationRules() або updateRules().

Пароль: різні правила для створення й оновлення

Приклад (app/Larsadmin/User.php):

Password::make('Пароль', 'password')
    ->creationRules('required', 'min:8')
    ->updateRules('nullable', 'min:8')
    ->help('Залиште порожнім, щоб не змінювати пароль.'),

Повідомлення

Повідомлення валідації беруться з lang/{locale}/validation.php, а підписи полів з їх назв. Українські повідомлення встановлює larsadmin:install (Локалізація).

Власні поля

Власне поле є спадкоємцем Field (або Text, Number, …). З 1.5 його захищені хуки (resolveValue(), formatForDisplay(), fillValue(), fillString(), typeRules(), implicitRules(), acceptsNullInput(), defaultAlign()), публічні хуки (fill(), fillInto(), fillAttribute(), resolve(), eagerLoads(), applySort(), bindTo(), hasAuditValue(), auditValue()), withMeta(), jsonSerialize() і $component є стабільним API. Поле з вбудованим компонентом описано в Розширення: огляд, поле з власним Vue-компонентом, зокрема поле, що надсилає файли (multipart()), у Розширення: публічний API.

З 1.6 стабільні також authorizedTo(), inAction() і хук actionValue(). Два останні стосуються полів у модальному вікні дії: Дії: поля розширень у модальному вікні.

Права на запис: authorizedTo()

authorizedTo(string $ability): bool відповідає, чи може поточний користувач виконати view, update або delete над записом, для якого поле розв'язується (у resolve(), jsonSerialize() тощо). Це ті самі відповіді policy, які панель уже обчислила для рядка (кнопки «Переглянути», «Редагувати», «Видалити»), тож виклик не додає запитів до policy, також на index з багатьма рядками.

use Illuminate\Database\Eloquent\Model;
use Maxcxam\Larsadmin\Fields\Field;

class Contract extends Field
{
    public string $component = 'acme/contract';

    public function resolve(Model $record): static
    {
        parent::resolve($record);

        // посилання лише для того, хто може переглядати запис
        return $this->withMeta([
            'downloadUrl' => $this->authorizedTo('view')
                ? route('acme.contracts.download', $record->getKey())
                : null,
        ]);
    }
}

authorizedTo() повертає false (fail closed), коли відповідь невідома: інша здатність, контекст створення, поле дії (inAction()), поле, створене вручну поза Entity. Права в серіалізоване поле не додаються: поле саме вирішує, що віддати клієнту. Вбудовані File і Image віддають URL файлів за authorizedTo('view'). Larsadmin::findField() повертає поле з правами для знайденого запису. У тестах права передає serializeField(..., abilities: ['view' => true]) (Розширення: тестування).

Далі: Зв'язки.

Введіть запит, щоб шукати в усіх посібниках. ↑ ↓ — вибір, Enter — відкрити.