# Basics
The HasMany field is designed to work with the relation of the same name in Laravel and includes all the basic methods.
To create this field, use the static make()
method.
HasMany::make( Closure|string $label, ?string $relationName = null, Closure|string|null $formatted = null, ?ModelResource $resource = null)
$relationName
- name of the relationship,$resource
- the model resource referenced by the relation.
$label
- label, field header,
The $formatted
parameter is not used in the HasMany
field!
The presence of the model resource referenced by the relation is mandatory!
The resource also needs to be
registered
with the service provider MoonShineServiceProvider in the method
menu()
or resources()
. Otherwise, there will be a 404 error.
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', 'comments', resource: new CommentResource()) ];} //...
If you do not specify $relationName
,
then the relation name will be determined automatically based on $label
.
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', resource: new CommentResource()) ];} //...
You can omit $resource
if the model resource matches the name of the relationship.
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', 'comments') ];} //...
# Fields
The fields()
method allows you to set the fields that will be displayed in the 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'), ]) ];} //...
# Creating a Relationship Object
The creatable()
method allows you to create a new relation object through a modal window.
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() ];} //...
You can customize the create button by passing the button parameter to the method.
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', resource: new CommentResource()) ->creatable( button: ActionButton::make('Custom button', '') ) ];} //...
# Number of records
The limit()
method allows you to limit the number of records displayed in preview.
limit(int $limit)
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', resource: new CommentResource()) ->limit(1) ];} //...
# Link only
The onlyLink()
method will allow you to display the relationship as a link with the number of elements.
onlyLink(?string $linkRelation = null, Closure|bool|null $condition = null)
You can pass optional parameters to the method:
linkRelation
- relation reference;-
condition
- closure or boolean value, responsible for displaying the relationship as a link.
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', resource: new CommentResource()) ->onlyLink() ];} //...
To retrieve relation values for a parent resource,
You must set the $parentRelations
property in the relationship resource.
namespace App\MoonShine\Resources; use MoonShine\Resources\ModelResource; class CommentResource extends ModelResource{ //... protected array $parentRelations = ['user']; //...}
The route will be available:
/resource/comment-resource/index-page/user-{id}
The linkRelation
parameter allows you to create a link to a relation with a parent resource binding.
use MoonShine\Fields\Relationships\HasMany; //... public function fields(): array{ return [ HasMany::make('Comments', resource: new CommentResource()) ->onlyLink('user') ];} //...
The condition
parameter via a closure will allow you to change the display method depending on the conditions.
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; }) ];} //...
# Parent ID
If the relationship has a resource, and you want to get the ID of the parent element, then you can use the ResourceWithParent trait.
use MoonShine\Resources\ModelResource;use MoonShine\Traits\Resource\ResourceWithParent; class PostImageResource extends ModelResource{ use ResourceWithParent; //...}
When using a trait, it is necessary to define methods:
protected function getParentResourceClassName(): string{ return PostResource::class;} protected function getParentRelationName(): string{ return 'post';}
To get the parent ID, use the getParentId()
method.
$this->getParentId();
Recipe: saving files HasMany connections in the directory with the parent ID.
# Advanced
The HasMany field is displayed outside the main resource form by default.
If you need to display relation fields inside the main form,
then you can use the JSON field in the asRelation()
mode.
//... public function fields(): array{ return [ Json::make('Comments', 'comments') ->asRelation(new CommentResource()) //... ]} //...
For more detailed information, please refer to the section Json field .
Using the Template field you can construct a field for HasMany relationships using fluent interface during the declaration process.
For more detailed information, please refer to the section Template field .
In Moonshine you can customize the form page and place HasMany fields in tabs using the Tabs and Tab decorations.
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, ]; }}
For more details you can read the article Form page customization. Moon Shine 2.0 .