这些使用 db_or() 的 Drupal SQL 查询有什么问题?

What is wrong with these Drupal SQL queries using db_or()?

我工作的机构在我们的 Drupal CMS 和 LDAP 服务器之间有一个现有的和有效的集成。该集成的一个特点是能够从 LDAP 中提取记录以填充 Drupal 中的字段。我们告诉 Drupal 使用自定义模块填充哪些字段和内容类型,这些模块最初设计为仅容纳 (1) 内容类型的单个机器名称和 (2) 每个字段的单个机器名称。

我们现在正在尝试修改这些配置项,使其以逗号分隔的列表形式存在,这样我们就可以向任意数量的内容类型提供 LDAP 信息,这些内容类型不一定使用共享字段。对 (2) 的修改,即为一个字段输入多个机器名称并仍然用所需数据填充的能力,已经在起作用。但是,完成 (1) 所需的修改将允许记录输出到多种内容类型,这取决于 SQL 查询,我认为我的语法肯定是错误的。

存储内容类型的机器名称的配置项在 Drupal 内部称为 dart_netid_content_type。这是旧代码,适用于标识单一内容类型的单一机器名称:

// All nodes of type from dart_netid_content_type, with either no LDAP lookup time, or over 24 hours ago
$query = db_select('node');
$query->leftjoin('dart_ldap_update', 'ldap', 'node.nid = ldap.nid');
$query->fields('node', array('nid'))
  ->fields('ldap', array('nid', 'ldap_updated'))
  ->condition('type', variable_get('dart_netid_content_type', ''), '=')
  ->condition('status', '1', '=')
  ->condition(db_or()->condition('ldap_updated', NULL, 'IS')->condition('ldap_updated', $limit, '<'))
  ->orderby('ldap_updated', 'ASC');

这是新查询,应该适用于多种内容类型。有趣的是,查询并没有完全被破坏;如果您输入标识单一内容类型的单一机器名称,查询将继续工作。但是,如果您在 dart_netid_content_type 中存储一个逗号分隔的列表,它已经在处理其他配置项,例如应该用数据填充的字段的机器名称,则查询失败并且模块不会识别任何节点或填充它们的任何字段。

/*
 * Break up dart_netid_content_type into an array
 */
$dart_netid_content_type_array = explode(",", variable_get('dart_netid_content_type', ''));

/*
 * For each item in the array, create an 'or' conditional in a db_query that
 * checks for all of those content types
 */
$content_type_or = db_or();
foreach($dart_netid_content_type_array as $content_type) {
  $content_type_or->condition('type', $content_type, '=');
}

// All nodes of type from dart_netid_content_type, with either no LDAP lookup time, or over 24 hours ago
$query = db_select('node');
$query->leftjoin('dart_ldap_update', 'ldap', 'node.nid = ldap.nid');
$query->fields('node', array('nid'))
  ->fields('ldap', array('nid', 'ldap_updated'))
  ->condition($content_type_or)
  ->condition('status', '1', '=')
  ->condition(db_or()->condition('ldap_updated', NULL, 'IS')->condition('ldap_updated', $limit, '<'))
  ->orderby('ldap_updated', 'ASC');

以一种希望更直观的方式阐明这两个版本之间的预期差异:dart_netid_content_type 现在可能是一种内容类型,或不止一种。之前的查询正在搜索类似于 WHERE type = dart_netid_content_type 的内容。我现在试图哄它做的是查看 dart_netid_content_type_array 中的各个项目并进行类似于 WHERE (type = dart_netid_content_type_array[0]) OR (type = dart_netid_content_type_array[1]) OR ... OR (type = dart_netid_content_type_array[sizeof(dart_netid_content_type_array)]).

的查询

在 Drupal 的 db_query 和 db_or 语法中包装时,我的逻辑似乎有问题。

如果需要,我可以通过共享更多驱动 LDAP 到节点功能的自定义模块来提供更多上下文。

预先感谢您的帮助。

如何使用 IN 确定内容类型是否在值数组中?像这样:

$dart_ct_array = explode(",", variable_get('dart_netid_content_type', ''));
$dart_netid_content_types = "('" . implode("','", $dart_ct_array) . "')";

$query = db_select('node');
$query->leftjoin('dart_ldap_update', 'ldap', 'node.nid = ldap.nid');
$query->fields('node', array('nid'))
  ->fields('ldap', array('nid', 'ldap_updated'))
  ->condition('type', $dart_netid_content_types, 'IN')
  ->condition('status', '1', '=')
  ->condition(db_or()->condition('ldap_updated', NULL, 'IS')->condition('ldap_updated', $limit, '<'))
  ->orderby('ldap_updated', 'ASC');