Extra Table - xalaida/laravel-translatable GitHub Wiki
With this strategy, the translatable model table does not physically contain fields for translatable attributes. They are stored separately in a special table for translations. However, the model can work with them as it would with regular model attributes.
The following picture shows the database schema of this strategy. Columns that contain actual translations are highlighted in blue.
Set up
Let's make, for example, a translatable Book
model that has 2 translatable attributes: title
and description
.
The model class may look like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Nevadskiy\Translatable\Strategies\ExtraTable\HasTranslations;
class Book extends Model
{
use HasTranslations;
protected $translatable = [
'title',
'description',
];
}
And we need 2 tables: books
and book_translations
.
The simplest books
table migration might look like this:
Schema::create('books', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
The book_translations
table should contain the title
and description
fields:
Schema::create('book_translations', function (Blueprint $table) {
$table->id();
$table->foreignId('book_id')->references('id')->on('books');
$table->string('locale', 2);
$table->string('title');
$table->text('description');
$table->timestamps();
$table->unique(['book_id', 'locale']);
});
That's all. The model is now ready to work with translations.
Configuration
Custom foreign key
By default, the foreign key is determined automatically by the model name.
For example, if the model is named Book
, the strategy expects the foreign key to be book_id
.
If you want to use another foreign key, you can do so by overriding the getEntityTranslationForeignKey
method in the model as follows:
<?php
namespace App;
use App\BookTranslation;
use Illuminate\Database\Eloquent\Model;
use Nevadskiy\Translatable\Strategies\ExtraTable\HasTranslations;
class Book extends Model
{
use HasTranslations;
public function getEntityTranslationForeignKey(): string
{
return 'entity_id';
}
}
Custom table name
The name of the table for translations is also determined from the model name.
For the Book
model, the strategy expects the name book_translations
for the table for translations.
To use a custom table name, you must override the getEntityTranslationTable
method in the model as follows:
<?php
namespace App;
use App\BookTranslation;
use Illuminate\Database\Eloquent\Model;
use Nevadskiy\Translatable\Strategies\ExtraTable\HasTranslations;
class Book extends Model
{
use HasTranslations;
protected function getEntityTranslationTable(): string
{
return 'book_entity_translations';
}
}
Custom translation model
By default, you do not need to create a separate model to work with the translation table.
The strategy uses one Translation
model internally and dynamically sets the name of the table into it.
But if for some reason you need to create a custom translation model, then you can specify it by overriding the getTranslationModelClass
method:
<?php
namespace App;
use App\BookTranslation;
use Illuminate\Database\Eloquent\Model;
use Nevadskiy\Translatable\Strategies\ExtraTable\HasTranslations;
class Book extends Model
{
use HasTranslations;
public function getTranslationModelClass() : string
{
return BookTranslation::class;
}
}
Note that all casts, accessors, mutators and everything related to translatable attributes must only be declared once in the original entity model, not in the translation model.
Custom global translation model
You can also specify one global model for the extra table strategy globally in the App\Providers\AppServiceProvider
class:
use Nevadskiy\Translatable\Strategies\ExtraTable\ExtraTableStrategy;
use App\Translation;
public function boot()
{
ExtraTableStrategy::useModel(Translation::class);
}
For this model, you do not need to specify a concrete table name, because the strategy will dynamically substitute its table name for each translated model on the fly.