Astrotomic / laravel-translatable

A Laravel package for multilingual models
https://docs.astrotomic.info/laravel-translatable/
MIT License
1.25k stars 157 forks source link

Translations not created while calling all seeders (but created if calling only this class) #277

Closed Pomstiborius closed 2 years ago

Pomstiborius commented 2 years ago

Describe the bug I created a seeder with example translations for Page model. After running php artisan migrate:fresh --seed or php artisan db:seed page is created but no translations are saved to the database. I need to run php artisan db:seed --class=PageSeeder (this class is called in DatabaseSeeder) to have not only page, but also translations present. Running the same code inside controller also creates new page with translations, the only problem is with mass seeding.

To Reproduce Create PageSeeder class and fill in any translations. Call this seeder inside DatabaseSeeder.

Expected behavior Page should be created and all translations should be saved. Right now page is created but with no translations.

Versions (please complete the following information)

Pomstiborius commented 2 years ago

@Gummibeer Did you have any question that you forgot to post?

Gummibeer commented 2 years ago

No, but it is a question and not a bug and I don't have time for it right now. It's 99% a usage problem. If you would post the seeder code I could potentially check it.

Pomstiborius commented 2 years ago

I believe it's a bug since the same piece of code behaves properly when run from the controller or seeder for the second time and not for the first time. Seeders and migrations are pretty basic, I'm posting them down below.

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('pages', static function (Blueprint $table) {
            $table->id();
            $table->timestamps();
            $table->softDeletes();
        });

        Schema::create('page_translations', static function (Blueprint $table) {
            $table->id();
            $table->foreignId('page_id')->nullable()->constrained()->cascadeOnUpdate()->nullOnDelete();
            $table->string('locale_code', 25)->nullable();
            $table->string('slug', 250);
            $table->string('title', 250);
            $table->string('summary', 1000)->nullable();
            $table->mediumText('content');
            $table->timestamp('published_at')->nullable();

            $table->unique(['page_id', 'locale_code']);
            $table->unique(['locale_code', 'slug']);
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('page_translations');
        Schema::dropIfExists('pages');
    }
};
<?php

namespace Database\Seeders;

use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    use WithoutModelEvents;

    public function run(): void
    {
        $this->call([
            PageSeeder::class,
        ]);
    }
}
<?php

namespace Database\Seeders;

use App\Models\Page;
use Illuminate\Database\Seeder;

class PageSeeder extends Seeder
{
    public function run(): void
    {
        $page = new Page();
        $page->fill([
            'en' => [
                'slug' => 'about-us',
                'title' => 'About us',
                'content' => 'This page will be about us',
            ],
            'pl' => [
                'slug' => 'o-nas',
                'title' => 'O nas',
                'content' => 'Ta strona będzie o nas',
            ],
        ]);
        $page->save();
    }
}

$translatedAttributes is filled in properly, just like locale_key and locales inside config file.

Gummibeer commented 2 years ago

use WithoutModelEvents; that one is your issue - it prevents saving the translations automatically. https://github.com/Astrotomic/laravel-translatable/blob/6f2e3855836d46ab7ad3dabd269a400404f8b42c/src/Translatable/Translatable.php#L34-L37 In case you need that trait you can will have to call $page->saveTranslations(); after the $page->save(); on your own. Keep in mind that it's a protected method. https://github.com/Astrotomic/laravel-translatable/blob/6f2e3855836d46ab7ad3dabd269a400404f8b42c/src/Translatable/Translatable.php#L362-L382

Alternatively you could try \Illuminate\Database\Eloquent\Model::push() instead of save() but I'm not sure if that will work properly.

Pomstiborius commented 2 years ago

You are right, removing WithoutModelEvents worked. I didn't think of that because it all worked ok on second seeders run which is so weird. And using push() instead of save() also works with that trait enabled. Thank you for your help!