HABTM 数据在 __saveMulti() 期间损坏?

发布于 2024-08-24 00:27:01 字数 2355 浏览 4 评论 0原文

我正在使用 Cake 1.2.6,昨晚我注意到当我提交表单时,HABTM 关系没有被保存。

我在委员会志愿者之间有HABTM关系。 Volunteer 的主键是 UUID,而 Committee 的主键是人类可读的字符串(例如 BOARDOFDIRECTORSFAIRCOMMITTEEFAIRASSSOCIATES 等)。我有一个用于创建/编辑志愿者的表单,该表单包含一个选择框,其选项正是您所期望的,并且填充了从 Cake 的 find( 'list' ) 方法返回的选项。虽然我想不出这有什么重要的原因,但只能为志愿者选择一个委员会(HABTM 是为了满足预期的未来需求)。

初步结果表明,选择 BOARDOFDIRECTORS 选项可以按预期工作,但其他选项则不然。通过核心代码跟踪执行情况将我引导到 Model->__saveMulti() ,其中 第 1393 行,执行此代码:

 $data[$this->hasAndBelongsToMany[$assoc]['foreignKey']] = $id;

如果我在该代码之前转储 $data,则输出为 FAIRASSSOCIATES 。紧接着,它的值为4AIRASSSOCIATES。似乎可以安全地假设这就是未保存关系的原因,但我还没有弄清楚为什么数据在执行过程中此时发生变化。

还有其他人看过这个吗?我错过了一些关键部分吗?据我所知,这在 v1.2.1 中运行良好(我大约一周前升级)。

更新

我看到的第一个明显奇怪之处是,虽然我的 $row 是一个字符串,但 第 1366 行 计算结果为 true所以我进入了那个代码块。如果我的数据是一个字符串,它怎么会有成员值?

更新

我显然有一些思考要做,但这是底线。如果我在 之前和之后立即删除日志写入第 1394 行 如下:

$this->log( 'Setting ' . $data . '[' . $this->hasAndBelongsToMany[$assoc]['foreignKey'] . '] = ' . $id, LOG_DEBUG );

$data[$this->hasAndBelongsToMany[$assoc]['foreignKey']] = $id;

$this->log( 'Creating ' . json_encode( $data ) . ' on ' . $join, LOG_DEBUG );

相关输出为:

2010-03-05 18:57:08 Debug: Setting FAIRASSOCIATES[volunteer_id] = 4b78717f-8ad4-4671-b81c-4e8745591fb4
2010-03-05 18:57:08 Debug: Creating "4AIRASSOCIATES" on CommitteesVolunteer

可能的问题:

  1. 我不确定 Cake 如何/为何尝试在字符串
  2. “FAIRASSSOCIATES”上设置 volunteer_id 成员是以下的 ID一个由志愿者组成的委员会,而不是任何类型的模型,所以我根本不理解 FAIRASSSOCIATES[volunteer_id] 的相关性。
  3. 我不知道 $data 的值是如何或为何被这一行代码转变为 4AIRASSSOCIATES 的。

I'm using Cake 1.2.6 and last night I noticed that a HABTM relationship wasn't being saved when I submit a form.

I have a HABTM relationship between Committee and Volunteer. The primary key for a Volunteer is a UUID while the primary key for a Committee is a human readable string (e.g. BOARDOFDIRECTORS, FAIRCOMMITTEE, FAIRASSOCIATES, etc.). I have a form to create/edit volunteers and that form includes a select box whose options are exactly what you'd expect and are populated with options returned from Cake's find( 'list' ) method. Although I can't think of a reason it would matter, only one committee can be selected for a volunteer (the HABTM is for expected future needs).

Initial results show that selecting the BOARDOFDIRECTORS option works as expected, but the others do not. Tracing the execution through the core code leads me to Model->__saveMulti() where, in Line 1393, this code is executed:

 $data[$this->hasAndBelongsToMany[$assoc]['foreignKey']] = $id;

If I dump $data before that code, the output is FAIRASSOCIATES. Immediately after, its value is 4AIRASSOCIATES. It seems safe to assume that's why the relationship isn't being saved, but I haven't figured out why the data is changing at this point in the execution.

Has anyone else seen this? Am I missing some critical piece? To the best of my knowledge, this was working fine in v1.2.1 (I upgraded a week ago or so).

UPDATE

The first bit of apparent weirdness I see is that, although my $row is a string, the condition in Line 1366 evaluates to true so I drop into that code block. If my data is a string, how can it have a member value?

UPDATE

I clearly have some thinking to do, but here's the bottom line. If I drop log writes immediately before and immediately after Line 1394 like so:

$this->log( 'Setting ' . $data . '[' . $this->hasAndBelongsToMany[$assoc]['foreignKey'] . '] = ' . $id, LOG_DEBUG );

