Closed mahfoudfx closed 1 year ago
Hi,
I'm not familiar with Filament.
So I quickly scouted the docs and source for the unique
rule, which is similar to unique_translation
.
If you know more about its inner workings, I'd be happy to learn it.
It seems that the built-in unique
rule accepts an ignorable
or ignoreRecord
parameter.
This is automatically used on update
validations:
https://filamentphp.com/docs/2.x/forms/validation#unique
Sometimes, you may wish to ignore a given model during unique validation. For example, consider an "update profile" form that includes the user's name, email address, and location. You will probably want to verify that the email address is unique. However, if the user only changes the name field and not the email field, you do not want a validation error to be thrown because the user is already the owner of the email address in question.
Field::make('email')->unique(ignorable: $ignoredUser)
If you're using the admin panel, you can easily ignore the current record by using ignoreRecord instead:
Field::make('email')->unique(ignoreRecord: true)
When you look at the code, it evaluates the parameters and generates a standard Rule
.
What I don't see is a nice way to add more rules, except with the rule()
or rules()
method.
But that wouldn't be very clean.
I tried to investigate using the simple way similar to Laravel Nova.
Forms\Components\TextInput::make('slug')->required()
->rules(['unique_translation:posts,slug']),
It doesn't generate any error but it allows the duplication. After a quick check, I noticed that the generated query is wrong. It is generating the name of the column in place of the code of language.
Actual generated query (not working)
select count(*) as aggregate from `posts` where (`slug` LIKE %"slug": "books"% or `slug` LIKE %"slug":"books"%))
Excpected query
select count(*) as aggregate from `posts` where (`slug` LIKE %"en": "books"% or `slug` LIKE %"en":"books"%))
I found the source of this issue and a solution. It is related to the function getArrayAttributeNameAndLocale
located in the class/file UniqueTranslationValidator.php
(line 97), by replacing the second parameter of the getAttributeNameAndLocale
function. I just replaced the dot '.'
by a ','
and it works.
Actual getArrayAttributeNameAndLocale
function (not working)
protected function getArrayAttributeNameAndLocale($attribute)
{
return $this->getAttributeNameAndLocale($attribute, '.');
}
Working getArrayAttributeNameAndLocale
function
protected function getArrayAttributeNameAndLocale($attribute)
{
return $this->getAttributeNameAndLocale($attribute, ',');
}
When I change the dot to a comma my validation tests fail. I do get the correct query using the dot.
Illuminate\Database\Events\QueryExecuted^ {
+sql: "select count(*) as aggregate from `test_models` where (`slug` LIKE ? or `slug` LIKE ?)"
+bindings: array:2 [
0 => "%"en": "existing-slug-en"%"
1 => "%"en":"existing-slug-en"%"
]
+time: 0.28
+connection: Illuminate\Database\MySqlConnection^ {#940 …24}
+connectionName: "mysql"
}
The dot is what Laravel uses to notate array fields in the form. This package is designed to accept fields like this:
<!-- This assumes you want to use the current locale -->
<input name="slug">
<!-- Specific locales in array syntax -->
<input name="slug[en]">
<input name="slug[nl]">
Can you show me in what format the form input is received?
I think this trait handles the validation: https://github.com/filamentphp/filament/blob/2.x/packages/support/src/Commands/Concerns/CanValidateInput.php
I fixed on my side: https://github.com/codezero-be/laravel-unique-translation/pull/26
I fixed on my side: #26
Thank you for the PR! 👍
Hello, I tried to use this great package with Filament which handles translations using spatie/nova-translatable in a simple way like Laravel Nova, unfortunately this is not working (allowing duplication).
Laravel Nova
Filament (assumed and tested)
Thanks.