【问题标题】:Programmatically getting nodes by title in Drupal 7在 Drupal 7 中以编程方式按标题获取节点
【发布时间】:2011-12-03 18:01:12
【问题描述】:

我有一个模块,它以编程方式将大量节点添加到我的 Drupal 7 站点。为了防止重复,我想检查我新创建的节点的标题是否不存在于系统中。永远不会有两个节点具有相同名称的情况。我试过使用node_load(),但这似乎不允许我根据标题加载节点。

我不知道如何继续,所以我想知道这里是否有人可以帮助我。

总结一下:如何检查某个标题的节点是否已经存在?

谢谢。

【问题讨论】:

  • 如果您愿意,我们可以将其移至我们的 [Drupal 站点](drupal.stackexchange.com),在那里它可能会得到更好的覆盖。如果您希望我们这样做,请标记(但不要交叉发布)。谢谢。

标签: drupal drupal-7 drupal-modules


【解决方案1】:

节点是实体,因此您可以使用EntityFieldQuery 类来查询它们。这样,您就不必担心信息是如何存储在数据库中的。而且,如果您需要根据字段值添加额外的过滤器,代码演变将很容易。

$result = (new EntityFieldQuery())
  ->entityCondition('entity_type', 'node')
  ->propertyCondition('title', $title)
  ->execute();
$title_is_unique = empty($result['node']);

【讨论】:

  • 对于这样一个简单的查询来说,开销太大了,字段存储不会扩展到实体属性,所以在这里使用 EntityFieldQuery 没有真正的好处
  • 是的,使用 EntityFieldQuery 查询单个节点属性存在一些开销。但由于它仅适用于多节点创建过程,因此性能成本很可能是微不足道的。如果节点创建过程演变成需要检查多个条件的东西,维护起来会更容易。
  • 如果使用实体翻译和Title模块,需要更新代码以查询title_field字段而不是title属性。
  • 我知道这是多年以后的事了,但这段代码有一个错误——你不能链接 PHP 构造函数。在 5.4 及更高版本中,您可以使用 (new EntityFieldQuery())->,但正如所写,这应该会产生致命错误
【解决方案2】:

您可以使用如下 SQL 查询获取所有节点标题:

 $row = db_query('SELECT nid FROM {node} WHERE title = :mytitle', array(':mytitle' => $myNewTitle))->fetchField();
 if(!isset($row['nid'])) {
    //safe to continue
 } else {
    //that title is already there and its in node with node id "nid"
 }

如果没有返回结果,那么你可能会认为你很好。

或者您也可以编辑节点表以使标题字段唯一并处理 MySQL 抛出的错误。不过真的不知道这有多可行。

【讨论】:

  • +1 这是完成此任务的最佳方式。您应该考虑加入修订表以获取最新版本的数据
  • 请在编写自定义数据库查询时将您的表名用大括号括起来。
【解决方案3】:

这是利用 API 和计数函数的 D7 方法。

$query = db_select('node', 'n')
  ->fields('n', array('nid'))
  ->condition('n.title', $myNewTitle, '=');

return $query->countQuery()->execute()->fetchField();

【讨论】:

    【解决方案4】:
    node_load_multiple(array(), array('title' => $title));
    

    来源:DrupalWebTestCase::DrupalGetNodeByTitle的胆子

    【讨论】:

      【解决方案5】:

      只是一个友好的提示。为了安全起见,您应该始终在 drupal sql 查询中的表周围使用大括号!它可以防止 SQL 注入攻击。

      应该是这样的:(注意 {node} )

       $row = db_query('SELECT nid FROM {node} WHERE title = :mytitle', array(':mytitle' =>   $myNewTitle))->fetchField();
       if(!isset($row['nid'])) {
          //safe to continue
       } else {
          //that title is already there and its in node with node id "nid"
       }
      

      【讨论】:

      • 对于节点查询,似乎为了使节点访问限制检查正常工作,您必须使用带有“node_access”标签的动态查询,请参阅drupal.org/update/modules/6/7#db_rewrite_sql。对于这种情况,这并不重要,因为重复标题检测不应该担心节点访问限制。但是对节点使用动态查询是一个好习惯。
      • 如果您在设置文件中设置了前缀,则大括号仅用于为表格添加前缀。与 SQL 注入无关。我使用 D7 sql API 添加字段和条件,所以在您的示例中,如果我猜的话,您的变量 $myNewTitle 没有被转义?
      【解决方案6】:

      正确的方法是给数据库添加一个唯一索引。 然后,您将确保所有标题都是独一无二的。 很简单:

      db_add_unique_key("{node}", "title_uniq", array("title"));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-27
        • 1970-01-01
        相关资源
        最近更新 更多