Get it All
Together

Just a quick note to discuss an interesting set of behavior which, while they may seem obvious to some, struck me as a bit counter-intuitive when working on a form recently. I was helped in this endeavor by a WebbedIT in this thread of the Google CakePHP Group. But I took things a bit further out of curiosity and thought I’d share it here.

The form in question pulls data from a table of location whose primary key is the zip code. The fields are zipcode, city and state. I intended to create a form that would allow a person to select either the city/state combination or the zip code. Obviously for the sake of usability, I wanted to make the state choices a select rather than a standard input.

But of course, CakePHP’s automagic selects are built from the find(‘list’) method and that method wants to use the primary key of the table as the value of the select by default. Hence I ended up with the following:
[php]
// In the Controller:
function beforeRender() {
$states = $this->Location->find(‘list’, array(‘fields’ => array(‘Location.state’), ‘group’ => array(‘Location.state’)));
$this->set(‘states’, $states);
}

// In the View:
<?php echo $form->input(‘state’); ?>

// Output to browser: ?>
<select id="LocationState" name="data[Location][state]">
<option value="98791">AK</option>
<option value="35004">AL</option>
<option value="71601">AR</option>
<option value="85003">AZ</option>
<option value="90001">CA</option>

</select><?php
[/php]

That is definitely not what I intended at all. As WebbedIT pointed out, the solution was to include two fields in the request, both the same actual state field as follows:
[php]
$states = $this->Location->find(‘list’, array(‘fields’ => array(‘Location.state’, ‘Location.state’), ‘group’ => array(‘Location.state’)));
[/php]
Well, OK. That gets me past my problem, but what’s this all about? What happens if I select two different fields? What if I select three? What happens when I change the order of fields?

The answer after copious screwing around is that it seems CakePHP organizes the the results in the following method: [optgroup], value, display. I have really no idea what would happen if we extended beyond three fields and honestly don’t have the time to find out. For example, if we grabbed fields in the following call:
[php]$states = $this->Location->find(‘list’, array(‘fields’ => array(‘Location.city’, ‘Location.state’), ‘group’ => array(‘Location.state’)));[/php]
We can expect that the city will be used as the displayed text and the state would be used as the value of the option. If we grabbed three fields from the table, we would end up with option groups in the resulting select element:
[php]
// This query:
$states = $this->Location->find(‘list’, array(‘fields’ => array(‘Location.city’, ‘Location.state’, ‘Location.zipcode’), ‘group’ => array(‘Location.state’)));
// Gives us:
<select id="LocationState" name="data[Location][state]">
<optgroup label="98791">
<option value="98791">AK</option>
</optgroup>
<optgroup label="35004">
<option value="Acmar">AL</option>
</optgroup>
<optgroup label="71601">
<option value="North Cedar">AR</option>
</optgroup>
<optgroup label="85003">
<option value="Phoenix">AZ</option>
</optgroup>
<optgroup label="90001">
<option value="Los Angeles">CA</option>
</optgroup>

</select>
[/php]

I can see lots of reasons why this option group thing would be good to have around, though in my case because I’m grouping, it makes less sense. If I ungrouped the items, I’d get a city presumably in every zip code.

I hope this helps some people figure out what is going on with CakePHP’s automagic selects. The functionality is definitely helpful but not at all documented that I’ve seen and definitely counter-intuitive.