Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

gabriel27's avatar

Laravel Filament 3 Relation Manager and Group with multiple chained relationships

I am trying to create a page that will show like a tree with 3 models included each related One to Many to each other:

I have 3 models: - Category - Element - Content A category may contain multiple elements and an element may contain multiple contents.

I need to create a page with panels that will allow me to add/edit categories, for each category to add/edit elements and for each element to add/edit content.

So for each model I need to have tables and forms.

I know nesting resources is a solution but honestly I do not want the user to go through all steps.

I found Relation Groups but I believe these are not applicable. Please correct me if I am wrong.

With Relation Manager I found that I may have tabs but I understand this may work if Element and Content are directly related to Category which they are not.

Can I chain Relation Managers somehow? Or is there a better solution?

I would like to manage all from one page and show all forms in modals.

Thank you.

0 likes
13 replies
LaryAI's avatar
Level 58

To achieve the desired functionality in Laravel Filament, you can use the Relation Manager to manage the relationships between your models. However, since you want to manage all three models from one page and show all forms in modals, you will need to set up nested Relation Managers.

Here's a step-by-step guide on how you can set up your Filament page to manage Categories, Elements, and Contents:

  1. Create a Filament Resource for each of your models (Category, Element, Content).

  2. In your CategoryResource, set up a Relation Manager for Elements. This will allow you to manage Elements within a Category.

use Filament\Resources\Form;
use Filament\Resources\Table;
use Filament\Resources\RelationManagers\HasManyRelationManager;

class CategoryResource extends Resource
{
    // ...

    public static function form(Form $form)
    {
        return $form
            // Define fields for Category
            // ...
            ;
    }

    public static function table(Table $table)
    {
        return $table
            // Define columns for Category
            // ...
            ;
    }

    public static function getRelations()
    {
        return [
            ElementsRelationManager::class,
        ];
    }

    public static function getPages()
    {
        return [
            // Define pages for Category
            // ...
        ];
    }
}

class ElementsRelationManager extends HasManyRelationManager
{
    protected static string $relationship = 'elements';

    protected function getTableQuery()
    {
        return parent::getTableQuery()
            // Optionally, add constraints or modify the query
            ;
    }

    protected function getTableColumns()
    {
        return [
            // Define columns for Elements within Category
            // ...
        ];
    }

    protected function getFormSchema()
    {
        return [
            // Define fields for Elements within Category
            // ...
        ];
    }
}
  1. Similarly, in your ElementResource, set up a Relation Manager for Contents.
class ElementResource extends Resource
{
    // ...

    public static function getRelations()
    {
        return [
            ContentsRelationManager::class,
        ];
    }

    // ...
}

class ContentsRelationManager extends HasManyRelationManager
{
    protected static string $relationship = 'contents';

    // Define getTableColumns, getFormSchema, etc. for Contents
}
  1. Now, to manage Contents within Elements within Categories, you can use the ElementsRelationManager within CategoryResource to include a nested Relation Manager for Contents.
class ElementsRelationManager extends HasManyRelationManager
{
    // ...

    protected function getTableColumns()
    {
        return [
            // Define columns for Elements
            // ...

            // Add a nested relation manager for Contents
            Tables\Columns\TextColumn::make('contents_count')
                ->counts('contents')
                ->url(fn ($record): string => URL::route('filament.resources.elements.edit', [
                    'record' => $record,
                    'relation' => 'contents',
                ])),
        ];
    }
}
  1. Finally, ensure that your CategoryResource and ElementResource pages are set up to handle the nested relations and that the forms and tables are displayed in modals as desired.

This setup allows you to manage Categories, Elements, and Contents from one page, with each level of the hierarchy being managed through nested Relation Managers. The ElementsRelationManager within CategoryResource will provide a link to manage the related Contents, which will be handled by the ContentsRelationManager within ElementResource.

Remember to adjust the getTableColumns, getFormSchema, and other methods to match the fields and relationships of your actual models.

gabriel27's avatar

Hello,

Tried the AI suggested solution but it is not working. I am still looking for solutions to this.

Does anyone have any suggestion?

Thank you.

ooyekanmi's avatar

@gabriel27 I tried the Lary AI option for the Nested Relations Manager and it worked perfectly. If you follow the steps carefully,

  • It adds a column to the first relation manager table that links to the 2nd relation manager.

The only down side is that you need to create the resource and relation manager for Element. If you dont want that Element resource on the navigation, then you can hide it with $shouldRegisterNavigation = false;

gabriel27's avatar

@jaseofspades88 The models are related one to many: Category - Element - Content: A category may contain multiple elements and an element may contain multiple contents.

jaseofspades88's avatar

