在 CakePHP 中检索 HABTM、HasMany...等数据比 -1 递归手动连接更好的方法?
我有一个事件数据库。我创建了一个模型函数来检索基于城市、类型、子类型、开始和结束的事件。结束日期。
它(大部分)可以工作,但是天哪,这是一段新颖的代码。有更好的方法吗? (这是很多代码,但不难理解我正在做的事情):
我的一些关联:
Event belongsTo Restaurant
Event belongsTo Venue
Restaurant belongsTo City
Venue belongsTo City
Event hasAndBelongsToMany EventType
Event hasAndBelongsToMany EventSubType
Event hasMany Schedule
Schedule hasMany Date
(and of course their belongsTo/hasMany counterparts are set up too)
我的“getEvents”函数(在事件模型中):
function getEvents($opts) {
//$opts = limit, start, end, fields, types, subtypes, subsubtypes, cities
//dates
$qOpts['start'] = date('Y-m-d') . ' 00:00:00';
if(isset($opts['start'])) $qOpts['start'] = $opts['start'];
$qOpts['end'] = date('Y-m-d') . ' 23:59:59';
if(isset($opts['end'])) $qOpts['end'] = $opts['end'];
//limit
if(isset($opts['limit'])) $qOpts['limit'] = $opts['limit'];
//fields
$qOpts['fields'] = array('Event.id', 'Event.name', 'Event.slug', 'City.name', 'Date.start');
if(isset($opts['fields'])) $qOpts['fields'] = $opts['fields'];
//joins
$qOpts['joins'] = array(
array('table' => 'schedules',
'alias' => 'Schedule',
'type' => 'LEFT',
'conditions' => array(
'Event.id = Schedule.event_id',
)
),
array('table' => 'dates',
'alias' => 'Date',
'type' => 'LEFT',
'order' => 'Date.start ASC',
'conditions' => array(
'Date.schedule_id = Schedule.id',
),
),
array('table' => 'venues',
'alias' => 'Venue',
'type' => 'LEFT',
'conditions' => array(
'Event.venue_id = Venue.id',
)
),
array('table' => 'restaurants',
'alias' => 'Restaurant',
'type' => 'LEFT',
'conditions' => array(
'Event.restaurant_id = Restaurant.id',
)
),
array('table' => 'cities',
'alias' => 'City',
'type' => 'LEFT',
'conditions' => array(
'OR' => array(
'Venue.city_id = City.id',
'Restaurant.city_id = City.id',
),
)
),
array('table' => 'event_types_events',
'alias' => 'EventTypesEvent',
'type' => 'LEFT',
'conditions' => array(
'EventTypesEvent.event_id = Event.id',
)
),
array('table' => 'event_sub_types_events',
'alias' => 'EventSubTypesEvent',
'type' => 'LEFT',
'conditions' => array(
'EventSubTypesEvent.event_id = Event.id',
)
),
array('table' => 'event_types',
'alias' => 'EventType',
'type' => 'LEFT',
'conditions' => array(
'EventTypesEvent.event_type_id = EventType.id',
)
),
array('table' => 'event_sub_types',
'alias' => 'EventSubType',
'type' => 'LEFT',
'conditions' => array(
'EventSubTypesEvent.event_sub_type_id = EventSubType.id',
)
),
);
//date conditions
$qOpts['conditions'] = array(
"Date.start >=" => $qOpts['start'],
"Date.start <=" => $qOpts['end'],
);
//cities conditions
if(isset($opts['cities'])) {
if(is_array($opts['cities'])) {
$cityConditions['OR'] = array();
foreach($opts['cities'] as $city_id) {
array_push($cityConditions['OR'], array('City.id'=>$city_id));
}
array_push($qOpts['conditions'], $cityConditions);
}
}
//event types conditions
if(isset($opts['event_types'])) {
if(is_array($opts['event_types'])) {
$eventTypeConditions['OR'] = array();
foreach($opts['event_types'] as $event_type_id) {
array_push($eventTypeConditions['OR'], array('EventType.id'=>$event_type_id));
}
array_push($qOpts['conditions'], $eventTypeConditions);
}
}
//event sub types conditions
if(isset($opts['event_sub_types'])) {
if(is_array($opts['event_sub_types'])) {
$eventSubTypeConditions['OR'] = array();
foreach($opts['event_sub_types'] as $event_sub_type_id) {
array_push($eventSubTypeConditions['OR'], array('EventSubType.id'=>$event_sub_type_id));
}
array_push($qOpts['conditions'], $eventSubTypeConditions);
}
}
$this->recursive = -1;
$data = $this->find('all', $qOpts);
return $data;
}
奖励积分:我有一个关于StackOverflow(此处) 询问关于这个函数 - 试图弄清楚如何让它返回多个日期,而不是每个事件只返回一个日期。
I have a database of Events. I created a model-function to retrieve the events based on city, type, subtype, start & end dates.
It's working (mostly), but geez, it's a novel worth of code. Is there a better way to do this? (It's a lot of code, but not hard to follow what I'm doing):
Some of my associations:
Event belongsTo Restaurant
Event belongsTo Venue
Restaurant belongsTo City
Venue belongsTo City
Event hasAndBelongsToMany EventType
Event hasAndBelongsToMany EventSubType
Event hasMany Schedule
Schedule hasMany Date
(and of course their belongsTo/hasMany counterparts are set up too)
My "getEvents" function (in the event model):
function getEvents($opts) {
//$opts = limit, start, end, fields, types, subtypes, subsubtypes, cities
//dates
$qOpts['start'] = date('Y-m-d') . ' 00:00:00';
if(isset($opts['start'])) $qOpts['start'] = $opts['start'];
$qOpts['end'] = date('Y-m-d') . ' 23:59:59';
if(isset($opts['end'])) $qOpts['end'] = $opts['end'];
//limit
if(isset($opts['limit'])) $qOpts['limit'] = $opts['limit'];
//fields
$qOpts['fields'] = array('Event.id', 'Event.name', 'Event.slug', 'City.name', 'Date.start');
if(isset($opts['fields'])) $qOpts['fields'] = $opts['fields'];
//joins
$qOpts['joins'] = array(
array('table' => 'schedules',
'alias' => 'Schedule',
'type' => 'LEFT',
'conditions' => array(
'Event.id = Schedule.event_id',
)
),
array('table' => 'dates',
'alias' => 'Date',
'type' => 'LEFT',
'order' => 'Date.start ASC',
'conditions' => array(
'Date.schedule_id = Schedule.id',
),
),
array('table' => 'venues',
'alias' => 'Venue',
'type' => 'LEFT',
'conditions' => array(
'Event.venue_id = Venue.id',
)
),
array('table' => 'restaurants',
'alias' => 'Restaurant',
'type' => 'LEFT',
'conditions' => array(
'Event.restaurant_id = Restaurant.id',
)
),
array('table' => 'cities',
'alias' => 'City',
'type' => 'LEFT',
'conditions' => array(
'OR' => array(
'Venue.city_id = City.id',
'Restaurant.city_id = City.id',
),
)
),
array('table' => 'event_types_events',
'alias' => 'EventTypesEvent',
'type' => 'LEFT',
'conditions' => array(
'EventTypesEvent.event_id = Event.id',
)
),
array('table' => 'event_sub_types_events',
'alias' => 'EventSubTypesEvent',
'type' => 'LEFT',
'conditions' => array(
'EventSubTypesEvent.event_id = Event.id',
)
),
array('table' => 'event_types',
'alias' => 'EventType',
'type' => 'LEFT',
'conditions' => array(
'EventTypesEvent.event_type_id = EventType.id',
)
),
array('table' => 'event_sub_types',
'alias' => 'EventSubType',
'type' => 'LEFT',
'conditions' => array(
'EventSubTypesEvent.event_sub_type_id = EventSubType.id',
)
),
);
//date conditions
$qOpts['conditions'] = array(
"Date.start >=" => $qOpts['start'],
"Date.start <=" => $qOpts['end'],
);
//cities conditions
if(isset($opts['cities'])) {
if(is_array($opts['cities'])) {
$cityConditions['OR'] = array();
foreach($opts['cities'] as $city_id) {
array_push($cityConditions['OR'], array('City.id'=>$city_id));
}
array_push($qOpts['conditions'], $cityConditions);
}
}
//event types conditions
if(isset($opts['event_types'])) {
if(is_array($opts['event_types'])) {
$eventTypeConditions['OR'] = array();
foreach($opts['event_types'] as $event_type_id) {
array_push($eventTypeConditions['OR'], array('EventType.id'=>$event_type_id));
}
array_push($qOpts['conditions'], $eventTypeConditions);
}
}
//event sub types conditions
if(isset($opts['event_sub_types'])) {
if(is_array($opts['event_sub_types'])) {
$eventSubTypeConditions['OR'] = array();
foreach($opts['event_sub_types'] as $event_sub_type_id) {
array_push($eventSubTypeConditions['OR'], array('EventSubType.id'=>$event_sub_type_id));
}
array_push($qOpts['conditions'], $eventSubTypeConditions);
}
}
$this->recursive = -1;
$data = $this->find('all', $qOpts);
return $data;
}
Bonus points: I have a question on StackOverflow (here) that asks about this function as well - trying to figure out how to get it to return multiple dates instead of just one per event.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
只需正确设置关联并执行正常(递归)
find()
即可。如果您想要对检索到的关联数据进行更多控制,请使用 ContainableBehavior。如果您在某些关联模型上有条件,要求您将其他表连接到主查询中,那么这是一个不同的主题,并且有很多方法可以解决它(搜索 SO 或提出特定问题)。为此,手动连接可能是合适的。不过,您不需要仅仅为了检索关联数据而手动连接表。
Just set up your associations properly and do a normal (recursive)
find()
. If you want more control over the associated data that's retrieved, use the ContainableBehavior.If you have conditions on some associated model that requires you to join other tables into the primary query, that's a different topic and there are many ways to go about it (search SO or ask a specific question). For that purpose manual joins may be appropriate. You do not need to manually join tables just to retrieve associated data though.