CakePHP HABTM:编辑一项会导致 HABTM 行重新创建,破坏额外的数据

发布于 2024-08-21 13:21:46 字数 2171 浏览 11 评论 0原文

我在 CakePHP 中的 HABTM 关系遇到问题。

我有两个模型,如下所示:Department HABTM Location。一家大公司拥有多栋大楼,每栋大楼提供的服务数量有限。每个建筑物也有自己的网页,因此除了 HABTM 关系本身之外,每个 HABTM 行还有一个 url 字段,用户可以访问该字段以查找有关他们感兴趣的服务以及如何使用的其他信息它在他们感兴趣的建筑物上运行。

我已经像这样设置了模型:

<?php
class Location extends AppModel {
    var $name = 'Location';

    var $hasAndBelongsToMany = array(
        'Department' => array(
            'with' => 'DepartmentsLocation',
            'unique' => true
        )
    );
}
?>


<?php
class Department extends AppModel {
    var $name = 'Department';

    var $hasAndBelongsToMany = array(
        'Location' => array(
            'with' => 'DepartmentsLocation',
            'unique' => true
        )
    );
}
?>

<?php
class DepartmentsLocation extends AppModel {
    var $name = 'DepartmentsLocation';

    var $belongsTo = array(
        'Department',
        'Location'
    );    


    // I'm pretty sure this method is unrelated. It's not being called when this error
    // occurs. Its purpose is to prevent having two HABTM rows with the same location
    // and department.
    function beforeSave() {

        // kill any existing rows with same associations
        $this->log(__FILE__ . ": killing existing HABTM rows", LOG_DEBUG);

        $result = $this->find('all', array("conditions" =>
            array("location_id" => $this->data['DepartmentsLocation']['location_id'],
                  "department_id" => $this->data['DepartmentsLocation']['department_id'])));


        foreach($result as $row) { 
            $this->delete($row['DepartmentsLocation']['id']);
        }

        return true;
    }
}
?>

控制器完全无趣。

问题: 如果我编辑 Location 的名称,则链接到该 Location 的所有 DepartmentsLocation 都将使用空 URL 重新创建。由于模型指定 unique 为 true,这也会导致所有较新的行覆盖较旧的行,这实际上会破坏所有 URL。

我想知道两件事: 我可以阻止这一切吗?如果是这样,怎么办?

而且,用一个不太技术性和更多的抱怨:为什么会发生这种情况?对我来说,通过 Cake 编辑字段会造成如此多的麻烦,这似乎很奇怪,而我可以轻松地通过 phpMyAdmin,在那里编辑 Location 名称,并获得我期望的结果。当我刚刚编辑一行上的字段时,为什么 CakePHP 会触及 HABTM 数据?它甚至不是外键!

I'm having trouble with my HABTM relationship in CakePHP.

I have two models like so: Department HABTM Location. One large company has many buildings, and each building provides a limited number of services. Each building also has its own webpage, so in addition to the HABTM relationship itself, each HABTM row also has a url field where the user can visit to find additional information about the service they're interested and how it operates at the building they're interested in.

I've set up the models like so:

<?php
class Location extends AppModel {
    var $name = 'Location';

    var $hasAndBelongsToMany = array(
        'Department' => array(
            'with' => 'DepartmentsLocation',
            'unique' => true
        )
    );
}
?>


<?php
class Department extends AppModel {
    var $name = 'Department';

    var $hasAndBelongsToMany = array(
        'Location' => array(
            'with' => 'DepartmentsLocation',
            'unique' => true
        )
    );
}
?>

<?php
class DepartmentsLocation extends AppModel {
    var $name = 'DepartmentsLocation';

    var $belongsTo = array(
        'Department',
        'Location'
    );    


