Поля

BelongsToMany

Основы

Поле BelongsToMany предназначено для работы с одноименной связью в Laravel и включает все Базовые методы.

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

Наличие ModelResource, на который ссылается отношение, обязательно. Ресурс также необходимо зарегистрировать в сервис-провайдере MoonShineServiceProvider в методе $core->resources(). В противном случае будет ошибка 500.

 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make(
'Categories',
'categories',
resource: CategoryResource::class
)

belongs_to_many belongs_to_many_dark

Вы можете опустить $resource, если ModelResource совпадает с названием связи.

use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', 'categories')

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

use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories')

По умолчанию для отображения значения используется поле в связанной таблице, которое указано свойством $column в ресурсе модели. Аргумент $formatted позволяет переопределить это.

use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make(
'Categories',
'categories',
formatted: 'name'
)

Если вам нужно указать более сложное значение для отображения, тогда в аргумент $formatted можно передать функцию обратного вызова.

use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make(
'Categories',
'categories',
fn($item) => "$item->id. $item->title"
)

Заголовок столбца

По умолчанию заголовок столбца таблицы использует свойство $title, указанное в ModelResource отношения. Метод columnLabel() позволяет переопределить заголовок.

columnLabel(string $label)
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->columnLabel('Title')

Pivot

Метод fields() используется для реализации полей pivot в отношении BelongsToMany.

fields(FieldsContract|Closure|iterable $fields)
 namespaces
use App\MoonShine\Resources\ContactResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Fields\Text;
 
BelongsToMany::make(
'Contacts',
resource: ContactResource::class
)
->fields([
Text::make('Contact', 'text'),
])

belongs_to_many_pivot belongs_to_many_pivot_dark

В отношении необходимо указать, какие поля pivot используются в промежуточной таблице! Подробнее в официальной документации Laravel.

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

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

creatable(
Closure|bool|null $condition = null,
?ActionButton $button = null,
)
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->creatable()

belongs_to_many_creatable belongs_to_many_creatable_dark

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

 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Components\ActionButton;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->creatable(
button: ActionButton::make('Custom button', '')
)

Выбор

Поле BelongsToMany может быть отображено в виде выпадающего списка. Для этого необходимо использовать метод selectMode().

 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->selectMode()

belongs_to_many_select belongs_to_many_select_dark

Опции

Все опции выбора доступны для изменения через атрибуты data:

 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->selectMode()
->customAttributes([
'data-max-item-count' => 2
])

Для получения более подробной информации, пожалуйста, обратитесь к Choices.

Placeholder

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

placeholder(string $value)
BelongsToMany::make('Countries', 'countries')
->nullable()
->placeholder('Countries')

Метод placeholder() используется только если поле отображается в виде выпадающего списка selectMode()!

Дерево

Метод tree() позволяет отображать значения в виде дерева с чекбоксами, например, для категорий, которые имеют вложенность. В метод необходимо передать столбец в базе данных, по которому будет строиться дерево.

tree(string $parentColumn)
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->tree('parent_id')

belongs_to_many_tree belongs_to_many_tree_dark

Горизонтальный режим

Метод horizontalMode() позволяет отображать значения в виде горизонтального списка.

horizontalMode(
Closure|bool|null $condition = null,
string $minColWidth = '200px',
string $maxColWidth = '1fr'
)
  • $condition - (опционально) условие для отображения поля в горизонтальном режиме,
  • $minColWidth - (опционально) минимальная ширина колонки,
  • $maxColWidth - (опционально) максимальная ширина колонки.
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->horizontalMode(true, minColWidth: '100px', maxColWidth: '33%')

belongs_to_many_horizontal belongs_to_many_horizontal_dark

Предпросмотр

По умолчанию в preview поле будет отображаться в виде таблицы.

belongs_to_many_preview belongs_to_many_preview_dark

Для изменения отображения в preview можно использовать следующие методы.

onlyCount

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

BelongsToMany::make('Categories', resource: CategoryResource::class)
->onlyCount()

belongs_to_many_preview_count belongs_to_many_preview_count_dark

inLine

Метод inLine() позволяет отображать значения поля в виде строки.

inLine(string $separator = '', Closure|bool $badge = false, ?Closure $link = null)

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

  • separator - разделитель между элементами,
  • badge - замыкание или булево значение, отвечающее за отображение элементов в виде бейджа,
  • $link - замыкание, которое должно возвращать ссылки url или компонент Link.

При передаче булевого значения true в параметр badge будет использоваться цвет Primary. Для изменения цвета отображаемого badge используйте замыкание и возвращайте компонент Badge::make().

 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Components\Badge;
use MoonShine\UI\Components\Link;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->inLine(
separator: ' ',
badge: fn($model, $value) => Badge::make((string) $value, 'primary'),
link: fn(Property $property, $value, $field): string|Link => Link::make(
app(CategoryResource::class)->getDetailPageUrl($property->id),
$value
)
)

