Question

I'm trying to return a list of events, and include the city where it's taking place. The city is only associated through the Event's Venue though.

Below is the code I'm using. It returns all the correct data, but it doesn't return ANY city data (other than the city_id field in Venue - which I'm not sure why it's returning).

Associations:

Event belongsTo Venue
Venue hasMany Event

Venue belongsTo City    
City hasMany Venue

Code:

        $this->Event->Behaviors->attach('Containable');
        $events = $this->Event->find('all', array(
            'limit' => 5,
            'order' => 'Event.created DESC',
            'fields' => array(
                'name',
                'description',
                'phone',
                'price_general',
                'price_child',
                'price_adult',
                'price_child',
                'tickets_url'
            ),
            'contain' => array(
                'Venue' => array(
                    'fields' => array(
                        'name',
                        'address',
                        'city_id',
                    ),
                    'City' => array(
                        'fields' => array(
                            'City.name',
                            'state'
                        ),
                        'conditions' => array(
                            'City.id' => 'Venue.city_id'
                        )
                    )
                ),
                'Schedule' => array(
                    'fields'=>array(),
                    'Date' => array(
                        'conditions'=>array(
                            'Date.start >=' => $start_date,
                            'Date.start <=' => $end_date,
                        )
                    )
                )
            ),
        ));

Bonus answer: (that I have currently asked in another StackOverflow question) - The Date conditions are supposed to filter which events show up, but instead, they're only filtering which Date data to show.


WORKING ANSWER: (thanks bancer)

    $this->Event->recursive = -1;
    $options['joins'] = array(
            array('table' => 'schedules',
                'alias' => 'Schedule',
                'type' => 'LEFT',
                'conditions' => array(
                    'Event.id = Schedule.event_id',
                )
            ),
            array('table' => 'dates',
                'alias' => 'Date',
                'type' => 'LEFT',
                'conditions' => array(
                    'Date.schedule_id = Schedule.id',
                )
            )
        );
        $options['fields'] = array(
            'Event.name',
            'Schedule.start_date',
            'Date.start',
        );
        $options['limit'] = 5;
        $events = $this->Event->find('all', $options);
Was it helpful?

Solution

I would recommend to avoid using Containable. It generates too many queries in some cases. A better way for complex queries is to join tables "manually".

Another option I would consider at the first place is to search through 'Venue' model without using Containable like this: $this->Event->Venues->find('all', ...). As Venues directly associated with Cities and Events there should be possible to get what you want without extra complexities.

Update: take a look at the question How to change the sequence of 'joins' in CakePHP?

OTHER TIPS

instead of containable, did you try including the city data in fields itself by fields=> array('','','City.name)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top