    // I'm pretty sure this method is unrelated. It's not being called when this error
    // occurs. Its purpose is to prevent having two HABTM rows with the same location
    // and department.
    function beforeSave() {

        // kill any existing rows with same associations
        $this->log(__FILE__ . ": killing existing HABTM rows", LOG_DEBUG);

        $result = $this->find('all', array("conditions" =>
            array("location_id" => $this->data['DepartmentsLocation']['location_id'],
                  "department_id" => $this->data['DepartmentsLocation']['department_id'])));


        foreach($result as $row) { 
            $this->delete($row['DepartmentsLocation']['id']);
        }

        return true;
    }
}
?>

The controllers are completely uninteresting.

The problem:
If I edit the name of a Location, all of the DepartmentsLocations that were linked to that Location are re-created with empty URLs. Since the models specify that unique is true, this also causes all of the newer rows to overwrite the older rows, which essentially destroys all of the URLs.

I would like to know two things:
Can I stop this? If so, how?

And, on a less technical and more whiney note: Why does this even happen? It seems bizarre to me that editing a field through Cake should cause so much trouble, when I can easily go through phpMyAdmin, edit the Location name there, and get exactly the result I would expect. Why does CakePHP touch the HABTM data when I'm just editing a field on a row? It's not even a foreign key!

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

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

发布评论

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

评论(3

花之痕靓丽 2024-08-28 13:21:46

从 CookBook 来看,第一个问题是:

保存时默认
HasAndBelongsToMany 关系,蛋糕
将删除连接表上的所有行
在保存新的之前。

我不太清楚为什么 Cake 试图保存 HABTM 数据,即使您的数据中没有外键,但有一个简单的解决方案。只需销毁关联即可保存通话:

$this->Location->unbindModel(
    array('hasAndBelongsToMany' => array('Department'))
);

From the CookBook the 1st problem is:

By default when saving a
HasAndBelongsToMany relationship, Cake
will delete all rows on the join table
before saving new ones.

I am not quite sure why Cake is trying to save the HABTM data even though you don't have a foreign key in your data, but there is an easy solution for that. Simply destroy the association for the save call:

$this->Location->unbindModel(
    array('hasAndBelongsToMany' => array('Department'))
);
在你怀里撒娇 2024-08-28 13:21:46

我正在思考为什么会发生这种情况的一个原因。当您检索 Location 时,您还会检索 locations_departments 数据。当您执行 save($this->data) 时,它会在数组中查找模型并保存它们。

解决此问题的一种方法是将(模型的)recursive 属性设置为 -10 (尝试一下,我不确定,只需打印出数据即可查看结果)。您可以在模型中设置:var $recursive = -1;或在控制器方法(操作)中设置:$this->ModelName->recursive = -1;代码>

有关递归的更多信息: http://book.cakephp.org/view/439/recursive< /a>

这与 harpax 的建议非常相似,只是如果您不需要该数据,请告诉 Cake,这样它就不会获取它。

I'm thinking of one reason why this might be happening. When you retrieve Location, you also retrieve locations_departments data. And when you do a save($this->data) it looks for models in the array and saves them.

A way to solve this is setting the recursive attribute (of a model) to -1 or 0 (try, I'm not sure, just print out the data to see what comes out). You can set it in the model: var $recursive = -1; or in the controller method (action): $this->ModelName->recursive = -1;

More about recursive: http://book.cakephp.org/view/439/recursive

It's really similar to what harpax suggested, just if you don't need that data, tell it to Cake, so that it won't fetch it.

孤凫 2024-08-28 13:21:46

问题是,在保存 Location 时,您也为 save 方法提供了一个包含所有 DepartmentsLocations 的数组。因此,CakePHP 销毁了所有内容并尝试重新创建它。

这是蛋糕的常见错误,因为它通常会给你带来太多的结果。

确保仅传递需要保存的数据,或者最好仅获取您需要的数据。

Trouble is that when saving your Location, you gave the save method an array containing all the DepartmentsLocations too. Thus CakePHP destroys everything and try to recreate it.

This is a common mistake with cake since it will often pull far too many results for you.

Be sure to pass only the data that needs to be saved, or better to fetch only the datas you need.

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