The easiest way to do this in filament would be..

CategoryResource has an ElementRelationManager

and...

ElementResource has a ContentRelationManager

...which would take care of the relationships individually and you'd be able to manage all of those fields out of the box.

If you wanted to create one place to manage all of these, then it's entirely up to you how to handle it. If you create a custom page: https://filamentphp.com/docs/3.x/panels/resources/custom-pages then you can look at how to add a custom table to the page here: https://filamentphp.com/docs/3.x/tables/adding-a-table-to-a-livewire-component.

Then I would suggest you use a series of custom actions to add and manage these resources all from the one table. From experience I can attest to the relation managers being easy to manage... I guess the question comes down to having your user have to click through one or two pages to get all of that filament goodness out of the box... or a LOT of time spent customising the flow for the sake of one or two fewer clicks... it's up to you depending on project requirements.

1 like
gabriel27's avatar

@jaseofspades88 Thank you for your reply. I tried to use the Relation Manager but it works only for the first level. I add the ResourceManager between Category and Element and when I edit a category I see the Category edit form and below the table of Elements.

The Create and Edit functions from the Elements table show the forms in pop-ups.

If I try to add an action to edit one Element and see the Contents table I get the popup with the form but not the table of Contents.

If I try to change the edit action of the Relationship Manager like the below:

Tables\Actions\EditAction::make()->url(fn (Element $record): string => CourseContentResource::getUrl('edit', ['record' => $livewire->getOwnerRecord()])),

I receive an error that it is expecting an Element object not a CourseContent one.

I am sure I am doing something wrong but I could not find any tutorial of nested relation managers.

jaseofspades88's avatar

Did you read the rest of my answer, @gabriel27 about custom pages and adding tables? I have nothing more to add that would bring much more value. Make the tool work for you, not the opposite.

gabriel27's avatar

Thank you for your reply. I thought to give a real try on option 1 and use the included components already created in Filament.

It is true I may create custom pages and sort everything out but the volume of work will be quite different and one of the reasons I chose Filament is to decrease development time.

If anyone is searching for this too all I found so far is to create a nested resource and a relations manager between level 2 and 3. If you have more than 3 levels I still do not have another solution except for the one recommended by @jaseofspades88 to create custom pages.

I will try the nested resources with relations manager for 3 levels and see how it works.

@jaseofspades88 thank you again for all your support.

jaseofspades88's avatar

You can deal with as many levels as necessary, @gabriel27 using filament...

ModelA hasMany ModelB, which hasMany ModelC, which hasMany ModelD...

It just means you need to have multiple relation managers between two resources..

gabriel27's avatar

@jaseofspades88 I mentioned in my reply above:

  • you create the first relation manager Model A hasMany Model B => when you click Edit for Model A you see the form to edit Model A and the table for entries for Model B.
  • you create the second relation manager between Model B hasMany Model C => when I click Edit on any element from Model B I get a popup instead of the page with the form for Model B and I do not get the table with Model C

All I could find online is to use Relation manager between Model A and B and repeater between Model B and C.

Do you know any tutorial, paid course, anything that will document multi level RelationManagers?

Thank you.

gabriel27's avatar
gabriel27
OP
Best Answer
Level 1

I ended up creating a filament page with sections and subsections depending on relationships and each with a livewire component for the pop-up form. This is each of my livewire component for each relationship:

<x-filament::modal id="edit-category-{{ $list->id }}-{{$category->id}}" >
    <x-slot name="trigger">
        <x-filament::button icon="{{ $icon }}" color="{{ $button_color }}">
            {{ $action_text }} category
        </x-filament::button>
    </x-slot>

    <div>
    <x-slot name="heading">
        {{ $action_text }} Category
    </x-slot>
        <form wire:submit="create" class="mt-6">
            {{ $this->form }}

        <x-filament::button type="submit" size="lg" class="mt-6">
            Save
        </x-filament::button>

        </form>
        <x-slot name="footer">

        </x-slot>
    </div>
</x-filament::modal>

After in the livewire component for the form in the create method I do the create actions needed and at the end I add:

$this->form->fill();
parent::dispatch('close-modal', id: 'edit-category-'.$this->list->id.'-'.$category->id);

This way I clear the form and close the exact modal I needed. I had issues to identify the exact modal to close until I found you may add the id of the exact modal.

Also I recommend to dispatch an event to the parent class to refresh the page.

In livewire 3 I dispatched an event in the livewire component:

$this->dispatch('refreshParent');

And in the parent component I used the magic method $refresh:

protected $listeners = ['refreshParent' => '$refresh'];

I hope it helps.

1 like

Please or to participate in this conversation.