skip to Main Content

I have a ‘projects’ table in my Laravel project. The migration looks something like this:

        Schema::create('projects', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('key')->nullable();
            $table->integer('bpm')->nullable();
            $table->boolean('is_collaborative')->default(false);
            $table->foreignId('owner_id')->constrained('users')->cascadeOnDelete();
            $table->timestamps();
        });

I want the owner_id field to reference a user’s id in order to know who the owner of the project is (since projects will be collaborative and multiple users will have access to them).

After creating the following method on my Project model:

public function owner(): BelongsTo
    {
        return $this->belongsTo(User::class, 'owner_id');
    }

And the following method on my User model:

public function projectsOwned(): HasMany
    {
        return $this->hasMany(Project::class, 'owner_id');
    }

I implemented the store function on my ProjectController:

public function store(Request $request)
    {
        // Validate the data input by the user.
        $validatedData = $request->validate([
            'title' => ['required', 'max:255'],
        ]);

        // Create a new project.
        auth()->user()->projects()->create($validatedData);

        return to_route('projects.index')->with('status', __('Project created successfully!'));
    }

The thing is, this function will throw the following exception:
General error: 1364 Field 'owner_id' doesn't have a default value when executed.

What can I do to make Laravel automatically insert the authenticated user’s id into the owner_id field without having to add owner_id to the $fillable array of the Project model?

PS: I also have a many-to-many relationship between users and projects to keep track of who has access to which projects. That’s why I use the auth()->user()->projects() method when trying to store a new project in the database.

2

Answers


  1. Laravel has conventions that you would need to follow to get this to work. Even though you are using owner_id I don’t see an owners table, it is looking for user_id on the users table. You’re also calling in your store function:

    auth()->user()->projects()->create($validatedData);
    

    This is also looking for the auth user’s id and auth is only associated with the authenticated user, not any other model.

    If you really need and owner_id field, you can create an owners table and reference your user on that before you can reference it on the projects table from the owners. Then on your store functions you can find the owner by id and then store but also since this isn’t authenticated from the user model you’ll have to either make sure owner_id is in your fillable properties on your models or you can use guarded instead(I never recommend guarded when you’re learning).

    Keep in mind, migrations need to be in order so have your main migrations listed before your relations tables. Users, then owners, then projects.

    Login or Signup to reply.
  2. You should use the projectsOwned() relationship you defined in your User model. This one-to-many relationship will automatically handle the owner_id foreign key.

    public function store(Request $request)
    {
        // Validate the data input by the user.
        $validatedData = $request->validate([
            'title' => ['required', 'max:255'],
        ]);
    
        // Create a new project.
        auth()->user()->projectsOwned()->create($validatedData);
    
        return redirect()->route('projects.index')->with('status', __('Project created successfully!'));
    }
    

    In this modified method, we use auth()->user()->projectsOwned()->create($validatedData); instead of auth()->user()->projects()->create($validatedData);. This will automatically set the owner_id field to the authenticated user’s ID.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search