views:

31

answers:

2

Guys,

I have small problem when trying to create many-to-many link in doctrine.

I have simple scenario here: User and Role with many-to-many relationship defined.

$user = new User();
$user->username = 'greg';
$user->save();


$role = new Role();
$role->name = "Administrator";
$role->save();

$role_user = new Role_User();
$role_user->Role = $role;
$role_user->User = $user;
$role_user->save();

Now, I did some experiments and I can save user and role on it's own without any problems. They both have autoincrement ids and it works fine. The problem starts when I want to create relationship with exception saying 'Couldn't get last insert identifier'.

I can't change DB schema and I was not generating it via YAML - I reverse engineered models from existing DB via 'generateModelsFromDb'. This is how this table looks like:

CREATE TABLE  `ofp`.`Role_User` (
   `roles_id` bigint(20) NOT NULL,
   `users_id` bigint(20) NOT NULL,
   KEY `FK8B6B91F429A30245` (`roles_id`),
   KEY `FK8B6B91F429A6266F` (`users_id`),
   CONSTRAINT `FK8B6B91F429A6266F` FOREIGN KEY (`users_id`) REFERENCES `User` (`id`),
   CONSTRAINT `FK8B6B91F429A30245` FOREIGN KEY (`roles_id`) REFERENCES `Role` (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Error I'm getting would suggest there is something wrong with creating primary key identifier to this table, but I'm not sure I need one there (Maybe unique key to eliminate duplicates?).

Does anybody have any clues?

A: 

You shouldn't even use Role_User object directly. Note that it's only a part of your db-schema, not object interface.

$role = new Role();
$role['name'] = 'role name';
$role->name   = 'role name';
$role->setName('role name'); // That won't work unless you're using Doctrine with
                             // Symfony (just notice)
$role->set('name', 'role name');

$user = new User();
$user['username'] = 'username';
$user['Roles'][] = $role;

$user->save();

That should save user object, then role and finally create relationship between them.

Crozin
I simply followed doctrine manual. The aproach you are proposing makes much more sense and is very similar to java-jpa aproach.Classes generated from DB do not expose any methods like addRole or addUser etc. Maybe I'm generating models in a wrong way, but I wouldn't think so, this is how I do it: Doctrine_Core::generateModelsFromDb('../php/models', array('ofp'), array('generateTableClasses' => true));
Greg
I forget that clean Doctrine doesn't support "normal" setters/getters.
Crozin
I think the problem I'm experiencing is actually caused by the fact, that during model generation many-to-many relations have no refClass defined: $this->hasMany('Role_User', array( 'local' => 'id', 'foreign' => 'users_id'));I will investigate it further.
Greg
A: 

Setting refClass is mandatory in many-to-many relationships

Jordi Cabot
Yes, you are right, however if you are working with existing DB and not building models from YAML refactoring does not include refClass in many-to-many relationships, so in this case generated models need to be tweaked in order to work properly - and that in a way answers my question.
Greg