dvdfreitas's avatar

Polymorphic connecting the same table

Hi,

I have two models: Text and Sentence that I want to be translatable. So I would like to have a model called Translate that says that the text with id 1, is translated in the text with id 2. The same can happen with sentences: the sentence with id 1 is translated into the sentence with id 2.

I had this working for the sentences:

Schema::create('translations', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('source_id');
            $table->unsignedBigInteger('target_id');            
            $table->unsignedBigInteger('author_id')->nullable();
            $table->timestamps();

            $table->foreign('source_id') ->references('id')->on('sentences');
            $table->foreign('target_id')->references('id')->on('sentences');
            $table->foreign('author_id')->references('id')->on('people');

            $table->unique(['source_id', 'target_id']);
        });

But now I want to do the same for the texts. Can I use polymorphism? How can I do it, if the referred model are the same?

I hope I'm clear enough.

Thanks, David

0 likes
4 replies
LaryAI's avatar
Level 58

Yes, you can use polymorphism to achieve this. In Laravel, you can use the morphTo and morphMany relationships to create a polymorphic relationship between the Translate model and the Text and Sentence models.

First, you need to modify the translations table to include the polymorphic columns. You can do this by adding translatable_type and translatable_id columns to the table:

Schema::create('translations', function (Blueprint $table) {
    $table->id();
    $table->unsignedBigInteger('source_id');
    $table->unsignedBigInteger('target_id');
    $table->unsignedBigInteger('author_id')->nullable();
    $table->unsignedBigInteger('translatable_id');
    $table->string('translatable_type');
    $table->timestamps();

    $table->foreign('source_id')->references('id')->on('sentences');
    $table->foreign('target_id')->references('id')->on('sentences');
    $table->foreign('author_id')->references('id')->on('people');

    $table->unique(['source_id', 'target_id']);
});

Next, you need to update the Translate model to define the polymorphic relationship:

use Illuminate\Database\Eloquent\Model;

class Translate extends Model
{
    public function translatable()
    {
        return $this->morphTo();
    }
}

Then, update the Text and Sentence models to define the inverse of the polymorphic relationship:

use Illuminate\Database\Eloquent\Model;

class Text extends Model
{
    public function translations()
    {
        return $this->morphMany(Translate::class, 'translatable');
    }
}

class Sentence extends Model
{
    public function translations()
    {
        return $this->morphMany(Translate::class, 'translatable');
    }
}

Now, you can use the polymorphic relationship to retrieve translations for both Text and Sentence models. For example, to get all translations for a specific Text model:

$text = Text::find(1);
$translations = $text->translations;

To create a translation for a Text or Sentence model, you can use the create method on the translations relationship:

$text = Text::find(1);
$translation = $text->translations()->create([
    'source_id' => 1,
    'target_id' => 2,
    'author_id' => 1,
]);

Remember to adjust the column names and relationships according to your specific application.

webrobert's avatar

Why not just have a [Lexicon] table then a column for element type. Word. Text. Sentence. Include a language_id en fr etc. and finally a meaning column.

One table. One query. Lexeme::where(‘meaning’, ‘red’)->get() Gives you the sentence in all languages.

Forgive my syntax. On my phone.

dvdfreitas's avatar

Thanks for your reply. If it's a sentece, the sentence will be saved in the database. If it's a text, it will be saved on a file.

bixinon157's avatar

local locksmith service stands out as a shining beacon of excellence. With an unwavering commitment to customer satisfaction and a wealth of experience in the industry, we have established ourselves as the go-to locksmiths in the area. Our team of highly skilled and certified locksmiths is equipped with the latest tools and technology to handle a wide range of lock-related challenges. locksmith near me

Please or to participate in this conversation.