1

I'm not able to generate slug when seeding database. I'm creating an e-commerce website course, learning Laravel as a beginner.

But no error about slug is provided. What should I do? Slug is not inserted into database when slug column is not nullable. When I made slug collumn nullable, it remains empty. Laravel-sluggable installed.

This is the error I get:

SQLSTATE[HY000]: General error: 1364 Field 'slug' doesn't have a default value (Connection: mysql, SQL: insert into products (title, image, description, price, created_at, updated_at, created_by, updated_by) values (Accusantium enim sapiente reprehenderit.

Product.php:

<?php  
namespace App\Models;  
  
use Illuminate\Database\Eloquent\Factories\HasFactory;  
use Illuminate\Database\Eloquent\Model;  
use Illuminate\Database\Eloquent\SoftDeletes;  
use Spatie\Sluggable\HasSlug;  
use Spatie\Sluggable\SlugOptions;  
use Illuminate\Support\Facades\Log;  
  
class Product extends Model  
{  
    use HasFactory;  
    use HasSlug;  
    use SoftDeletes;  
  
    public function getSlugOptions(): SlugOptions  
    {  
        Log::info('Generating slug for product: ' . ($this->title));  
        return SlugOptions::create()  
            ->generateSlugsFrom('title')  
            ->saveSlugsTo('slug');  
    }  
}  

ProductFactory.php:

<?php  
  
namespace Database\Factories;  
use Illuminate\Database\Eloquent\Factories\Factory;  
use Illuminate\Support\Facades\Log;  
  
/**  
 * @extends \Illuminate\Database\Eloquent\Factories\Factory\<\App\Models\Product\>  
 */  
class ProductFactory extends Factory  
{  
    /**  
     * Define the model's default state.  
     *  
     * @return array<string, mixed>  
     */  
    public function definition(): array  
    {  
        Log::info('Generating fake product data');  
        return [  
            'title' => fake()->text(20),  
            'image' => fake()->imageUrl(),  
            'description' => fake()->realText(2000),  
            'price' => fake()->randomFloat(2, 2, 5),  
            'created_at' => now(),  
            'updated_at' => now(),  
            'created_by' => 1,  
            'updated_by' => 1,  
        ];  
    }  
}  

ProductSeeder.php:

<?php    
  
namespace Database\Seeders;  
use App\Models\Product;  
use Illuminate\Database\Console\Seeds\WithoutModelEvents;  
use Illuminate\Database\Seeder;  
use Illuminate\Support\Facades\Log;  
  
class ProductSeeder extends Seeder  
{  
    /**  
     * Run the database seeds.  
     */  
    public function run(): void  
    {  
        Log::info('Seeding products table with fake data');  
        Product::factory(50)->create();  
    }  
}  

laravel.log (nothing logged from Product.php)

[2025-11-19 14:16:48] local.INFO: Seeding products table with fake data    
[2025-11-19 14:16:48] local.INFO: Generating fake product data  

...and 49 other rows of Generating fake product data

2025_10_20_194742_create_products_table.php:

<?php  
  
use App\Models\User;  
use Illuminate\Database\Migrations\Migration;  
use Illuminate\Database\Schema\Blueprint;  
use Illuminate\Support\Facades\Schema;  
  
return new class extends Migration  
{  
    /**  
     * Run the migrations.  
     */  
    public function up(): void  
    {  
        Schema::create('products', function (Blueprint $table) {  
            $table->id();  
            $table->string('title', 2000);  
            $table->string('slug', 2000)->nullable(); // I tried not nullable too.  
            $table->string('image', 2000)->nullable();  
            $table->string('image_mime')->nullable();  
            $table->integer('image_size')->nullable();  
            $table->longText('description')->nullable();  
            $table->decimal('price', 10, 2);  
            $table->foreignIdFor(User::class, 'created_by')->nullable();  
            $table->foreignIdFor(User::class, 'updated_by')->nullable();  
            $table->softDeletes();  
            $table->foreignIdFor(User::class, 'deleted_by')->nullable();  
            $table->timestamps();  
        });  
    }  
  
    /**  
     * Reverse the migrations.  
     */  
    public function down(): void  
    {  
        Schema::dropIfExists('products');  
    }  
};
4
  • I don't use this library, but is it possible that slug must be fillable ? laravel.com/docs/12.x/eloquent#mass-assignment Commented Nov 22 at 12:41
  • I tried protected $fillable, also protected $guarded = empty array. Did not work. It's strange that I didn't see any error. Commented Nov 22 at 17:38
  • 1
    Have you tried outside the factories? They sometimes behave strangely. We would need to examine the exact code to determine whether the event creating is sent during the mass creation by the factory. Commented Nov 23 at 18:10
  • It's for learning purposes, so yes. I can share whole project: github.com/krajcovict/ecommerce/blob/… Looks like nobody has this problem except me, so I think it's some rookie mistake. (I tried also fillable and guarded, but same results.) Commented Nov 24 at 13:30

2 Answers 2

4

Remove WithoutModelEvents trait in your DatabaseSeeder class will fix your issue.

This trait prevents Eloquent events from firing, preventing HasSlug trait's to execute the slug generation.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. This solved my problem. (Looks obvious now.)
0

protected $guarded = [];
do this and then try again

New contributor
Md Saifullah is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

2 Comments

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
Thank you for your comment. Clément Baconnier posted correct solution. Just for the record, I tried protected $guarded = []; , but later found out it's not necessary to solve my problem. Problem was caused by WithoutModelEvents trait in my DatabaseSeeder function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.