filamentphp / filament

A collection of beautiful full-stack components for Laravel. The perfect starting point for your next app. Using Livewire, Alpine.js and Tailwind CSS.
https://filamentphp.com
MIT License
18.1k stars 2.83k forks source link

After v3 upgrade: No property found for validation: ['name'] #8009

Closed XbNz closed 1 year ago

XbNz commented 1 year ago

Package

filament/filament

Package Version

v3.0.30

Laravel Version

v10.20.0

Livewire Version

v3.0.0-beta.10

PHP Version

PHP 8.2.8

Problem description

The error is not very clear, in fact, the end of the stack trace is inside index.php which is never helpful.

Did some digging and found Livewire\Features\SupportValidation\HandlesValidation::checkRuleMatchesProperty() to be at fault.

Possibly useful debug info:

// CanBeValidated::class

public function validate(): array
{
    if (! count($this->getComponents())) {
        return [];
    }

    $rules = $this->getValidationRules();

    if (! count($rules)) {
        return [];
    }

    dd($rules, $this->getValidationAttributes());

    return $this->getLivewire()->validate($rules, [], $this->getValidationAttributes());
}

Dump results:

array:3 [▼ // vendor/filament/forms/src/Concerns/CanBeValidated.php:78 "field_1" => array:1 [▶] "field_2" => array:3 [▶] "field_3" => array:3 [▶] ]

array:3 [▼ // vendor/filament/forms/src/Concerns/CanBeValidated.php:78 "field_1" => "field 1" "field_2" => "field 2" "field_3" => "field 3" ]

Expected behavior

Work, I guess?

Steps to reproduce

Upgrade from Filament v2 & Livewire v2 to Filament v3 & Livewire v3

Reproduction repository

Unable to reproduce in fresh project

Relevant log output

No response

github-actions[bot] commented 1 year ago

Hey @XbNz! We're sorry to hear that you've hit this issue. 💛

However, it looks like you forgot to fill in the reproduction repository URL. Can you edit your original post and then we'll look at your issue?

We need a public GitHub repository which contains a Laravel app with the minimal amount of Filament code to reproduce the problem. Please do not link to your actual project, what we need instead is a minimal reproduction in a fresh project without any unnecessary code. This means it doesn't matter if your real project is private / confidential, since we want a link to a separate, isolated reproduction. That would allow us to download it and review your bug much easier, so it can be fixed quicker. Please make sure to include a database seeder with everything we need to set the app up quickly.

XbNz commented 1 year ago

Ok, some more info:

Whatever is happening inside of Livewire\Features\SupportValidation\HandlesValidation::validate() is causing the issue. In particular, this specific code snippet:

$data = $this->prepareForValidation(
    $this->getDataForValidation($rules)
);

Which seems to be turning my $rules into, well, whatever this is...

$data: array:11 [▼ // vendor/livewire/livewire/src/Features/SupportValidation/HandlesValidation.php:210 "record" => null "data" => [] "previousUrl" => "http://app.test/admin/resource-name/create" "mountedActions" => [] "mountedActionsArguments" => [] "mountedActionsData" => [] "componentFileAttachments" => [] "mountedFormComponentActions" => [] "mountedFormComponentActionsArguments" => [] "mountedFormComponentActionsData" => [] "mountedFormComponentActionsComponents" => [] ]

And then trying to compare it to the $rules, using:

$this->checkRuleMatchesProperty($rules, $data);
protected function checkRuleMatchesProperty($rules, $data)
{
    collect($rules)
        ->keys()
        ->each(function($ruleKey) use ($data) {
            throw_unless(
                array_key_exists(Utils::beforeFirstDot($ruleKey), $data),
                new \Exception('No property found for validation: ['.$ruleKey.']')
            );
        });
}

And that's where the error is thrown.

frknasir commented 1 year ago

Could it be that for every rule key, livewire expects a corresponding public property?

pcfjojo commented 1 year ago

I also face the same issue.

gjsman commented 1 year ago

I had this problem as well. It appears to be an undocumented, massive breaking change.

The way I fixed it was as follows (please leave a heart or thumbs up if you were affected and this helps - if this is a recurring issue I'll file a PR to add it to breaking changes):

  1. Before any methods, paste the following property:
public ?array $data = [];
  1. Then, in your code, add the following function / adapter shim:
use Filament\Forms;

public function form(Forms\Form $form): Forms\Form
    {
        return $form
            ->schema($this->getFormSchema())
            ->statePath('data');
    }

I noticed this because if you read the new, v3 documentation for adding a form to a Livewire component, getFormSchema() never appears anymore. Yet it still functions in apparently (I'm just guessing) a botched attempt at backwards compatibility which in some situations backfires and just makes things confusing.

Edit: Also, for fixing broken relationships: https://filamentphp.com/docs/3.x/forms/adding-a-form-to-a-livewire-component#setting-a-form-model

pcfjojo commented 1 year ago

@gjsman Thank you so much for your valuable comment.

frknasir commented 1 year ago

@gjsman Thanks man! Just came back to post that I solved it reading this -> https://filamentphp.com/docs/3.x/forms/adding-a-form-to-a-livewire-component

jaypatch commented 1 year ago

@gjsman it worked

massimomarazzi commented 8 months ago

@gjsman it worked