在Drupal 7中,通过程序获取节点标题

9
我有一个模块,程序化地将许多节点添加到我的Drupal 7网站上。为了避免重复,我想要检查是否在系统中已经存在了刚刚新建的节点标题。永远不会有两个节点拥有相同的名称。我尝试使用node_load(),但似乎不能根据标题加载节点。
我被卡住了,所以想知道这里是否有人可以帮助我。
总结一下:如何检查某个标题的节点是否已经存在?
谢谢。

1
如果您愿意,我们可以将此移至我们的Drupal网站,这样可能会得到更好的覆盖范围。如果您希望我们这样做,请标记一下(但不要重复发布)。谢谢。 - Kev
相关:如何根据标题加载节点? 在DS上。 - kenorb
6个回答

18

节点是实体,因此您可以使用EntityFieldQuery类来查询它们。这样,您就不必担心信息在数据库中的存储方式。如果需要根据字段值添加其他筛选条件,代码演变也会更加容易。

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

这对于一个如此简单的查询来说是非常繁琐的开销,字段存储不扩展到实体属性,因此在这里使用EntityFieldQuery没有真正的好处。 - Clive
2
是的,使用EntityFieldQuery查询单个节点属性会有一些开销。但由于它仅适用于多节点创建过程,因此性能成本很可能是微不足道的。如果节点创建过程演变为需要检查多个条件,那么维护起来也会更容易。 - Pierre Buyle
如果您使用实体翻译和标题模块,则需要更新代码以查询title_field字段而不是title属性。 - Pierre Buyle
1
我知道这已经是多年之后的事了,但是这段代码中有一个错误——你不能链式调用PHP构造函数。在5.4及以上版本中,你可以使用(new EntityFieldQuery())->,但按照原来的写法,这应该会导致致命错误。 - Clive

8
您可以使用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 这是完成此任务的最佳方式。你应该考虑加入修订表,以获取最新版本的数据。 - Clive
请在编写自定义数据库查询时,将表名用花括号括起来。 - Pierre Buyle

4
这里有一个使用API和计数函数的D7方法。
$query = db_select('node', 'n')
  ->fields('n', array('nid'))
  ->condition('n.title', $myNewTitle, '=');

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

4

2

友情提醒:为了安全起见,您在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”标记的动态查询,请参见http://drupal.org/update/modules/6/7#db_rewrite_sql。 对于这种情况,重复标题检测并不需要担心节点访问限制。但是,对于节点使用动态查询是一个好习惯。 - Pierre Buyle
1
花括号仅在您的设置文件中设置了前缀时,才用于前缀表。这与SQL注入无关。我使用D7 sql API添加字段和条件,因此在您的示例中,如果我猜测,您的变量$myNewTitle没有被转义? - iLLin

1
正确的方法是在数据库中添加唯一索引。 这样你就可以确保所有标题都是唯一的。 很简单:
db_add_unique_key("{node}", "title_uniq", array("title"));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接