In a CakePHP app, if you've done the right thing and defined your Model associations at the database level (ie, if you've added foreign key indexes to all the relevant fields in every table), then you might come across errors when deleting records… something like this:
SQLSTATE[23000]: INTEGRITY CONSTRAINT VIOLATION: 1451 CANNOT DELETE OR UPDATE A PARENT ROW: A FOREIGN KEY CONSTRAINT FAILS
You'll want to catch that exception yourself, and ideally, display it nicely for your users.
Here's a quick method I wrote for AppModel.php
that should do the trick. On the beforeDelete
callback, it'll loop through the model's $hasMany
associations, and for any that aren't listed as 'dependent' => true
, it'll check for linked records, and throw an exception if it finds any.
(Of course, 'dependent' => true
cases can be ignored, since those associated records will get deleted automatically)
Say you were deleting a Category that had Items, the exception message will look something like this:
THERE ARE ITEMS LINKED TO THIS RECORD.
So, here's the code to put in AppModel.php
:
<?php
public function beforeDelete($cascade = true) {
$canDelete = true;
foreach ($this->hasMany as $model => $details) {
if ($details['dependent'] !== true ) {
if ($details['className'] == $this->name) {
$ModelInstance = $this;
} else {
$ModelInstance = $this->{$details['className']};
}
$count = $ModelInstance->find("count", array(
"conditions" => array($details['foreignKey'] => $this->id)
));
if ($count) {
throw new Exception( sprintf("There are %s linked to this record.", strtolower(Inflector::humanize(Inflector::tableize($model)))) );
}
if ($count > 0) {
$canDelete = false;
}
}
}
return $canDelete;
}
And here's what the relevant snipped might look like in your controller:
<?php
try {
if ($this->MyModel->delete()) {
$this->Session->setFlash('Record deleted', 'default', array(), 'good');
} else {
$this->Session->setFlash('Record was not deleted. Unknown error.', 'default', array(), 'bad');
}
} catch (Exception $e) {
$this->Session->setFlash("Delete failed. {$e->getMessage()}", 'default', array(), 'bad');
}
return $this->redirect(array('action' => 'index'));