CakePHP : Toggle a BitWise status field
I had a problem. I have been using BitWise status indicators for sometime now, in fact after reading Mark Story’s article they have been a staple of development ever since. In my latest work there was a need to turn on or off an item from a menu. I came across this Nice Trick to toggle Model, which seemed to be perfect but because it is on or off it wasn’t quite what I was looking for.
So I made this. If you’d like to use it, throw it into the AppModel. If you’d like to help make it better, leave a comment and let me know what to do…
function toggleField($field, $data = null, $bitwise = true) { $field = $this->escapeField($field); if(empty($data['conditions'])){$data['conditions'] = null;}; if(is_array($data['conditions'])){ //ARRAY :: The user has passed a few conditions so we set that up for an insert. foreach($data['conditions'] as $object => $property){ $data['conditions'][$this->escapeField($object)] = $property; unset($data['conditions'][$object]); } $query_where = $data['conditions']; } elseif(!empty($data['conditions']['id'])) { $query_where = array($this->escapeField() => $data['conditions']['id']); } else { //DEFAULT :: Where there is no conditions passed, we assume that it is updating the status with the current 'id'. $data['conditions']['id'] = $this->id; $query_where = array($this->escapeField() => $data['conditions']['id']); } if($bitwise){ $query_string = 'CASE'; $query_string .= ' WHEN '. $field .' & '. $data['switching']['On'] .' THEN ('. $field .' &~ '. $data['switching']['On'] .') | '. $data['switching']['Off']; $query_string .= ' WHEN '. $field .' & '. $data['switching']['Off'] .' THEN ('. $field .' &~ '. $data['switching']['Off'] .') | '. $data['switching']['On']; $query_string .= ' WHEN '. $field .' & 0 THEN '. $field .' | '. $data['switching']['On']; $query_string .= ' ELSE 0'; $query_string .= ' END'; $query_conditions = array($field => $query_string); } else { $query = array($field => 'NOT ' . $field); } return $this->updateAll($query_conditions, $query_where); }
Then to call it I have two ways. Firstly the easy way, where I do not need to specify fields:
function live_not_live($id = null) { if(!empty($id)) { $toggle_field = $this->Category->toggleField('status', array( 'switching' => array( 'On' => Category::LIVE, 'Off' => Category::NOT_LIVE ) )); if($toggle_field) { $this->redirect($this->referer()); } } }
No fields are specified, so it just alters the row with the $id variable.
The next one runs based on some conditions specified to the call. In other words there are two fields that need to be set to change the status.
function lock_unlock_domain($id = null) { if(!empty($id)) { $current_setting = $this->CategoryGroup->findByOurId($id, array('recursive' => -1)); $toggle_field = $this->CategoryGroup->toggleField('status', array( 'conditions' => array( 'our_id' => $current_setting['CategoryGroup']['our_id'], 'whm_id' => $current_setting['CategoryGroup']['whm_id'] ), 'switching' => array( 'On' => Category::LIVE, 'Off' => Category::NOT_LIVE ) )); if($toggle_field) { $this->redirect($this->referer()); } } }
And thats it. Status changed in keeping with the Fat Models, Skinny Controllers theory. I am happy with how