Create Many-to-Many Association with Idiorm/Paris
As simple as this really turned out to be, I struggled with this a bit as it isn't explicitly discussed in the docs (http://paris.readthedocs.org/en/latest/associations.html#has-many-through).
The idea is that you have two Models with a has_many_through
relationship and an intermediate Model to manage that relationship.
A little DB magic to get things hooked up:
CREATE TABLE IF NOT EXISTS `Addresses` (
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `Users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`),
KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
CREATE TABLE IF NOT EXISTS `AddressUser` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`Addresses_id` int(11) NOT NULL,
`Users_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`),
KEY `Addresses_id` (`Addresses_id`),
KEY `Users_id` (`Users_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
ALTER TABLE `AddressUser`
ADD CONSTRAINT `AddressUser_ibfk_3` FOREIGN KEY (`Users_id`) REFERENCES `Users` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
ADD CONSTRAINT `AddressUser_ibfk_4` FOREIGN KEY (`Addresses_id`) REFERENCES `Addresses` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION;
The main models:
// One side of the relationship
class User extends \Model {
public static $_table = 'Users';
public function addresses() {
return $this->has_many_through('Address');
}
}
// Another side of the relationship
class Address extends \Model {
public static $_table = 'Addresses';
public function users() {
return $this->has_many_through('User');
}
}
// Intermediate model for managing the relationship
class AddressUser extends \Model {
public static $_table = 'AddressUser';
}
Then to create an association or link two of the main Models together:
$address_user = \Model::factory('AddressUser')->create();
$address = \Model::factory('Address')->find_one($address_id);
$user = \Model::factory('User')->find_one($user_id);
// Just to make sure these entities actually exist in the db
if ($address && $user) {
$address_user->addresses_id = $address->id;
$address_user->users_id = $user->id;
$address_user->save();
}
At this point you should be able to create new rows in the AddressUser
table that link up with the correct models in the respective Addresses
and Users
tables.
Written by Matt Ross
Related protips
3 Responses
Matt, this is great!
It's really helped me out and got me through a problem I didn't know how to solve.
I suspect one could override the save() method of both User and Address to ensure a valid UserAddress is saved for each relationship as well.
You're right too, this should be included in the documentation :)
I am sure it is just because I am too close to the project, but I can't really see what is missing from the docs here so please could you report this explicitly as an issue or better yet a pull request on the project so that the documentation can be improved.
What about delete the relationship between the user and their addresses? How you do it?