Wednesday, March 31, 2010

Re: Set class help needed

On Mar 31, 10:16 am, "Dr. Loboto" <drlob...@gmail.com> wrote:
> If you pass "fields" option to find("list") as described for grouping
> - this will do all the magic.

Thanks, both, for the tip. I'd forgotten about that option (I don't
think I've used it before). I'm not sure that it'll work in this case,
though, as I'm querying the members table and containing both
countries & regions for the names.

I've already got a complicated method to retrieve a list of countries
and regions that is used elsewhere. In the other place, I'm creating a
list of links of country names, with sublists of regions for those
countries that have them. The former are links to /members/country/[A-
Z]{2} and the latter, /members/region/[A-Z]{2}. Getting the list
involves querying on distinct Member.country_id and distinct
Member.region_id and then merging the two. So, only countries and
regions that have members are represented.

public function locations()
{
$countries = Set::extract(
$this->find(
'all',
array(
'fields' => array('DISTINCT(Member.country_id)'),
'contain' => array(
'Country' => array(
'fields' => array('*')
)
)
)
),
'{n}.Country'
);

foreach($countries as $key => $country)
{
if (in_array($country['iso_code'], array('US', 'CA')))
{
$countries[$key]['regions'] = Set::extract(
$this->find(
'all',
array(
'fields' => array('DISTINCT(Member.region_id)'),
'conditions' => array(
'NOT' => array('Member.region_id' => null),
'Member.country_id' => $country['id']
),
'contain' => array(
'Region' => array(
'fields' => array('*'),
'order' => array('Region.name' => 'ASC')
)
)
)
),
'{n}.Region'
);
}
}
return $countries;
}

This results in the array I posted earlier as the data I was starting
out with. Now, I need to create a select list from that data to show
elsewhere. Of course, I can't have the form point to both country and
region so I decided to only list the regions, grouped by country. In
this case, that's US & Canada. Other countries are not presented. This
suits the client because their membership is limited to those two.
However, there are edge cases where existing members live abroad.

What I ended up doing is abandoning Set and doing it the old-fashioned
way:

$options = array();
foreach($data as $k => $d)
{
if (!in_array($d['iso_code'], array('US', 'CA')))
{
unset($data[$k]);
}
else
{
$options[$d['name']] = array();

foreach($d['regions'] as $region)
{
$options[$d['name']][$region['iso_code']] = $region['name'];
}
}
}

It's damned ugly but it works. I'm using requestAction() and caching
the elements, so I'm not too concerned about the overhead.

Check out the new CakePHP Questions site http://cakeqs.org and help others with their CakePHP related questions.

You received this message because you are subscribed to the Google Groups "CakePHP" group.
To post to this group, send email to cake-php@googlegroups.com
To unsubscribe from this group, send email to
cake-php+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/cake-php?hl=en

To unsubscribe, reply using "remove me" as the subject.

No comments: