I think it happens sometimes, that you need to keep a certain amount of data, and don't want your database table to grow out of limit.
For example, we have a fairly typical Post model and a posts table with more than 100 posts. We only want the latest 100 posts in the table, so we need to delete older posts on every new post.
To accomplish this in Cake way, we need to write a bit of script. So, let's add a trimming method to our Post model (You can also add it to AppModel to make it reusable in other models):
<?php class Post extends AppModel { var $name = 'Post'; function trim($options) { $defaults = array('conditions' => null, 'maintain' => null, 'order' => null, 'cascade' => true, 'callbacks' => false, 'notices' => true); $options = array_merge($defaults, (array)$options); extract($options); if ($notices) { $calledFrom = debug_backtrace(); if ($calledFrom[1]['function'] != 'beforeSave') { trigger_error( __("({$this->alias}::trim()) should only be called by Model::beforeSave()", true), E_USER_WARNING ); return false; } } $conditions = (array)$conditions; $count = $this->find('count', array_merge(array('recursive' => -1), compact('conditions'))); if ($count <= 0) { return false; } if (is_int($maintain) && $maintain > 0) { $start = $maintain - 1; $last = $count - $start; unset($maintain); if ($start == $last) { return false; } } if (isset($start) && isset($last) && $count > $start) { if (is_null($order)) { $order = array($this->alias . '.' . $this->primaryKey => 'desc'); } $limit = $start . ',' . $last; $ids = Set::extract( $this->find('all', array_merge(array( 'fields' => "{$this->alias}.{$this->primaryKey}", 'recursive' => -1), compact('conditions', 'order', 'limit') )), "{n}.{$this->alias}.{$this->primaryKey}" ); $this->deleteAll(array($this->alias . '.' . $this->primaryKey => $ids), $cascade, $callbacks); } } } ?>
In theory it's pretty simple.
- We count to get total number of recods in our posts table along with conditions (if needed)
- We get all the IDs of the records to delete.
- And then, we delete them with Model::deleteAll().
Now, let's call it in our Post model beforeSave():
function beforeSave() { $this->trim(array( 'maintain' => 100 )); return true; }
Here are some options available for the trim() method.
$options has the following possible keys - all of which are optional except for the 'maintain' key:
conditions | mixed | Conditions to match | (no default) |
maintain | integer | The maximum number of records to maintain | (no default) |
order | mixed | String or array defining order | primary key desc |
cascade | boolean | Set to true to delete records that depend on this record | true |
callbacks | boolean | Run callbacks (not being used). | false |
notices | boolean | When set to false, E_NOTICES wont't be displayed | true |
That’s all folks.