【问题标题】:drupal 7 | db_select | date_field condition德鲁巴 7 |数据库选择 |日期字段条件
【发布时间】:2016-07-06 08:43:18
【问题描述】:

在 hook_user_login 上,我想删除给定内容类型的登录用户拥有的超过 21 天的节点。

下面的代码可以正常工作(没有日期条件):

function mymodule_user_login(&$edit, $account) {
  global $user;
  $myuid = $user->uid;
  $mytype = 'testdelete';
  $mydate = '2016-07-06 18:45:00';

  $results = db_select('node', 'n')
        ->fields('n', array('nid'))
        ->condition('type', $mytype)
        ->condition('uid', $myuid)
        ->execute();

  foreach ($results as $result) {
    $nids[] = $result->nid;
  }

  if (!empty($nids)) {
    node_delete_multiple($nids);
    drupal_set_message(t('%count nodes has been deleted', array('%count' => count($nids))));
  }
}

现在我坚持了一个多星期以来的日期条件。我的日期字段是内容类型“testdelete”被称为“基准”,小部件是弹出日历。

我试过了:

->fields('n', array('nid','field_datum'))

->fields('n', array('nid','datum'))

两者都导致异常:

PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'n.field_datum' in 'field list': SELECT n.nid AS nid, n.field_datum AS field_datum FROM {node} n WHERE (type = :db_condition_placeholder_0) AND (uid = :db_condition_placeholder_1) ; Array ( [:db_condition_placeholder_0] => testdelete [:db_condition_placeholder_1] => 4 ) in mymodule_user_login() 

条件应该如何:

->condition('datum', $mydate,'<')  

而 $mydate 应该类似于:now() -21 days

其他问题:

我担心 hook_user_login 不适合这份工作,或者这样可以吗?
我应该改用 hook_cron 之类的东西吗?

【问题讨论】:

  • 为什么不在Drupal Answers发帖?
  • 对不起 - 我下次会这样做

标签: date drupal conditional-statements


【解决方案1】:

要根据字段值选择节点集合,您应该使用EntityFieldQuery 而不是db_select()db_select() 是一个简单的查询编写工具,假设您知道数据库中使用的存储结构。 EntityFieldQuery 旨在抽象出数据存储,让您只了解内容类型结构。

在你的情况下,它看起来像:

$query = new EntityFieldQuery();

$query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'testdelete')
  ->entityCondition('uid', $myuid)
  ->fieldCondition('field_datum', 'value', $mydate, '<')

$results = $query->execute();

至于hook_user_login()hook_cron(),这取决于您的目标。如果您希望无论用户活动如何都在时间线之后删除内容,hook_cron() 是一个更好的选择。如果您希望内容保留到用户返回,那么hook_user_login() 是正确的工具。

使用hook_user_login(),如果您的用户生成了大量需要在登录时删除的内容,您可能无法及时处理所有必需的任务。如果是这种情况,您将需要考虑创建批处理作业或使用 Drupal 的任务队列来让 Drupal 由于时间密集型工作而不会强迫用户等待它完成。

【讨论】:

    【解决方案2】:

    您的 db_select 查询只是从节点表中进行选择。
    但是,字段值存储在它们自己的表中。
    要使用日期字段执行 db_select,您必须加入 datnum 字段表。
    例如(未测试):

    $query = db_select('node', 'n');
    $query->join('field_data_field_datnum', 'datnum', 'n.nid = datnum.entity_id');
    $query->fields('n', array('nid'));
    $query->fields('datnum', array('datnum_value'));
    // add conditions here
    

    更好的选择可能是使用EntityFieldQuery
    EntityFieldQuery的使用方法可以看HERE

    至于在HOOK_user_login中做,这真的取决于你的情况。
    在高流量网站上,在用户登录时执行此操作可能不是一个好主意。
    我会在 HOOK_cron 上做。

    【讨论】:

      【解决方案3】:

      谢谢你们,

      @acrosman - 我用你的方法做了两个小改动

      ->propertyCondition('uid', $myuid,'=')
      

      和一个“;”在

      的末尾
      ->fieldCondition('field_datum', 'value', $mydate, '<');
      

      对于可能有相同问题的所有其他人
      我关于删除节点的初始问题的代码

      foreach ($results as $result) {
          $nids[] = $result->nid;    }
      

      等等.....不再起作用了

      我使用了以下代码,效果很好

      foreach($results['node'] as $node){
          node_delete($node->nid);
      } 
      

      谢谢大家
      汤姆

      【讨论】:

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