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

jcc5018's avatar

Attempt 3-- Trying to dynamically create methods to use in filament, but not sure if i am doing it right

This is the 3rd attempt at a solution to work with filamentphp as my other attempts have failed to save the data.

It seems when i just create a standard select statement with the appropriate relationship attached, the data saves as expected, so I am trying to dynamically create those relationship names based on my table data.

See other two attempts below: Livewire

Within Filament itself

This time i am trying to create the methods by including this code in my HOBBY Model:

public function __call($method, $parameters)
    {
        // Check if the method exists as a tag in the Tag table
        $tag = Tag::where('tag', $method)->first();
        if ($tag) {
            return $this->createRatingMethod($tag->tag);
        }

        return parent::__call($method, $parameters);
    }

    private function createRatingMethod($tag): MorphToMany
    {
        return $this->morphToMany(Tag::class, 'taggable')
                    ->where('tag_type', 13)
                    ->where('tag', $tag)
                    ->withTimestamps();
    }

then in the hobby resource, i created a function :

 public static function Ratings()
    {
        $ratings = Tag::where('tag_type', 13)
                      ->where('parent_id', null)
                      ->orderBy('tag', 'asc')
                      ->get();

        foreach ($ratings as $rating) {
            return Select::make($rating->tag)
                         ->label($rating->tag)
                         ->relationship(
                             name: $rating->tag,
                             titleAttribute: 'tag'
                         );
        }
    }

Which i then called in the form via

 Section::make('Ratings')
                       ->schema([
                           self::Ratings(),
                           //                           Livewire::make(Ratings::class),
                       ]),

So this results in an error: Call to a member function getResults() on null:

which i have no idea what it is referring to, so once again, i am stuck. Filament is getting to be too complicated for me to work with

The ratings section is a subform based on TAGS table with the inputs generated from the PARENT TAG and options generated from each child tag. I can get the form to display in the first two methods i have tried but the data will not save. And i have no idea how to fix it so it does. I have been working on this for months now and I am getting frustrated not being able to find a solution.

I suspect in the first two methods I tried, I am simply not saving the correct value. As in some sort of array format Data{ratings] or something but since i can't figure out how to see the $Data being passed, it is difficult to see how I need to format it.

See sample DB and expected rendering : Sample

0 likes
3 replies
LaryAI's avatar
Level 58

It seems like you're trying to dynamically create relationships and form fields in Filament based on tags from your database. There are a few issues in your code that need to be addressed.

Firstly, in your __call method, you're trying to dynamically handle method calls that don't exist on the model. However, the createRatingMethod should return a relationship instance, but it's not clear if it's being used correctly since the __call method should return the result of the relationship method, not the relationship method itself.

Secondly, in your Ratings method within the hobby resource, you're using a foreach loop but returning on the first iteration, which means you're only creating a select field for the first rating. You should instead be collecting all the select fields and returning them as an array.

Here's a revised version of your code:

In your Hobby model:

public function __call($method, $parameters)
{
    // Check if the method exists as a tag in the Tag table
    $tag = Tag::where('tag', $method)->first();
    if ($tag) {
        return $this->morphToMany(Tag::class, 'taggable')
                    ->where('tag_type', 13)
                    ->where('tag', $tag->tag)
                    ->withTimestamps();
    }

    return parent::__call($method, $parameters);
}

In your Hobby resource:

public static function Ratings()
{
    $ratings = Tag::where('tag_type', 13)
                  ->where('parent_id', null)
                  ->orderBy('tag', 'asc')
                  ->get();

    $fields = [];

    foreach ($ratings as $rating) {
        $fields[] = Select::make($rating->tag)
                         ->label($rating->tag)
                         ->relationship(
                             name: $rating->tag,
                             titleAttribute: 'tag'
                         );
    }

    return $fields;
}

And in your form schema:

Section::make('Ratings')
       ->schema([
           ...self::Ratings(), // Spread operator to include all fields
       ]),

Make sure to use the spread operator (...) to include all the fields in the schema array.

Regarding the error "Call to a member function getResults() on null", this suggests that the relationship method you're trying to call does not exist or is not returning a proper relationship instance. Ensure that the dynamic method names you're creating match the actual relationship names and that they return valid relationship instances.

Lastly, if you're still having trouble with saving the data, you might need to look into how Filament handles saving relationships and ensure that your dynamic fields are correctly configured to save the related data. You may need to override the save method in your Filament resource or use a custom Livewire component to handle the saving logic.

jcc5018's avatar

I know that the bot wont answer anymore, but isnt the point of this code to CREATE the methods that do not actually exist? So I do not understand how this works I guess as my goal is to create not check if some method exists so that I do not have to manually create a new method each time I add a rating category.

jcc5018's avatar

This adjusted code displays the inputs, but still does not save the selected option to the taggables table

 public static function Ratings()
    {
        $parentTags = Tag::where('tag_type', 13)
                         ->where('parent_id', null)
                         ->orderBy('tag', 'asc')
                         ->get();

        $fields = [];

        foreach ($parentTags as $parentTag) {
            $childTags = Tag::where('parent_id', $parentTag->id)->get();

            $select = Select::make($parentTag->tag)
                            ->label($parentTag->tag)
                            ->options(function () use ($childTags) {
                                return $childTags->pluck('tag', 'id');
                            });

            $fields[] = $select;
        }

        return $fields;
    }

Hobby model

 public function __call($method, $parameters)
    {
        // Check if the method exists as a tag in the Tag table
        $tag = Tag::where('tag', $method)->first();
        if ($tag && $tag->parent_id === null) {
            return $this->createRatingMethod($tag->id);
        }

        return parent::__call($method, $parameters);
    }

    private function createRatingMethod($parentId): MorphToMany
    {
        return $this->morphToMany(Tag::class, 'taggable')
                    ->where('parent_id', $parentId)
                    ->withTimestamps();
    }

Please or to participate in this conversation.