1

I've got a User model that hasOne Membership model, with a users table and a memberships table (each entry in the memberships table has a foreign key linked to a user_id).

I've made a registration page that lets the user have a 7 days trial period on the membership but I'm having trouble storing the data.

This is the dd() of the data in the registration form:

"_token" => "ckRlMligEyTwu7ssOi4TmesycbsPpVQlrJ4jQaBd"
"username" => "JaneDoe"
"password" => "password"
"password_confirmation" => "password"
"expiration" => "2021-04-30"

Now in my controller I've got the following store() method:

public function store(Request $request) {
    // validating
    $this->validate($request, [
        'username' => ['required', 'max:200'],
        'password' => 'required|confirmed',
        'expiration' => 'required'
    ]);
    
    // storing
    User::create([
        'username' => $request->username,
        'password' => Hash::make($request->password),
        'expiration' => $request->expiration
    ]);
}

This won't store anything in the memberships table and I have no idea how to correctly write the store method using the Model's Eloquent Relationships declared.

Thanks for the help.

EDIT: While trying to make some sense i've modified the store() function, now looks like this:

public function store(Request $request) {
    // validating
    $this->validate($request, [
        'username' => ['required', 'max:200'],
        'password' => 'required|confirmed',
        'expiration' => 'required'
    ]);
    
    // storing
    User::create([
        'username' => $request->username,
        'password' => Hash::make($request->password)
    ])->membership(Membership::create([
        'expiration' => $request->expiration
    ]));
}

Now seems like Laravel doesn't know where to get the user_id of the newly created user, like the error suggests: SQLSTATE[HY000]: General error: 1364 Field 'user_id' doesn't have a default value (SQL: insert into `memberships` (`expiration`, `updated_at`, `created_at`)

1 Answers1

2

Your solution is to do:

User::create([
    'username' => $request->username,
    'password' => Hash::make($request->password)
])->membership()->create([
    'expiration' => $request->expiration
]);

Using the relation (membership() not membership as an attribute) will already know the relation key (user_id in this case).

You can see more info about this in the documentation.


Other way of doing same is:

$membership = new Membership([
    'expiration' => $request->expiration
]);

User::create([
    'username' => $request->username,
    'password' => Hash::make($request->password)
])->membership()->save($membership);

More info about save() on the documentation.

matiaslauriti
  • 7,065
  • 4
  • 31
  • 43
  • 1
    I was just writing the answer to my own question and saw the notification. Thank you, i'll take this as a confirmation of a proper way to do it. Hope this helps others – Emmanuele D'Ettorre Apr 23 '21 at 19:22
  • 1
    No problem !!! For anyone seen this, remember you can do the inverse of this (`membership -> user` instead of `user -> membership`) but using other methods, look at the documentation I've shared, the next 2 items is doing the same but for the inverse of the relation (it does not use same methods). – matiaslauriti Apr 23 '21 at 19:28