简体   繁体   中英

Laravel Model relations with foreign key constraints

I'm trying to get foreign key constraints to work in Laravel. But I can't seem to save my models anymore.

My database structure is setup as follows (I've removed unnecessary code):

Schema::create($this->tableName, function(Blueprint $table)
{
    $table->increments('id');

    $table->string('username')->unique();
    $table->string('password', 64);

    $table->integer('address_id')->unsigned();
});

Schema::create($this->tableName, function(Blueprint $table)
{
    $table->increments('id');

    $table->integer('user_id')->unsigned();

    $table->string('name');
    $table->string('surname');

    $table->string('street');
    $table->string('number');
    $table->string('town');
    $table->string('country');
});

So the Address is in a separate table and an Address belongs to a User . The User has an Address .

Next I've created the corresponding models:

Class User extends Model
{
    public function address()
    {
        return $this->hasOne('Address');
    }
}

Class Address extends Model
{
    public function user()
    {
        return $this->belongsTo('User');
    }
}

Now when I try to create a User with an Address and save it I get constraint errors. I've tried it both ways (saving the User first and saving the Address first) but both give an error.

The first idea I had was this:

// Create a new user
$user = new User($data);
$address = new Address($addressData);

$address->user()->associate($user);
$user->push(); // Error here

But this gives the error:

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`eet`.`users`, CONSTRAINT `users_address_id_foreign` FOREIGN KEY (`address_id`) REFERENCES `addresses` (`id`)) (SQL: insert into `users` (`username`, `email`, `password`, `type`, `phone`, `cellphone`, `newsletter_week`, `ip`, `updated_at`, `created_at`) values (adsadsad, validemail@gmail.comx, passWO23dw00, customer, 123123213, 1234567890, 1, ::1, 2014-10-05 19:56:03, 2014-10-05 19:56:03))

So I tried saving the Address first, and then the User like:

$user = new User($data);

$address = new Address($addressData);
$address->save(); // Error here

$address->user()->associate($user);
$user->push();

But then the following error is generated:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'user_id' cannot be null (SQL: insert into `addresses` (`name`, `surname`, `street`, `number`, `town`, `country`, `user_id`) values (Foo, Bar, FooStreet, 200, Townsville, nl, ))

So what is a good way to do this? I could make the field address_id for the User nullable, but is that a good practise? I want a User to always have an Address .

I would start with database design first.

For users table I would use:

$table->increments('id');

$table->string('username')->unique();
$table->string('password', 64);

address_id is not necessary here.

For addresses table I would use:

$table->increments('id');

$table->integer('user_id')->unsigned();

$table->string('name');
$table->string('surname');

$table->string('street');
$table->string('number');
$table->string('town');
$table->string('country');
$table->foreign('user_id')
      ->references('id')
      ->on('users')
      ->onDelete('CASCADE');

You should use foreign key in addresses table and add onDelete('CASCADE`) - now if you remove user, address will be removed automatically. You won't have any orphaned addresses.

Now inserting data:

$user = new User($data);
$user->save();
$address = new Address($addressData);
$user->address()->save($address);

You don't need to put in $addressData any user_id - it will be filled automatically.

At first save the parent model and in this case it's User so:

$user = new User($data);
$user->save();

Then try:

// $addressData ...
$addressData['user_id'] = $user->id;
$address = new Address($addressData);
$address->save();

Or maybe:

$user = new User($data);
$user->address = new Address($addressData);
$user->push();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM