Hide
on 2/9/06

If you use MPTT tables anywhere (The cake acl system uses it) you may have found that when you delete an entry, the lft and rght fields for the neighouring nodes don't get updated. This may have rather dire concequences ;)

There is an open ticket for how to delete from the cake acl tables, but as it is potentially quite generic, I thought I'd include the (potential) fix here. Below are two versions of a delete method, one takes care of associations, and the other doesn't:

  1. <?php
  2. // If there are associations to take care of
  3. function
  4. delete($Alias) {
  5. $class = $this->name;
  6. $result = $this->findByAlias($Alias);
  7. $object =
  8. $result[$class];
  9. if ($object == null || count($object) == 0) {
  10. return false;
  11. }
  12. $idList[] = $result[$class]['id'];
  13. // won't somebody please think of the children.
  14. $Children=
  15. $this->findAll(array("rght"=>"< {$result[$class]['rght']}","lft"=>"> {$result[$class]['lft']}"),"id",null,null,null,-1);
  16. foreach($Children as $Child) {
  17. $idList[] = $Child[$class]['id'];
  18. }
  19. // Delete associated
  20. permissions.
  21. $this->ArosAco->query("DELETE FROM ".$this->ArosAco->tablePrefix.$this->ArosAco->table." WHERE
  22. {$class}_id in (".implode(",",$idList).")");
  23. // Perform the delete
  24. $table =
  25. $this->tablePrefix.$this->table;
  26. $this->query("DELETE FROM $table WHERE $table.lft >= {$result[$class]['lft']} AND
  27. $table.rght <= {$result[$class]['rght']}");
  28. // Reindex.
  29. $shift = 1+ $result[$class]['rght'] -
  30. $result[$class]['lft'];
  31. $this->query('UPDATE ' . $table . ' SET `rght` = `rght` - ' . $shift . ' WHERE `rght` > '
  32. . $result[$class]['rght']);
  33. $this->query('UPDATE ' . $table . ' SET `lft` = `lft` - ' . $shift . ' WHERE `lft`
  34. > ' . $result[$class]['lft']);
  35. return true;
  36. }
  37. // No associations to take care or
  38. function delete($id)
  39. {
  40. $result = $this-read();
  41. // Perform the delete
  42. $table = $this->tablePrefix.$this->table;
  43. $this->query("DELETE FROM $table WHERE $table.lft >= {$result[$class]['lft']} AND $table.rght <=
  44. {$result[$class]['rght']}");
  45. // Reindex.
  46. $shift = 1+ $result[$class]['rght'] - $result[$class]['lft'];
  47. $this->query('UPDATE ' . $table . ' SET `rght` = `rght` - ' . $shift . ' WHERE `rght` > ' .
  48. $result[$class]['rght']);
  49. $this->query('UPDATE ' . $table . ' SET `lft` = `lft` - ' . $shift . ' WHERE `lft` > ' .
  50. $result[$class]['lft']);
  51. return true;
  52. }
  53. ?>

Should anybody use this and find it causes a problem please let me know.

1 Response to How to delete an MPTT Node

  1. 1
    The delete method in the Cake ACL system was recently updated - so if you came here because deleting a node has corrupted your data: Grab the latest trunk ;)