Reputation: 3234
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, [email protected], 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
.
Upvotes: 1
Views: 17730
Reputation: 111829
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.
Upvotes: 6
Reputation: 146191
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();
Upvotes: 0