Фильтрация списка по условиям - PullRequest
1 голос
/ 12 августа 2010

проблема

У меня есть список задач, с которыми пользователь сталкивается при входе в систему. Я хочу быть в состоянии фильтровать задачи по назначению. Соответствующие поля в таблице:

**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 голосов
/ 12 августа 2010

Извините за природу OCD / ADD, но мне всегда приходится возвращаться к реальному замыслу функциональности. Кажется, слышат, что в модели могут быть некоторые несоответствия. Почему у вас есть идентификатор команды в таблице задач? Если пользователь может быть в более чем одной команде, я понимаю, почему. Но если пользователь только в одной команде, то идентификатор команды в задачах может быть получен из отношений между пользователем и командой. Таким образом, назначая пользователя для задачи, вы фактически можете получить команду от пользователя.

Как говорится, я так и сделаю. Сначала добавьте фильтры в форму:

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))));

Это решение будет работать. Вы, конечно, можете адаптировать его для своих нужд.

ПРИМЕЧАНИЕ. Я обновил запрос, чтобы он соответствовал вашему запросу. Это будет работать больше, чем вы ожидаете. И хотя запросы не могут быть оптимизированы, они все равно работают довольно хорошо.

0 голосов
/ 12 августа 2010

Ну, лично я не думаю, что это слишком уродливо ...

Почему бы просто не создать два массива фильтров (один для и другой для или)

$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 для $orFilter, AND для $andFilter) ...

Он должен удовлетворить все ваши потребности и быть относительно перспективным (поскольку вы можете добавлять флаги по своему усмотрению) ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...