belongs_to_many_preview_in_line belongs_to_many_preview_in_line_dark

Метод relatedLink() позволит отобразить отношение в виде ссылки с количеством элементов. Ссылка будет вести на IndexPage дочернего ресурса из отношения HasMany, в котором буду показаны только данные элементы.

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

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

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

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

 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->relatedLink('category')

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

 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Fields\Field;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->relatedLink(condition: function (int $count, Field $field): bool {
return $count > 10;
})

Запрос для значений

Метод valuesQuery() позволяет изменить запрос для получения значений.

valuesQuery(Closure $callback)
 namespaces
use App\MoonShine\Resources\CategoryResource;
use Illuminate\Contracts\Database\Eloquent\Builder;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Fields\Field;
 
BelongsToMany::make('Categories', 'categories', resource: CategoryResource::class)
->valuesQuery(fn(Builder $query, Field $field) => $query->where('active', true))

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

asyncSearch(
string $column = null,
?Closure $searchQuery = null,
?Closure $formatted = null,
?string $associatedWith = null,
int $limit = 15,
?string $url = null,
)
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', 'categories', resource: CategoryResource::class)
->asyncSearch()

Поиск будет осуществляться по полю отношения ресурса column. По умолчанию column=id.

Вы можете передать параметры в метод asyncSearch():

  • $column - поле, по которому осуществляется поиск,
  • $searchQuery - функция обратного вызова для фильтрации значений,
  • $formatted - функция обратного вызова для настройки вывода,
  • $associatedWith - поле, с которым установить связь,
  • $limit - количество элементов в результатах поиска,
  • $url - url для обработки асинхронного запроса.
 namespaces
use App\MoonShine\Resources\CountryResource;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Fields\Field;
 
BelongsToMany::make('Countries', 'countries', resource: CountryResource::class)
->asyncSearch(
'title',
10,
searchQuery: function (Builder $query, Request $request, Field $field) {
return $query->where('id', '!=', 2);
},
formatted: function ($country, Field $field) {
return $country->id . ' | ' . $country->title;
},
'https://moonshine-laravel.com/async'
)

При построении запроса в searchQuery() вы можете использовать текущие значения формы. Для этого нужно передать Request в функцию обратного вызова.

 namespaces
use App\MoonShine\Resources\CityResource;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
use MoonShine\UI\Fields\Field;
use MoonShine\UI\Fields\Select;
 
Select::make('Country', 'country_id'),
 
BelongsToMany::make('Cities', 'cities', resource: CityResource::class)
->asyncSearch(
'title',
searchQuery: function (Builder $query, Request $request, Field $field): Builder {
return $query->where('country_id', $request->get('country_id'));
}
)

Запросы должны быть настроены с использованием метода asyncSearch(). Не используйте valuesQuery()!

Связанные поля

Для установления связи значений выбора между полями можно использовать метод associatedWith().

associatedWith(string $column, ?Closure $searchQuery = null)
  • $column - поле, с которым устанавливается связь,
  • searchQuery - функция обратного вызова для фильтрации значений.
 namespaces
use App\MoonShine\Resources\CityResource;
use MoonShine\Laravel\Fields\Relationships\BelongsTo;
 
BelongsToMany::make('Cities', 'cities', resource: CityResource::class)
->associatedWith('country_id')

Для более сложной настройки вы можете использовать asyncSearch().

Значения с изображением

Метод withImage() позволяет добавить изображение к значению.

withImage(
string $column,
string $disk = 'public',
string $dir = ''
)
  • $column - поле с изображением,
  • $disk - диск файловой системы,
  • $dir - директория относительно корня диска.
 namespaces
use App\MoonShine\Resources\CityResource;
use MoonShine\Laravel\Fields\Relationships\BelongsTo;
 
BelongsToMany::make('Cities', resource: CityResource::class)
->withImage('thumb', 'public', 'countries')->selectMode()

with_image belongs_to_image_dark

Кнопки

Метод buttons() позволяет добавить дополнительные кнопки к полю BelongsToMany.

buttons(array $buttons)
 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\UI\Components\ActionButton;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->buttons([
ActionButton::make('Check all', '')
->onClick(fn() => 'checkAll', 'prevent'),
 
ActionButton::make('Uncheck all', '')
->onClick(fn() => 'uncheckAll', 'prevent')
])

withCheckAll

Метод withCheckAll() позволяет добавить кнопку checkAll к полю BelongsToMany, аналогично предыдущему примеру.

 namespaces
use App\MoonShine\Resources\CategoryResource;
use MoonShine\Laravel\Fields\Relationships\BelongsToMany;
 
BelongsToMany::make('Categories', resource: CategoryResource::class)
->withCheckAll()