我有一组像这样的表:
logbook
,responsibility
,user
责任被重复使用 - 但每个日志只有一个不同的责任。每个职责都有一个用户。用户可以有多个职责(在多个日志上)。我有一张桌子可以将它们加在一起:
logbook_responsibility
,有三个列(每个组成主键) - logbook_id
,responsibility_id
和user_id
,这些都是外键。在我的schema.xml
中,此表格设置为isCrossRef="true"
。
将责任更新为新用户时,我会以$_POST
,$_POST['responsibility'][2] = 5
等形式传递给$_POST['responsibility'][7] = 2
中的数组。我有一个应该是的函数更新它们:
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;
}
在这里,我遍历选项,使用提供的ID创建新用户,按当前日志过滤以确保他们被允许负责此日志,并抓住第一个。这工作正常(转储->toArray()
:
array(11) {
["Id"]=>
int(2)
["CompanyId"]=>
int(1)
["CurrentLogbookId"]=>
int(1)
["OtherFieldsHere..."]=>
// etc, etc
}
接下来,我获取了LogbookResponsibility,再次按当前日志和责任ID进行过滤。在此阶段,新用户ID显示正确:
array(3) {
["LogbookId"]=>
int(1)
["ResponsibilityId"]=>
int(1)
["UserId"]=>
int(1)
}
然后我用之前抓取的用户更新此对象,然后保存。这样做我没有错误,之后检查对象显示该对象至少已更新:
array(3) {
["LogbookId"]=>
int(1)
["ResponsibilityId"]=>
int(1)
["UserId"]=>
int(2)
}
但是,在没有接触任何其他内容的情况下,查看数据库之后,用户ID仍为1.我已经测试过运行如下查询:
UPDATE logbook_responsibility SET user_id = 1 WHERE logbook_id = 1 AND responsibility_id = 1;
......无误地工作。
我的实际问题有两个问题:
1)为什么不节约? (是否与我的交叉引用表有关?是否有超过2列的交叉引用表有问题?)
2)通常有更好的方式来实现我的设置吗? *(我尝试使用责任对象实现相同目标,但没有看到从那里更新logbook_responsibility的方法)*
乐于接受建议和实际答案!
答案 0 :(得分:3)
正如评论中所建议的,当我运行getLastExecutedQuery()
方法时,我使用save()
来获取实际的查询运行,这是正在运行的查询(也解释了为什么没有错误) :
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;
正如您所看到的,update语句在语法上是正确的,但问题似乎在于Propel如何更新主键 - 这让我想知道为什么我的用户ID列作为主键的一部分?
将用户作为主键的一部分是没有意义的,所以我删除了它,当然这使它成功了。仍然存在真正的问题, “如何在Propel中更新主键?” ,但最好留给{{3}解释。
如果有人有更好的解释,我会乐意将此标记为答案。