删除相关行时将外列设置为 NULL
Set foreign column to NULL when related row is deleted
我有两张自选图片的用户(不用担心逻辑,名称已更改以保护无辜者):
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 习语(如果有的话)是什么?
CakePHP 2.x 中没有内置功能可以自动执行此操作,您必须自己实现。只要有可能,建议您在数据库中使用实际的外键约束,但如果那不可能,那么您实际上没有太多选择。
在 beforeDelete
或 afterDelete
events/callbacks 中做到这一点应该很容易。如果您的数据库支持事务(并且您的应用程序使用它们 - 它们不会自动发生删除操作),那么建议使用 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'
);
}
我有两张自选图片的用户(不用担心逻辑,名称已更改以保护无辜者):
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 习语(如果有的话)是什么?
CakePHP 2.x 中没有内置功能可以自动执行此操作,您必须自己实现。只要有可能,建议您在数据库中使用实际的外键约束,但如果那不可能,那么您实际上没有太多选择。
在 beforeDelete
或 afterDelete
events/callbacks 中做到这一点应该很容易。如果您的数据库支持事务(并且您的应用程序使用它们 - 它们不会自动发生删除操作),那么建议使用 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'
);
}