Приветствую!
Проблема:
При использовании поиска, построенного через Views exposed filters COMBINE с использованием оператора "Contains any word" проявляется чувствительность к регистру. Из-за чего масса материалов не может быть найдена..
Попытки решения:
Пробовали разное.
От проверки настроек кодировки по MySQL базе, которая везде utf8_general_ci и чувствительности к регистру поиском LIKE в ней по умолчанию нет..
До hook -ов, которые добавляют COLLATE к комбинированным фильтрам (максимум чего удалось добиться это не чувствительность на английский текст, на русский все равно не проходит)
<?php
function hook_views_query_alter(&$view, &$query) {
// Find all combine fields and make them case insensitive.
foreach ($query->where as $group_key => $group) {
foreach ($group['conditions'] as $key => $condition) {
if(preg_match('/:views_combine/', $condition['field'])) {
$query->where[$group_key]['conditions'][$key]['field'] = $condition['field'] . ' COLLATE utf8_general_ci';
}
}
}
}
?>
Проблему, чувствительность к регистру в комбинированном фильтре представлений, удавалось решить лишь использованием
LOWER в операторе Contains (взяли с Drupal.org):
<?php
function op_contains($field) {
$placeholder = $this->placeholder();
// old $this->query->add_where_expression($this->options['group'], "$field LIKE $placeholder", array($placeholder => '%' . db_like($this->value) . '%'));
$this->query->add_where_expression($this->options['group'], "LOWER($field) LIKE LOWER($placeholder)", array($placeholder => '%' . db_like($this->value) . '%'));
}
?>
НО ДЛЯ CONTAINS ANY WORD за не имением навыков PHP ничего придумать не удалось.
Кто может, помогите пжста написать код для данного оператора по аналогии принципа действия LOWER, что приведен выше
Сам код, как понимаю который необходимо скорректировать:
из файла модуля views/handlers/views_handler_filter_combine.inc
<?php
function op_word($field) {
$where = $this->operator == 'word' ? db_or() : db_and();
// Don't filter on empty strings.
if (empty($this->value)) {
return;
}
preg_match_all('/ (-?)("[^"]+"|[^" ]+)/i', ' ' . $this->value, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$phrase = FALSE;
// Strip off phrase quotes.
if ($match[2]{0} == '"') {
$match[2] = substr($match[2], 1, -1);
$phrase = TRUE;
}
$words = trim($match[2], ',?!();:-');
$words = $phrase ? array($words) : preg_split('/ /', $words, -1, PREG_SPLIT_NO_EMPTY);
$placeholder = $this->placeholder();
foreach ($words as $word) {
$where->where($field . " LIKE $placeholder", array($placeholder => '%' . db_like(trim($word, " ,!?")) . '%'));
//$where->where(LOWER $field . " LIKE LOWER $placeholder", array($placeholder => '%' . db_like(trim($word, " ,!?")) . '%'));
}
}
if (!
$where) {
return;
}
// Previously this was a call_user_func_array() but that's unnecessary
// as views will unpack an array that is a single arg.
$this->query->add_where($this->options['group'], $where);
}
?>
Слышал, что правка на прямую кода модулей не лучший способ. Поэтому возможно кто то сталкивался с данной задачей и нашел иное решение проблемы, которым готов поделиться..
Заранее спасибо!
Комментарии
Похожая проблема, решили?
Могу предположить, что связано с тем, что типы данных, которые обрабатываются функцией, у меня это была CONCAT_WS, разные. Ищу LIKE по каждому полю отдельно, тогда результат как ожидается.