根据条件过滤列表

时间:2010-08-11 21:23:21

标签: php cakephp filtering

问题

我有一个任务列表,用户在登录时会与您联系。我希望能够 根据作业过滤任务。表格中的相关字段是:

**tasks table**
task_id   | (FK int) user  | (FK int) team
            (assigned to)    (assigned to)

用户属于一个团队。在前端我有复选框:

[ ] Mine     [ ] My Team's   [ ] Others    (Filter)

条件相互排斥。例如,如果我只检查“我的团队”,那就暗示了 我希望看到分配给我的团队的所有任务,但不是我。如果我查看“我的”,我只想查看分配给我的任务。

我可以使用复选框的任意组合来过滤我的结果。

(丑陋)解决方案:

将标记转换为二进制数转换为int(小端)并使用switch

$num = bindec("{$flag1}{$flag2}{$flag3}");

switch ($num) {
    // [ ] Mine   [ ] My Team's   [X] Others
    case 1:
        $filter = array('team <>' => $teamId);
        break;
    // [ ] Mine   [X] My Team's   [X] Others
    case 3:
        $filter = array('user <>' => $userId);
        break;

    /* a few more */

    // [X] Mine   [X] My Team's   [X] Others
    default:
        $filter = array();
        break;
}

生成的$filter数组将传递给查询构建器 有用。但我觉得这真的很难看。还有更好的方法吗?

2 个答案:

答案 0 :(得分:0)

嗯,我个人认为这太难看了......

为什么不创建两个过滤器阵列(一个用于和,另一个用于或)

$andFilter = array();
$orFilter = array();
if ($flag1) {
    $orFilter['user = '] = $userId;
} else {
    $andFilter['user <> '] = $userId;
}
if ($flag2) {
    $orFilter['team = '] = $teamId;
} else {
    $andfilter['team <> '] = $teamId;
}
if ($flag3) {
    $orFilter['1 = '] = 1;
}

然后,将查询加入($orFilter) AND ($andFilter),其中过滤器的每个元素由相应的布尔运算符(OR $orFilterAND隔开$andFilter })...

它应该满足您的所有需求,并且是相对未来的证明(因为您可以根据需要添加标记)...

答案 1 :(得分:0)

很抱歉我有OCD / ADD的性质,但我总是要回到功能的真实意图。似乎听说模型中可能存在一些不一致。为什么在任务表中有团队ID?如果用户可以在多个团队中,那么我理解为什么。但是如果用户只在一个团队中,那么任务中的团队ID可以从用户和团队之间的关系中得出。因此,通过将用户分配给任务,您实际上可以从用户派生团队。

话虽这么说,我就是这样做的。首先,将过滤器添加到表单中:

echo $this->Form->input('filter_user_id', array('type' => 'checkbox', 'label' => 'Mine'));
echo $this->Form->input('filter_team_id', array('type' => 'checkbox', 'label' => 'Team'));
echo $this->Form->input('filter_other', array('type' => 'checkbox', 'label' => 'Other')); 

然后在控制器功能中,检查过滤器:

// process the filters
if($this->data['Task']['filter_user_id']) {
    $filter['Task.user_id'] = 'Task.user_id = ' . $user_id;
}
if($this->data['Task']['filter_team_id']) {
    $filter['Task.team_id'] = '(Task.team_id = ' . $team_id . ' AND Task.user_id <> ' . $user_id . ')';
}
if($this->data['Task']['filter_other']) {
    $filter['Task.id'] = '(Task.team_id <> ' . $team_id . ' AND Task.user_id <> ' . $user_id . ')';
}
$query = join(' or ', $filter);

$this->set('data', $this->Task->find('all', array('conditions' => array($query))));

此解决方案可行。您当然可以根据自己的需要进行调整。

注意:我更新了查询以符合您的要求。这将更像你期望的工作。虽然查询可能没有得到优化,但它仍然表现得相当不错。