HasMany

# Основы

Поле HasMany предназначено для работы с одноименным отношением в Laravel и включает в себя все базовые методы.

Для создания данного поля используется статический метод make().

HasMany::make(
Closure|string $label,
?string $relationName = null,
Closure|string|null $formatted = null,
?ModelResource $resource = null
)
  • $label - лейбл, заголовок поля,
  • $relationName - название отношения,
  • $resource - ресурс модели на которую ссылается отношение.

Параметр $formatted не используется в поле HasMany!

Наличие ресурса модели, на которую ссылается отношение, обязательно!
Ресурс также необходимо зарегистрировать в сервис провайдере MoonShineServiceProvider в методе menu() или resources(). Иначе, будет 404 ошибка.

use MoonShine\Fields\Relationships\HasMany;
 
//...
 
public function fields(): array
{
return [
HasMany::make('Comments', 'comments', resource: new CommentResource())
];
}
 
//...

Если не указать $relationName, то название отношения будет определено автоматически на основе $label.

use MoonShine\Fields\Relationships\HasMany;
 
//...
 
public function fields(): array
{
return [
HasMany::make('Comments', resource: new CommentResource())
];
}
 
//...

Можно не указывать $resource, если ресурс модели соответствует названию отношения.

use MoonShine\Fields\Relationships\HasMany;
 
//...
 
public function fields(): array
{
return [
HasMany::make('Comments', 'comments')
];
}
 
//...

# Поля

Метод fields() позволят задать поля, которые будут отображаться в preview.

fields(Fields|Closure|array $fields)
use MoonShine\Fields\Relationships\BelongsTo;
use MoonShine\Fields\Relationships\HasMany;
use MoonShine\Fields\Text;
 
//...
 
public function fields(): array
{
return [
HasMany::make('Comments', resource: new CommentResource())
->fields([
BelongsTo::make('User'),
Text::make('Text'),
])
];
}
 
//...

# Создание объекта отношения

Метод creatable() позволяет создавать новый объект отношения через модальное окно.

creatable(
Closure|bool|null $condition = null,
?ActionButton $button = null,
)
use MoonShine\Fields\Relationships\HasMany;
 
//...
 
public function fields(): array
{
return [
HasMany::make('Comments', resource: new CommentResource())
->creatable()
];
}
 
//...

Кастомизировать кнопку создания можно передав методу параметр button.

use MoonShine\Fields\Relationships\HasMany;
 
//...
 
public function fields(): array
{
return [
HasMany::make('Comments', resource: new CommentResource())
->creatable(
button: ActionButton::make('Custom button', '')
)
];
}
 
//...

# Количество записей

Метод limit() позволяет ограничить количество записей отображаемых в preview.

limit(int $limit)
use MoonShine\Fields\Relationships\HasMany;
 
//...
 
public function fields(): array
{
return [
HasMany::make('Comments', resource: new CommentResource())
->limit(1)
];
}
 
//...

Метод onlyLink() позволят отобразить отношение в виде ссылки с количеством элементов.

onlyLink(?string $linkRelation = null, Closure|bool|null $condition = null)

Методу можно передать необязательные параметры:

  • linkRelation - ссылка на отношение;
  • condition - замыкание или булево значение, отвечающее за отображение отношения как ссылки.

use MoonShine\Fields\Relationships\HasMany;
 
//...
 
public function fields(): array
{
return [
HasMany::make('Comments', resource: new CommentResource())
->onlyLink()
];
}
 
//...
linkRelation

Параметр linkRelation позволяет создать ссылку на отношение с привязкой родительского ресурса.

use MoonShine\Fields\Relationships\HasMany;
 
//...
 
public function fields(): array
{
return [
HasMany::make('Comments', resource: new CommentResource())
->onlyLink('comment')
];
}
 
//...
condition

Параметр condition через замыкание позволят изменять способ отображения в зависимости от условий.

use MoonShine\Fields\Relationships\HasMany;
 
//...
 
public function fields(): array
{
return [
HasMany::make('Comments', resource: new CommentResource())
->onlyLink(condition: function (int $count, Field $field): bool {
return $count > 10;
})
];
}
 
//...

# ID родителя

Если у связи есть ресурс, и необходимо получить ID родительского элемента, то можно воспользоваться трейтом ResourceWithParent.

use MoonShine\Resources\ModelResource;
use MoonShine\Traits\Resource\ResourceWithParent;
 
class PostImageResource extends ModelResource
{
use ResourceWithParent;
 
//...
}

При использовании трейта, необходимо определить методы:

protected function getParentResourceClassName(): string
{
return PostResource::class;
}
 
protected function getParentRelationName(): string
{
return 'post';
}

Для получения ID родителя используется метод getParentId().

$this->getParentId();

Рецепт: сохранение файлов в директории с ID родителя.

# Кнопка редактирования

