教义 1.2 保存记录关系 UPDATE 而不是 INSERT
我试图级联保存一些用户:
$user = new User();
$user->name = 'xxx';
$user->location->id = 1;
$user->location->name = 'yyy';
$user->save;
$user2 = new User();
$user2->name = 'zzz';
$user2->location->id = 1;
$user2->location->name = 'yyy';
$user2->location->zip = '123456';
$user2->save;
在这种情况下,我希望 Doctrine 足够聪明并更新位置 1,因为我正在更改 id 1 的内容,但我拥有的是另一个插入。 我尝试在 User 中使用 preSave() 方法来解决问题:
public function preSave( Doctrine_Event $event )
{
$invoker = $event->getInvoker();
if ( /...decide to UPDATE the record .../ )
{
$invoker->state( Doctrine_Record::STATE_DIRTY );
}
else
{
$invoker->state( Doctrine_Record::STATE_CLEAN );
}
}
但是当 Doctrine 尝试 UPDATE 时,它没有标识符并产生此错误:
Doctrine_Connection_Mysql_Exception: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
难道这不是 Doctrine 应该提供的开箱即用的东西吗?我在这里错过了什么吗?为什么我需要手动实现此行为?
进一步说明
我们有 3 种情况决定记录是否应插入、更新或简单相关:
1
- 我们的数据库的全新用户 - 应插入
- 我们的数据库的全新位置 - 应插入
2
- 我们的数据库的全新用户 - 应插入应该插入
- 现有位置 - 应该链接到用户记录
3
- 我们的数据库中的全新用户 - 应该插入
- 现有位置 ID,更新的数据 - 应该更新并链接到用户记录
我们需要找到最有效的方法来做到这一点。显然我们可以在 preSave() 等中进行大量选择,我们只需要充分利用 Doctrine
I am trying to save in cascade some users:
$user = new User();
$user->name = 'xxx';
$user->location->id = 1;
$user->location->name = 'yyy';
$user->save;
$user2 = new User();
$user2->name = 'zzz';
$user2->location->id = 1;
$user2->location->name = 'yyy';
$user2->location->zip = '123456';
$user2->save;
In this situation I wish Doctrine to be smart enough and update the location 1 since I am changing the content for the id 1, but what I have instead is another insert.
I tried to workaround using a preSave() method inside User:
public function preSave( Doctrine_Event $event )
{
$invoker = $event->getInvoker();
if ( /...decide to UPDATE the record .../ )
{
$invoker->state( Doctrine_Record::STATE_DIRTY );
}
else
{
$invoker->state( Doctrine_Record::STATE_CLEAN );
}
}
but when doctrine tries to UPDATE it doesn't have identifier and produces this error:
Doctrine_Connection_Mysql_Exception: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
Isn't this something that Docrtrine should provide out of the box? Am I missing something here? Why do I need to implement this behavior by hand?
Further Notes
We have 3 cases that dictate whether the record should be inserted, updated, or simply related:
1
- Brand new user to our database - should be inserted
- Brand new location to our database - should be inserted
2
- Brand new user to our database - should be inserted
- Existing location - should be linked to user record
3
- Brand new user to our database - should be inserted
- Existing location id, updated data - should be updated and linked to user record
We need to find the most efficient way to do this. Obviously we can do a multitude of selects in preSave() etc, we just need to get the most out of Doctrine
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
通常我会这样做:
一般来说 Doctrine 有很多方便的处理关系的方法,正确使用哪种方法取决于你的具体需要。例如,您应该指定如何构建位置对象、同一代码中有多少个用户实例、是否有位置 ID 或位置数据等等。
对于rails中的第1,2和3点,我将使用find_or_create_by方法,该方法在Doctrine中不可用,但您始终可以自己编写它。因此,如果您有 LocationTable 类,您可以执行以下操作:
不要将 preSave 挂钩用于此类事情,我认为它们应该用于其他用例。
Normally I would do something like this:
Generally speaking Doctrine has a lot of convenient methods to deal with relations, the correct one to use depends on your exact needs. For example you should specify how your location object is built, how many user instances do you have in the same code, if you have a location id or location data and so on.
For point 1,2 and 3 in rails I'd use find_or_create_by method, which is not available in Doctrine, but you can always write it by yourself. So if you have the
LocationTable
class you can do this:Don't use preSave hooks for this kind of things, I think they should be used for other use cases.
也许这个 将帮助
再见!
Maybe this will help
Bye!