Using checkboxes in CakePHP

Posted by Jason on July 3, 2007 at 10:26 pm

Something that’s had me confused for a couple of hours today is using a checkbox in my CakePHP application. I’ve been using the html helper to create the relevant html and was initially confused by the fact that it not only creates the input element but also a preceding hidden input element.

  1. <input type="hidden" name="data[Item][big_rock]"  value="0" id="ItemBigRock_" />
  2. <input type="checkbox" name="data[Item][big_rock]" id="ItemBigRock"  value="1" />

So I did the best thing I could think of and ignored it, but when I came to creating the form to edit existing values I just ended up getting strange results. The checkboxes seemed to have a life of their own, checking and un-checking at will between post-backs. Google came up with several posts about the general problem most people come across with checkboxes – the fact that they post back nothing if they are not checked, but it took me far too long to actually put the strange hidden input field and this standard behaviour together. In my defence, there is very little documentation on this (that I could find) for CakePHP.

I did a bit of debugging and discovered that I did always get a value posted back – sometimes ‘0′, sometimes ‘on’ and sometimes ‘-1′. The ‘on’ I’m used to as that is the value posted back by a checkbox when it is actually checked, but the others seemed a bit random. After much nashing of teeth and a lot of keyboard punching I think I have it, or at least I have a good enough idea of what they are doing to get it to work for me.

The hidden input field has the same name as the checkbox meaning that any value it contains is posted back if the checkbox is unchecked when the form posts. Nifty trick. If the checkbox is set to ‘unchecked’ when the form is rendered then the hidden field is set to ‘-1′, otherwise it is set to ‘0′. The result is that the value posted back is ‘on’ if the checkbox is checked by the user, 0 if the checkbox is unchecked by the user (and was originally checked when the form rendered) and -1 if the checkbox is unchecked (and was originally unchecked when the form rendered).

Make sense? I hope so. It’s actually pretty useful since you can tell what the user did rather than just knowing the state when the form is posted. Since this is not the value we want to stick in our database (well, -1 isn’t anyway) we need to do a bit of manipulation at the controller end. Rather than just mapping the checkbox to the model as you would probably do with a text field it is best to have some sort of interim parameter which can be checked and the desired value set on the model. This is my effort. I don’t think it’s too pretty but it’s late, I’m tired and it works.

  1. if (isset($this->data[‘Item’][‘big_rock_checked’]))
  2. {
  3.     if ($this->data[‘Item’][‘big_rock_checked’] != ‘-1′)
  4.     {
  5.         $this->data[‘Item’][‘big_rock’] = $this->data[‘Item’][‘big_rock_checked’];
  6.     }
  7. }

So, my fake value ‘big_rock_checked’ gets the posted value from the form and if it is ‘-1′ I know there’s no change to the value and can ignore it. Since it doesn’t get set on the model it doesn’t change the db value. If it’s ‘0′ or ‘on’ I just set the model value and let the framework deal with it.

I think some sleep is in order after that one :)

1 Comment »

  1. Thanks, dude – now I got some idea about hidden field :)

    Comment by cake_user — January 21, 2009 @ 4:01 pm

RSS feed for comments on this post. TrackBack URL

Leave a comment