tmkhqg
Last Updated: February 25, 2016
·
2.238K
· amsross
6203b560176e32d97b4d7938b0da826b

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.

Say Thanks
Respond

3 Responses
Add your response

13545
Af020d7b3418a632ad7d5454c4d5a1c3 normal

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 :)

over 1 year ago ·
13546
715a4bd349679b00b4659a3c136d1f3e

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.

over 1 year ago ·
21506
None

What about delete the relationship between the user and their addresses? How you do it?

over 1 year ago ·