Как использовать $query->добавить, где выражение в представлении крючка изменяет запрос


Я пытаюсь использовать hook_views_query_alter() чтобы выбрать некоторые узлы на основе расчета с использованием двух полей в этом узле. Я не могу найти много документации или примеров, которые помогли бы мне понять, как это работает.

Я мог бы использовать Представления PHP, но этот модуль очень глючит в Drupal 7.

Я думаю, что мне нужно использовать $query->add_where_expression(), но я не могу понять, как его использовать.

Мой взгляд называется "латлонг", и в качестве теста, чтобы проверить, имею ли я право подход, я попытался выбрать узлы на основе значения field_latitude. Копирование других функций, которые я видел в гугле, это мое лучшее предположение, но оно не работает. Я знаю, что один из моих узлов имеет значение 53,9519, поэтому, если мой синтаксис верен, я должен вернуть строку, но я этого не делаю:

function my_module_views_query_alter(&$view, &$query) {
  switch($view->name) {
    case 'latlong':  
      $query->add_where_expression(0,'field_data_field_latitude.field_latitude_value = 53.9519');      
      break;
  }
}

Если я print_r($query->where[0]) получу:

Array ( 
  [conditions] => 
    Array ( 
      [0] => 
        Array ( 
         [field] => field_data_field_latitude.field_latitude_value = 53.9519
         [value] => Array ( ) 
         [operator] => formula ) ) 
         [args] => Array ( ) 
         [type] => AND )

Что я делаю не так?

 2
Author: mpdonadio, 2014-03-25

2 answers

Если вы посмотрите документацию для views_plugin_query_default::add_where_expression(), вы заметите следующее примечание. (Акцент сделан на мне.)

Вызывающий отвечает за то, чтобы все поля были полностью заполнены (ТАБЛИЦА.ПОЛЕ) и что таблица уже существует в запросе . Внутренне используется метод dbtng "где".

Глядя на этот вопрос о переполнении стека, я бы понял, что ваш код должен быть следующим один.

function mymodule_views_query_alter(&$view, &$query) {
  switch($view->name) {
    case 'latlong':
      $alias = $query->add_table('field_data_field_latitude');  
      $query->add_where_expression(0, "$alias.field_latitude_value = :latitude", array(':latitude' => 53.9519);      
      break;
  }
}

Поскольку широта является плавающей точкой, я бы использовал сравнение, отличное от $alias.field_latitude_value = :latitude, например, проверяя, находится ли широта в диапазоне [$широта - $эпсилон, $широта + $эпсилон].

 8
Author: kiamlaluno, 2017-05-23 12:41:26

Предоставленный вами дамп запроса определенно выглядит неправильно.

Если вы прочтете до конца views_plugin_query_default::add_where_expression(), вы увидите, что $snippet - это просто предложение, и что вам действительно следует добавить {table.field} с заполнителем.

Я думаю, что это то, чего ты действительно хочешь

$query->add_where_expression(0, 'field_data_field_latitude.field_latitude_value = :latitude', array(':latitude' => 53.9519));

Однако точное сравнение значений с плавающей запятой с десятичными частями может быть затруднительным. Вы должны проверить это с помощью чего-то простого (скажем, node.uid), чтобы быть вдвойне уверенным. Если простой тест работает, но ваш не работает, тогда я подозреваю, что вы столкнулись с проблемами с плавающей запятой.

Вы также можете просмотреть SQL, чтобы точно увидеть, что создается. Скопируйте/вставьте это в свой любимый инструмент SQL и посмотрите, что происходит.

Вы упомянули, что пытаетесь найти двадцать узлов, ближайших к точке. Ваш подход для этого неверен. Вам нужно добавить поле корреляции, которое возвращает возвращает расстояние между узлом в этой строке и вашей точкой, сортируйте по возрастанию, а затем ограничьтесь 20 результатами. Это не полная боль, но и не простая (я только что сделал это в проекте).

К счастью, есть по крайней мере два модуля, которые могут сделать это за вас. Один из них - Геополе, другой - Местоположение. Оба интегрируются с представлениями, и я знаю, что Геополе поддерживает сортировку по близости, и я почти уверен, что Местоположение делает это. Использование одного из них может потребовать преобразования ваших полей для использования полей, определенных модулем, но эти два модуля предоставляют и другие преимущества.

 1
Author: mpdonadio, 2017-05-23 11:33:47