3
votes

I have a collection of tables like so:

logbook, responsibility, user

Responsibilities are reused - but only one distinct responsibility per logbook. Each responsibility has one user. A user can have multiple responsibilities (on multiple logbooks). I have a table to join these together:

logbook_responsibility, with three colummns (each making up the primary key) - logbook_id, responsibility_id and user_id, which are all foreign keys. In my schema.xml this table is set isCrossRef="true".

When updating a responsibility to a new user, I am passed in an array in $_POST in the form of $_POST['responsibility'][2] = 5, $_POST['responsibility'][7] = 2, etc. I have a function that is supposed to update them:

public function updateResponsibilities($options = null)
{
  foreach ($options['responsibility'] as $k => $v) {      
    $user = UserQuery::create()
      ->filterByLogbook($this->logbook)
      ->findOneById($v);

    $logbookResponsibility = LogbookResponsibilityQuery::create()
      ->filterByLogbook($this->logbook)
      ->filterByResponsibilityId($k)
      ->findOne();

    if (is_null($user) || is_null($logbookResponsibility)) {
      break;
    }

    $logbookResponsibility->setUser($user)->save();
  }

  return true;
}

Here I loop through the options, create a new user with the supplied ID, filter by the current logbook to make sure they're allowed to be responsible for this logbook, and grab the first one. This works fine (dumped with ->toArray():

array(11) {
  ["Id"]=>
  int(2)
  ["CompanyId"]=>
  int(1)
  ["CurrentLogbookId"]=>
  int(1)
  ["OtherFieldsHere..."]=>
  // etc, etc

}

Next I grab a LogbookResponsibility, filtering again by the current logbook and the responsibility ID. At this stage the new user ID is shown correctly:

array(3) {
  ["LogbookId"]=>
  int(1)
  ["ResponsibilityId"]=>
  int(1)
  ["UserId"]=>
  int(1)
}

I then update this object with the previously grabbed user, and save. I get no errors doing this, and inspecting the object afterwards shows that the object, at least, has updated:

array(3) {
  ["LogbookId"]=>
  int(1)
  ["ResponsibilityId"]=>
  int(1)
  ["UserId"]=>
  int(2)
}

But, without touching anything else, looking at the database after, the user ID is still 1. I've tested running a query like:

UPDATE logbook_responsibility SET user_id = 1 WHERE logbook_id = 1 AND responsibility_id = 1;

...which works without error.

My actual question is two-fold:

1) Why isn't it saving? (Is it to do with my cross ref table? Is there a problem with cross ref tables with more than 2 columns?)

2) Is there generally a better way to achieve my setup? *(I tried achieving the same with a responsibility object, but didn't see a way to update the logbook_responsibility from there)*

Happy to take suggestions as well as an actual answer!

1
You could check the last query run using Propel::getConnection()->getLastExecutedQuery();, that might point you in the right directionbillyonecan

1 Answers

3
votes

As suggested in the comments I used getLastExecutedQuery() to get hold of the actual query run when I run the save() method, and this is the query being run (also explaining why there was no error):

UPDATE `logbook_responsibility` SET `USER_ID`=3 WHERE
  logbook_responsibility.LOGBOOK_ID=1 AND
  logbook_responsibility.RESPONSIBILITY_ID=1 AND
  logbook_responsibility.USER_ID=3;

As you can see, the update statement is syntactically correct, but the problem seems to lie in how Propel updates primary keys - which leads me to wonder why I have my user id column as part of the primary key?

It didn't make sense to have the user as part of the primary key, so I removed it, and of course that made it work. There does still remain the real question, "How do I update primary keys in Propel?", but that's better left to somebody else to explain.

I'll be happy to un-mark this as the answer if someone has a better explanation.