当并非所有连接表列都是外键时保存 HABTM 记录

发布于 2024-07-13 14:50:25 字数 995 浏览 8 评论 0原文

我正在尝试更新具有“具有”和“属于多个”(HABTM) 关系的表。

当我的连接表看起来像这样时:

CREATE TABLE IF NOT EXISTS `items_labels` (
  `item_id` int(11) NOT NULL,
  `label_id` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

我使用 CakePHP,所以我可以使用 $this->Item->save($data) 更新表,其中 $data 是:

Array
(
    [Item] => Array
        (
            [id] => 1
        )
    [Label] => Array
        (
            [Label] => Array
                (
                    [0] => 4
                    [1] => 5
                    [2] => 7
                    [3] => 8
                )
        )
)

我已在连接表中添加了一列,所以现在看起来像:

CREATE TABLE IF NOT EXISTS `items_labels` (
  `item_id` int(11) NOT NULL,
  `label_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

当我保存 $data 时,我还想保存用户 ID。 在一次保存操作中,所有记录的用户 ID 都相同。

有人可以帮助我理解 $data 数组需要是什么样子才能合并用户 ID 吗? 谢谢。

I am trying to update tables with a has and belongs to many (HABTM) relationship.

When my join table looked like this:

CREATE TABLE IF NOT EXISTS `items_labels` (
  `item_id` int(11) NOT NULL,
  `label_id` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

I use CakePHP, so I could update the tables with $this->Item->save($data) where $data was:

Array
(
    [Item] => Array
        (
            [id] => 1
        )
    [Label] => Array
        (
            [Label] => Array
                (
                    [0] => 4
                    [1] => 5
                    [2] => 7
                    [3] => 8
                )
        )
)

I've added a column to my join table, so it now looks like:

CREATE TABLE IF NOT EXISTS `items_labels` (
  `item_id` int(11) NOT NULL,
  `label_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

When I am saving $data, I also want to save a user id. The user id will be the same for all records in a single save operation.

Can someone help me understand what the $data array needs to look like in order to incorporate the user id? Thanks.

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

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

发布评论

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

评论(2

甜柠檬 2024-07-20 14:50:25

这应该可行:

Array
(
    [Item] => Array
        (
            [id] => 1
        )

    [Label] => Array
        (
            [Label] => Array
                (
                    [0] => Array
                        (
                            [label_id] => 4
                            [user_id] => 1
                        )

                    [1] => Array
                        (
                            [label_id] => 5
                            [user_id] => 1
                        )

                    [2] => Array
                        (
                            [label_id] => 7
                            [user_id] => 1
                        )

                    [3] => Array
                        (
                            [label_id] => 8
                            [user_id] => 1
                        )

                )

        )

)

它将生成多个 INSERT,但可以使用一个保存调用。

This should work:

Array
(
    [Item] => Array
        (
            [id] => 1
        )

    [Label] => Array
        (
            [Label] => Array
                (
                    [0] => Array
                        (
                            [label_id] => 4
                            [user_id] => 1
                        )

                    [1] => Array
                        (
                            [label_id] => 5
                            [user_id] => 1
                        )

                    [2] => Array
                        (
                            [label_id] => 7
                            [user_id] => 1
                        )

                    [3] => Array
                        (
                            [label_id] => 8
                            [user_id] => 1
                        )

                )

        )

)

It will generate multiple INSERTs, but will work with one save call.

别想她 2024-07-20 14:50:25

CakePHP 的 model::save() 方法不会为您执行此操作。 我认为你必须使用 model::saveAll() 并在“with”模型上调用它。 CakePHP 会自动识别您的连接表,并可以对其进行建模,而无需您自己创建物理模型文件和类。 您所要做的就是按照 saveAll 期望的格式格式化数据数组。

我还没有尝试过,但类似下面的东西应该有效。

<?php
class Item extends AppModel {
  var $name = 'Item';
  var $_habtmData = null;
  function beforeSave() {
    $this->unbindModel(array('hasAndBelongsToMany' => array('Label')));
    $this->_habtmData = $this->data['Label'];
  }
  function afterSave() {
    if (is_array($this->_habtmData) && !empty($this->_habtmData)) {
      foreach ($this->_habtmData['Label'] as $k => $labelId) {
        $this->_habtmData['Label'][$k] = array(
          'item_id' => $this->id,
          'label_id' => $labelId,
          'user_id' => $userId, // Get this from somewhere
        );
      }
      $this->bindModel(array('hasMany' => array('ItemsLabel')));
      $this->ItemsLabel->saveAll($this->_habtmData);
    }
  }
}
?>

这一切都在模型中完成(应该如此),因此您的控制器和视图保持干净。 我们在 afterSave 中完成这一切,因此它仅在项目数据验证时才尝试。

本质上,我们在 beforeSave 中暂时取消绑定 Item hasAndBelongsToMany Label 关联,因此 HABTM 数据不会被保存,并且我们将 HABTM 数据存储在模型的属性中,因此我们可以在 afterSave 中使用它(尽管无论如何它可能仍然可用) )。

然后,我们使用 hasMany 关联将“with”模型绑定到 Item,并根据 CakePHP 的核心模型::saveAll() 方法的要求格式化数据,最后在“with”模型上调用它并传入新数据。

理论上它应该有效 - 祝你好运,让我知道你进展如何;-)

CakePHP's model::save() method won't do this for you AFAIK. I think you have to use model::saveAll() and call it on the "with" model. CakePHP is automagically aware of your join table and can modelise it without you having to create a physical model file and class yourself. All you should have to do is format the data array in the format saveAll expects.

I've not tried it, but something like the following should work.

<?php
class Item extends AppModel {
  var $name = 'Item';
  var $_habtmData = null;
  function beforeSave() {
    $this->unbindModel(array('hasAndBelongsToMany' => array('Label')));
    $this->_habtmData = $this->data['Label'];
  }
  function afterSave() {
    if (is_array($this->_habtmData) && !empty($this->_habtmData)) {
      foreach ($this->_habtmData['Label'] as $k => $labelId) {
        $this->_habtmData['Label'][$k] = array(
          'item_id' => $this->id,
          'label_id' => $labelId,
          'user_id' => $userId, // Get this from somewhere
        );
      }
      $this->bindModel(array('hasMany' => array('ItemsLabel')));
      $this->ItemsLabel->saveAll($this->_habtmData);
    }
  }
}
?>

This is all done in the model (as it should be), so your controller and views stay clean. We do it all in afterSave, so it only tries it if the Item data validates.

Essentially, we temporarily unbind the Item hasAndBelongsToMany Label association in beforeSave, so the HABTM data doesn't get saved and we store the HABTM data in a property of the model, so we can use it in afterSave (although it's probably still available then anyway).

We then bind the "with" model to Item with a hasMany association, and format the data as required by CakePHP's core model::saveAll() method, before finally calling it on the "with" model, passing in the new data.

It should work in theory - good luck and let me know how you get on ;-)

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