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

