0
votes

I'm trying to connect users table with user_info. I've found some posts about it and it works, but I've troubles with user_info->id autoincrement.

If I set it to: $table->increments('id');

I'm getting error that no default value is set, it works only if I add $table->integer('id')->nullable($value = true);

Here is what I got for now:

User model

public function userinfo()
{
    return $this->hasOne('App\Userinfo');
}

Userinfo model

public function user()
{
    return $this->belongsTo('App\User');
}

Migration/table structure

    public function up()
        {
            Schema::create('user_info', function (Blueprint $table) {
                //There is a problem, if I don't add user_id it says that user_id doesnt exists, so I created user_id and decided to set id to autoincrement but it doesnt works so I made it like that 
                $table->integer('id')->nullable($value = true);
                $table->foreign('id')->references('id')->on('users');
                $table->integer('user_id');

$table->string('avatar',255)->default('notset.jpg')->nullable($value = true);
                $table->string('looking_for',255)->nullable($value = true);
                $table->string('steam_nick',40)->nullable($value = true);
                $table->integer('age')->length(3)->nullable($value = true);
                $table->integer('isFriendly')->length(2)->nullable($value = true);
                $table->integer('isToxic')->length(2)->nullable($value = true);
                $table->integer('isLeader')->length(2)->nullable($value = true);
                $table->integer('isFunny')->length(2)->nullable($value = true);
                $table->integer('isSkilled')->length(2)->nullable($value = true);
                $table->text('description')->nullable($value = true);
                $table->timestamps();
            });
        }

Finally UserinfoController

 public function update(Request $request, $id)
 {
      $user = User::findOrFail($id); //Get role specified by id


       $this->validate($request, [
           'steam_nick'=>'max:120',
           'looking_for'=>'required',
           'avatar'=>'',
           'description'=>'max:450',
           'age'=>'min:2'
       ]);
       $input = $request->only(['steam_nick', 'looking_for', 'description','avatar','age']); //Retreive the name, email and password fields

       $userinfo = new Userinfo();
       if ($userinfo->user_id == null ) {
           $userinfo->steam_nick = $request->steam_nick;
           $userinfo->looking_for = $request->looking_for;
           $userinfo->description = $request->description;
           $userinfo->avatar = $request->avatar;
           $userinfo->age = $request->age;
           $user->Userinfo()->save($userinfo);
       } else {
           $user->Userinfo()->update($input);
       }

    }

Phpmyadmin img

All I need is to set id in user_info same as id in users. I don't need user_id, but couldn't make it works other way, but I'm sure it's wrong.

1

1 Answers

0
votes

Okay, let's break it down piece by piece.

First, what I like to do is specifically declare what my table column is as the second argument on any hasOne and belongsTo in a model. It's not strictly necessary since Laravel does some voodoo magic to guess what the table name is - but I recommend it because it makes the relationship very clear. So, I would do this on the user model:

public function userinfo()
{
    return $this->hasOne('App\Userinfo', 'user_id'); // it references user_id on your user_info table.
}

Next, let's look at your user_info migration. You were having problems with your primary key id because you were trying to set it as integer when it needs to be increments. We'll tweak the first three lines:

$table->increments('id')->unsigned();
$table->integer('user_id');
$table->foreign('user_id')->references('id')->on('users'); // foreign references the user_id field in this table, since that's what's making the connection between users and users_info, we point back to the user's id

At this point, if you are able, I recommend php artisan migrate:fresh --seed. It might help with any weird database structures you have prior. This is optional, though. You can try it if it doesn't work straight away.

Now in the controller, I noticed that you were previously referencing $user->Userinfo()->update($input);, but you named the relationship userinfo() in your user model. This is probably one of the things that was giving you an issue. They must match. Try setting up your controller like so:

public function update(Request $request, $id)
{
    $user = User::findOrFail($id); //Get role specified by id

    $this->validate($request, [
        'steam_nick'=>'max:120',
        'looking_for'=>'required',
        'avatar'=>'',
        'description'=>'max:450',
        'age'=>'min:2'
    ]);

    $input = $request->only(['steam_nick', 'looking_for', 'description','avatar','age']); //Retreive the name, email and password fields

    // Does this user have an info record? If not, create it, else update it.
    if (is_null($user->userinfo)) {
        // Since you already collected the data in the $input variable, we simply array_merge it with the user's id
        Userinfo::create(array_merge([
            'user_id' => $user->id,
        ], $input));
    } else {
        $user->userinfo()->update($input);
    }

    return redirect()->back();
}

So, basically what we are doing is checking to see if the user has a related record in the user_info table. If not, create it with the data. If so, simply update it. Since in our migration we declare that user_id cannot be null, we have to grab the user's id off the $user variable, and you've already grabbed all of the necessary data for the user_info table and put it in the $input variable, we simply array_merge() those two arrays when creating the user's info record.

Otherwise, if the related record already exists, we simply update the user_info record using our relationship ->userinfo().

Try that and let me know how it works.