这些使用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');