Model->Behaviors->load('Tools.Reset', array(...)); * $this->Model->resetRecords(); * * If you want to provide a callback function/method, you can either use object methods or * static functions/methods: * * 'callback' => array($this, 'methodName') * * and * * public function methodName($data, &$fields) {} * * For tables with lots of records you might want to use a shell and the CLI to invoke the reset/update process. * * @author Mark Scherer * @license MIT * @version 1.0 */ class ResetBehavior extends ModelBehavior { protected $_defaultConfig = array( 'limit' => 100, // batch of records per loop 'timeout' => null, // in seconds 'fields' => array(), // if not displayField 'updateFields' => array(), // if saved fields should be different from fields 'validate' => true, // trigger beforeValidate callback 'updateTimestamp' => false, // update modified/updated timestamp 'scope' => array(), // optional conditions 'callback' => null, ); /** * Configure the behavior through the Model::actsAs property * * @param Model $Model * @param array $config */ public function setup(Model $Model, $config = array()) { $this->settings[$Model->alias] = $config + $this->_defaultConfig; } /** * Regenerate all records (including possible beforeValidate/beforeSave callbacks). * * @param Model $Model * @param array $conditions * @param int $recursive * @return int Modified records */ public function resetRecords(Model $Model, $params = array()) { $recursive = -1; extract($this->settings[$Model->alias]); $defaults = array( 'page' => 1, 'limit' => $limit, 'fields' => array(), 'order' => $Model->alias . '.' . $Model->primaryKey . ' ASC', 'conditions' => $scope, 'recursive' => $recursive, ); if (!empty($fields)) { if (!$Model->hasField($fields)) { throw new CakeException('Model does not have fields ' . print_r($fields, true)); } $defaults['fields'] = array_merge(array($Model->primaryKey), $fields); } else { $defaults['fields'] = array($Model->primaryKey); if ($Model->displayField !== $Model->primaryKey) { $defaults['fields'][] = $Model->displayField; } } if (!$updateTimestamp) { $fields = array('modified', 'updated'); foreach ($fields as $field) { if ($Model->schema($field)) { $defaults['fields'][] = $field; break; } } } $params += $defaults; $count = $Model->find('count', compact('conditions')); $max = ini_get('max_execution_time'); if ($max) { set_time_limit(max($max, $count / $limit)); } $modifed = 0; while ($rows = $Model->find('all', $params)) { foreach ($rows as $row) { $Model->create(); $fieldList = $params['fields']; if (!empty($updateFields)) { $fieldList = $updateFields; } if ($fieldList && !in_array($Model->primaryKey, $fieldList)) { $fieldList[] = $Model->primaryKey; } if ($callback) { if (is_callable($callback)) { $parameters = array(&$row, &$fieldList); $row = call_user_func_array($callback, $parameters); } else { $row = $Model->{$callback}($row, $fieldList); } if (!$row) { continue; } } $res = $Model->save($row, compact('validate', 'fieldList')); if (!$res) { throw new CakeException(print_r($Model->validationErrors, true)); } $modifed++; } $params['page']++; if ($timeout) { sleep((int)$timeout); } } return $modifed; } }