删除相关行时将外部列设置为NULL

时间:2019-07-24 12:44:47

标签: cakephp cakephp-2.4 cakephp-2.x

我为用户提供了两张可选图片(不用担心逻辑,名称已经更改以保护无辜者):

CREATE TABLE users (
    id INT(10) NOT NULL AUTO_INCREMENT,
    first_name VARCHAR(255),
    last_name VARCHAR(255),
    first_picture_id INT(10) NULL DEFAULT NULL,
    second_picture_id INT(10) NULL DEFAULT NULL,
    PRIMARY KEY (id),
    CONSTRAINT FK_users_second_picture_id FOREIGN KEY (second_picture_id) REFERENCES pictures (id),
    CONSTRAINT FK_users_first_picture_id FOREIGN KEY (first_picture_id) REFERENCES pictures (id)
);

CREATE TABLE pictures (
    id INT(10) NOT NULL AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    path VARCHAR(255) NOT NULL,
    type VARCHAR(255) NOT NULL,
    PRIMARY KEY (id)
);

我已经以这种方式链接了我的模型(我希望那一部分是正确的):

class User extends AppModel{
    public $belongsTo = array(
        'FirstPicture' => array(
            'className' => 'Picture',
            'foreignKey' => 'first_picture_id',
        ),
        'SecondPicture' => array(
            'className' => 'Picture',
            'foreignKey' => 'second_picture_id',
        ),
    );
}
class Picture extends AppModel{
    public $hasOne = array(
        'User',
    );
}

现在,当我删除任何一张图片时:

$this->FirstPicture->delete($this->request->data('FirstPicture.id'));

...我想将user中的相应列设置为NULL

复制ON DELETE SET NULL外键删除的CakePHP习惯用法(如果有)是什么?

1 个答案:

答案 0 :(得分:1)

CakePHP 2.x内置没有可以自动执行此功能的功能,您必须自己实现。建议您尽可能在数据库中使用实际的外键约束,但是,如果这不可能,那么您在这里实际上没有太多选择。

beforeDeleteafterDelete事件/回调中这样做应该足够容易。如果您的数据库支持事务(并且您的应用程序使用它们-删除操作不会自动发生),则建议使用beforeDelete,因为它可以轻松地停止删除过程。如果没有事务,则将取决于您在错误情况下的更满意情况,未删除关联记录的空外键(beforeDelete)或未删除外键的已删除关联记录(afterDelete

这是一个简单的示例,您可以从关联的任何一方Picture进行操作:

public function beforeDelete($cascade = true) {
    if (!parent::beforeDelete($cascade)) {
        return false;
    }

    $result = $this->User->updateAll(
        array('first_picture_id' => null),
        array('first_picture_id' => $this->getID())
    );
    if (!$result) {
        return false;
    }

    $result = $this->User->updateAll(
        array('second_picture_id' => null),
        array('second_picture_id' => $this->getID())
    );
    if (!$result) {
        return false;
    }

    return true;
}

User

public function __construct($id = false, $table = null, $ds = null)
{
    parent::__construct($id, $table, $ds);

    $this->FirstPicture->getEventManager()->attach(
        function () {
            return $this->updateAll(
                array('first_picture_id' => null),
                array('first_picture_id' => $this->FirstPicture->getID())
            );
        },
        'Model.beforeDelete'
    );

    $this->SecondPicture->getEventManager()->attach(
        function () {
            return $this->updateAll(
                array('second_picture_id' => null),
                array('second_picture_id' => $this->SecondPicture->getID())
            );
        },
        'Model.beforeDelete'
    );
}