Laravel Unique Translation
IMPORTANT: March 2022
, (*1)
It's horrible to see what is happening now in Ukraine, as Russian army is
bombarding houses, hospitals and kindergartens., (*2)
Please check out supportukrainenow.org for the ways how you can help people there.
Spread the word., (*3)
And if you are from Russia and you are against this war, please express your protest in some way.
I know you can get punished for this, but you are one of the hopes of those innocent people., (*4)
, (*5)
, (*6)
Check if a translated value in a JSON column is unique in the database.
Imagine you want store a slug
for a Post
model in different languages., (*7)
The amazing spatie/laravel-translatable
package makes this a cinch!, (*8)
But then you want to make sure each translation is unique for its language., (*9)
That's where this package comes in to play., (*10)
This package also supports spatie/nova-translatable
in case you are using Laravel Nova and filamentphp/spatie-laravel-translatable-plugin
in case you are using Filament., (*11)
โ
Requirements
๐ฆ Installation
Require the package via Composer:, (*12)
composer require codezero/laravel-unique-translation
Laravel will automatically register the ServiceProvider., (*13)
๐ Usage
For the following examples, I will use a slug
in a posts
table as the subject of our validation., (*14)
โ๏ธ Validate a Single Translation
Your form can submit a single slug:, (*15)
<input name="slug">
We can then check if it is unique in the current locale:, (*16)
$attributes = request()->validate([
'slug' => 'required|unique_translation:posts',
]);
You could also use the Rule instance:, (*17)
use CodeZero\UniqueTranslation\UniqueTranslationRule;
$attributes = request()->validate([
'slug' => ['required', UniqueTranslationRule::for('posts')],
]);
โ๏ธ Validate an Array of Translations
Your form can also submit an array of slugs., (*18)
<input name="slug[en]">
<input name="slug[nl]">
We need to validate the entire array in this case. Mind the slug.*
key., (*19)
$attributes = request()->validate([
'slug.*' => 'unique_translation:posts',
// or...
'slug.*' => UniqueTranslationRule::for('posts'),
]);
โ๏ธ Specify a Column
Maybe your form field has a name of post_slug
and your database field slug
:, (*20)
$attributes = request()->validate([
'post_slug.*' => 'unique_translation:posts,slug',
// or...
'post_slug.*' => UniqueTranslationRule::for('posts', 'slug'),
]);
โ๏ธ Specify a Database Connection
If you are using multiple database connections, you can specify which one to use by prepending it to the table name, separated by a dot:, (*21)
$attributes = request()->validate([
'slug.*' => 'unique_translation:db_connection.posts',
// or...
'slug.*' => UniqueTranslationRule::for('db_connection.posts'),
]);
โ๏ธ Ignore a Record with ID
If you're updating a record, you may want to ignore the post itself from the unique check., (*22)
$attributes = request()->validate([
'slug.*' => "unique_translation:posts,slug,{$post->id}",
// or...
'slug.*' => UniqueTranslationRule::for('posts')->ignore($post->id),
]);
โ๏ธ Ignore Records with a Specific Column and Value
If your ID column has a different name, or you just want to use another column:, (*23)
$attributes = request()->validate([
'slug.*' => 'unique_translation:posts,slug,ignore_value,ignore_column',
// or...
'slug.*' => UniqueTranslationRule::for('posts')->ignore('ignore_value', 'ignore_column'),
]);
โ๏ธ Use Additional Where Clauses
You can add 4 types of where clauses to the rule., (*24)
where
$attributes = request()->validate([
'slug.*' => "unique_translation:posts,slug,null,null,column,value",
// or...
'slug.*' => UniqueTranslationRule::for('posts')->where('column', 'value'),
]);
whereNot
$attributes = request()->validate([
'slug.*' => "unique_translation:posts,slug,null,null,column,!value",
// or...
'slug.*' => UniqueTranslationRule::for('posts')->whereNot('column', 'value'),
]);
whereNull
$attributes = request()->validate([
'slug.*' => "unique_translation:posts,slug,null,null,column,NULL",
// or...
'slug.*' => UniqueTranslationRule::for('posts')->whereNull('column'),
]);
whereNotNull
$attributes = request()->validate([
'slug.*' => "unique_translation:posts,slug,null,null,column,NOT_NULL",
// or...
'slug.*' => UniqueTranslationRule::for('posts')->whereNotNull('column'),
]);
โ๏ธ Laravel Nova
If you are using Laravel Nova in combination with spatie/nova-translatable
, then you can add the validation rule like this:, (*25)
Text::make(__('Slug'), 'slug')
->creationRules('unique_translation:posts,slug')
->updateRules('unique_translation:posts,slug,{{resourceId}}');
โ๏ธ Filament
If you are using Filament in combination with filamentphp/spatie-laravel-translatable-plugin
, then you can add the validation rule like this:, (*26)
TextInput::make('slug')
->title(__('Slug'))
->rules([
UniqueTranslationRule::for('posts', 'slug')
])
TextInput::make('slug')
->title(__('Slug'))
->rules([
fn (Get $get) => UniqueTranslationRule::for('posts', 'slug')->ignore($get('id'))
])
๐ฅ Example
Your existing slug
column (JSON) in a posts
table:, (*27)
{
"en":"not-abc",
"nl":"abc"
}
Your form input to create a new record:, (*28)
<input name="slug[en]" value="abc">
<input name="slug[nl]" value="abc">
Your validation logic:, (*29)
$attributes = request()->validate([
'slug.*' => 'unique_translation:posts',
]);
The result is that slug[en]
is valid, since the only en
value in the database is not-abc
., (*30)
And slug[nl]
would fail, because there already is a nl
value of abc
., (*31)
โ ๏ธ Error Messages
You can pass your own error messages as normal., (*32)
When validating a single form field:, (*33)
<input name="slug">
$attributes = request()->validate([
'slug' => 'unique_translation:posts',
], [
'slug.unique_translation' => 'Your custom :attribute error.',
]);
In your view you can then get the error with $errors->first('slug')
., (*34)
Or when validation an array:, (*35)
<input name="slug[en]">
$attributes = request()->validate([
'slug.*' => 'unique_translation:posts',
], [
'slug.*.unique_translation' => 'Your custom :attribute error.',
]);
In your view you can then get the error with $errors->first('slug.en')
(en
being your array key)., (*36)
๐ง Testing
vendor/bin/phpunit
โ๏ธ Credits
๐ Security
If you discover any security related issues, please e-mail me instead of using the issue tracker., (*37)
๐ Changelog
A complete list of all notable changes to this package can be found on the
releases page., (*38)
๐ License
The MIT License (MIT). Please see License File for more information., (*39)