$data[$this->hasAndBelongsToMany[$assoc]['foreignKey']] = $id;

$this->log( 'Creating ' . json_encode( $data ) . ' on ' . $join, LOG_DEBUG );

The relevant output is:

2010-03-05 18:57:08 Debug: Setting FAIRASSOCIATES[volunteer_id] = 4b78717f-8ad4-4671-b81c-4e8745591fb4
2010-03-05 18:57:08 Debug: Creating "4AIRASSOCIATES" on CommitteesVolunteer

Possible issues:

  1. I'm not sure how/why Cake is trying to set the volunteer_id member on a string
  2. "FAIRASSOCIATES" is the ID of a committee to which a volunteer is grouped, not a model of any sort, so I don't understand the relevance of FAIRASSOCIATES[volunteer_id] at all.
  3. I have no idea how or why the value of $data is being morphed into 4AIRASSOCIATES by that one line of code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

把人绕傻吧 2024-08-31 00:27:01

我写了一个小修复,它在测试中,(atm它有效):它覆盖了uuid检测(愚蠢的如果只是询问数据是否有16长度或32长度)并假设它是一个有效的id,如果它是一个字符串或一个输入数据的编号。

只需添加函数(复制整个函数):

函数 __saveMulti($joined, $id)

从 lib 的 model.php 到应用程序的 app_model.php

然后替换 model.php 第 1355 行中的 IF :

if ((is_string($row) && (strlen($row))
== 36 || strlen($行) == 16)) || is_numeric($row)) {

现在你的 app_model.php 为这个(不要编辑你的库的 model.php,在你的 app_model.php 中执行此操作):

if( (is_string($row) && ((strlen($row) == 36 || strlen($row) == 16) || !$this->{$assoc}-> ;autoPrimaryKey )) || ( is_numeric($row) ) ) {

然后在你的 app_model.php 添加这个变量:

 var $autoPrimaryKey = true;

并且在您想要此行为的模型中添加相同的变量,但为 false,它将假定模型没有为 HABTM 自动生成的 UUID 并修复问题

 var $autoPrimaryKey = false;

我再说一遍,这只是测试中的修复,它解决了我的问题,您有任何问题,请将其发送到我的邮件 zydriel AT gmail.com

I wrote a small fix and it is in TESTING, (atm it works): it overrides uuid detection (stupid IF just asking if the data has 16 length or 32 length) and asumes it is a valid id if it is a string or a number for the data entered.

just add the function (copy the whole function):

function __saveMulti($joined, $id)

From lib's model.php to your app's app_model.php

Then replace the IF previously in model.php line 1355 :

if ((is_string($row) && (strlen($row)
== 36 || strlen($row) == 16)) || is_numeric($row)) {

NOW your app_model.php for this one ( dont edit your lib's model.php, do this in your app_model.php ):

if( (is_string($row) && ((strlen($row) == 36 || strlen($row) == 16) || !$this->{$assoc}->autoPrimaryKey )) || ( is_numeric($row) ) ) {

then in your app_model.php add this variable:

    var $autoPrimaryKey = true;

and in models that you want this behavior add the same variable but in false, it will asume that the model doesnt have auto generated UUID for HABTM and fix the issue

    var $autoPrimaryKey = false;

I repeat this is just a fix in testing, it solved the problem for me, any question you have, send it to my mail zydriel AT gmail.com

小镇女孩 2024-08-31 00:27:01

看起来我的问题是由于做了一些非常规的事情引起的。对于其值很少改变的查找表(并且没有计划通过应用程序这样做),我喜欢 PK 值是人类可读的。这使我能够直接查看数据库中的数据并以有意义的方式读取相关记录。在这种情况下,我可以查看 Volunteer 记录,无需任何类型的加入,即可看到她/他在名为 FAIRCOMMITTEECommittee 中代码> .查看应用程序外部的数据时有点方便。

在本例中,我的 3 个 Committee 值之一恰好是 16 个字符长(CakePHP 解释为 UUID 的长度),因此它的行为正确。其他的不是 16 个字符,并且行为不正确。

失败的条件位于 第 1355 行。我已输入一张票 看看UUID检测智能是否还有改进的空间。

It looks like my problem is caused by doing something non-conventional. For lookup tables whose values rarely change (and there are no plans for them to do so via the application), I like the PK values to be human readable. That allows me to look at the data directly in the database and read a related record in a meaningful way. In this case, I can look at a Volunteer record and, without requiring any kind of join, see that s/he is in the Committee named FAIRCOMMITTEE . Kind of handy when looking at the data outside of the application.

In this case, one of my 3 Committee values just happened to be 16 characters long--a length CakePHP interpreted as a UUID--so it behaved correctly. The others aren't 16 characters and didn't behave correctly.

The condition that fails is on Line 1355. I've entered a ticket to see whether there's any room for improvement in the UUID detection intelligence.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文