Метод changeEditButton() позволяет полностью переопределить кнопку редактирования.

use MoonShine\Fields\Relationships\HasMany;
 
//...
 
HasMany::make('Comments', 'comments', resource: new CommentResource())
->changeEditButton(
ActionButton::make(
'Edit',
fn(Comment $comment) => (new CommentResource())->formPageUrl($comment)
)
)

# Модальные окна

По умолчанию создание и редактирование записи поля HasMany происходит в модальном окне, метод withoutModals() позволяет отключить такое поведение.

use MoonShine\Fields\Relationships\HasMany;
 
//...
 
HasMany::make('Comments', 'comments', resource: new CommentResource())
->withoutModals()

# Модификация

У поля HasMany существуют методы с помощью которых можно модифицировать кнопки, изменить TableBuilder для превью и формы, а также изменить onlyLink кнопку.

modifyItemButtons()

Метод modifyItemButtons() позволяет изменить кнопки просмотра, редактирования, удаления и массового удаления.

/**
* @param Closure(ActionButton $detail, ActionButton $edit, ActionButton $delete, ActionButton $massDelete, self $field): array $callback
*/
modifyItemButtons(Closure $callback)
use MoonShine\Fields\Relationships\HasMany;
 
//...
 
public function fields(): array
{
return [
HasMany::make('Comments', resource: new CommentResource())
->modifyItemButtons(
fn(ActionButton $detail, $edit, $delete, $massDelete, HasMany $ctx) => [$detail])
)
];
}
 
//...
modifyOnlyLinkButton()

Метод modifyOnlyLinkButton() позволяет изменить onlyLink кнопку.

use MoonShine\Fields\Relationships\HasMany;
 
//...
 
public function fields(): array
{
return [
HasMany::make('Comments', resource: new CommentResource())
->onlyLink()
->modifyOnlyLinkButton(
fn(ActionButton $button, bool $preview) => $button
->when(
$preview,
fn(ActionButton $btn) => $btn->primary()
fn(ActionButton $btn) => $btn->secondary()
)
)
];
}
 
//...
modifyCreateButton() / modifyEditButton()

Методы modifyCreateButton() и modifyEditButton() позволяют изменять кнопки создания и редактирования.

use MoonShine\Fields\Relationships\HasMany;
 
//...
 
public function fields(): array
{
return [
HasMany::make('Comments', resource: new CommentResource())
->modifyCreateButton(
fn(ActionButton $button) => $button->setLabel('Custom create button')
)
->modifyEditButton(
fn(ActionButton $button) => $button->setLabel('Custom edit button')
)
->creatable(true)
];
}
 
//...
modifyTable()

Метод modifyTable() позволяет изменить TableBuilder для превью и формы.

use MoonShine\Fields\Relationships\HasMany;
 
//...
 
public function fields(): array
{
return [
HasMany::make('Comments', resource: new CommentResource())
->modifyTable(
fn(TableBuilder $table, bool $preview) => $table
->when($preview, fn(TableBuilder $tbl) => $tbl->customAttributes(['style' => 'background: blue']))
->unless($preview, fn(TableBuilder $tbl) => $tbl->customAttributes(['style' => 'background: green']))
)
];
}
 
//...

# Продвинутое применение

Отношение через поле JSON

Поле HasMany по умолчанию отображается вне основной формы ресурса.
Если необходимо отобразить поля отношения внутри основной формы, то можно воспользоваться полем JSON в режиме asRelation().

//...
 
public function fields(): array
{
return [
Json::make('Comments', 'comments')
->asRelation(new CommentResource())
//...
]
}
 
//...

За более подробной информацией обратитесь к разделу поле Json .

Отношение через поле Template

Используя поле Template можно конструировать поле для отношений HasMany используя fluent interface в процессе объявления.

За более подробной информацией обратитесь к разделу поле Template .

Вкладки для полей HasMany

В Moonshine можно кастомизировать страницу формы и разместить поля HasMany во вкладках используя декорации Tabs и Tab.

class PostFormPage extends FormPage
{
public function components(): array
{
if(! $this->getResource()->getItemID()) {
return parent::components();
}
 
$bottomComponents = $this->getLayerComponents(Layer::BOTTOM);
$imagesComponent = collect($bottomComponents)->filter(fn($component) => $component->getName() === 'images')->first();
$commentsComponent = collect($bottomComponents)->filter(fn($component) => $component->getName() === 'comments')->first();
 
$tabLayer = [
Block::make('', [
Tabs::make([
Tab::make('Edit', $this->mainLayer()),
Tab::make('Images', [$imagesComponent]),
Tab::make('Comments', [$commentsComponent])
])
])
];
 
return [
...$this->getLayerComponents(Layer::TOP),
...$tabLayer,
];
}
}

За более подробно можно прочитать в статье Кастомизация страницы формы. MoonShine 2.0 .