Drupal自定义模块和缓存问题

时间:2015-04-09 08:27:34

标签: php drupal drupal-7 drupal-modules

我们为Drupal网站创建了一些自定义自定义模块,我们遇到以下问题:每次创建或更新内容时(无论是什么),自定义模块生成的内容都会消失。我们必须清除所有缓存才能再次显示此内容。

由于这是我们第一次使用Drupal,我们肯定错过了一些东西,但我们不知道是什么。

非常感谢任何帮助!

以下是其中一个自定义模块的代码:

文件website_actualites.module

    <?php
/**
 * Implements hook_block_info().
 */
function website_actualites_block_info() {
    $blocks['website_actualites'] = array(
        'info' => t('website_actualites'),
        'cache' => DRUPAL_CACHE_PER_ROLE,
    );
    return $blocks;
}

/**
 * Implements hook_block_view().
 */
function website_actualites_block_view($delta = '') {
    $aDelta = explode('+', $delta);
    $nbActualite = 2;
    if (!empty($aDelta[1])) {
        $nbActualite = $aDelta[1];
    }
    $block = null;
    switch ($aDelta[0]) {
        case 'website_actualites':
            $block['content'] = _website_actualites_sweet_block_content($nbActualite);
            break;
    }
    return $block;
}

/**
 * Callback implemented by hook_block_view().
 */
function _website_actualites_sweet_block_content($nbActualite=2) {
    $query = new EntityFieldQuery();
    $query->entityCondition('entity_type', 'node')
        ->entityCondition('bundle', 'article')
        ->propertyCondition('status', 1)
        ->fieldCondition('field_mise_en_avant', 'value', 1)
        ->propertyOrderBy('created', 'DESC')
        ->range(0, $nbActualite)
        ->addMetaData('account', user_load(1));
    $result = $query->execute();

    // width col pour nb actu=2 : 4,8
    // width col pour nb actu=4: 2,4,2,4

    $colWidthEven=4;
    $colWidthOdd=8;
    if (4 == $nbActualite) {
        $colWidthEven=2;
        $colWidthOdd=4;
    }

    $data = array();
    if (isset($result['node'])) {
        $nids = array_keys($result['node']);
        $items = entity_load('node', $nids);

        $i=0;
        foreach ($items as $item) {
            $colWidth=$colWidthOdd;
            if (0 == $i%2) {
                $colWidth = $colWidthEven;
            }
            $i++;
            $data[$item->nid] = array(
                'title' => $item->title,
                'tags' => isset($item->fielsTags['und'][0]) ? $item->fielsTags['und'][0] : '',
                'body' => isset($item->body['und'][0]['value']) ? $item->body['und'][0]['value'] : '',
                'image' => isset($item->field_image['und'][0]) ? $item->field_image['und'][0] : '',
                'nid' => $item->nid,
                'col-width' => $colWidth,
                'alias' => drupal_get_path_alias('node/'.$item->nid)
            );
        }
    }

    $static_title = t('Static Title');
    $static_content = 'static content';



    return theme('website_actualites_output', array(
            'title' => $static_title,
            'content' => $static_content,
            'data' => $data
        )
    );
}

文件website_actualite-sweet - block.tpl.php

<?php

foreach ($data as &$row) {
    $url = drupal_get_path_alias('node/' . $row['nid']);
    $imageWrapper = file_stream_wrapper_get_instance_by_uri($row['image']['uri']);
    if (is_object($imageWrapper) && is_callable(array($imageWrapper, 'getExternalUrl'))) {
        $imageUrl = $imageWrapper->getExternalUrl();
        print '<div class="col-sm-'.$row['col-width'].'">
                    <div class="img">
                        <a href="/'. $url .'"><img src="' . $imageUrl . '" class="img-responsive" alt="image description"></a>
                    </div>
                    <p><a href="/'. $url .'">' . $row['title'] . '</a></p>
                </div>';
    }
}

1 个答案:

答案 0 :(得分:1)

首先,此代码存在一些问题。如果您打算使用Drupal,那么您需要坚持使用Drupal coding standards。避免使用驼峰套管用于变量,而应使用下划线。你也应该用2个空格来缩进。

在块信息功能中,您可以定义单个块,但是将其分配给未分配的变量:

// Define $blocks first.
$blocks = array();

$blocks['website_actualites'] = array(

下一个问题是,您致电hook_block_view($delta),此次调用将针对每个块增量触发,无论您是否将块增量设置为null(同样供将来参考应为NULL):

$block = null;

因此Drupal正在为每个块构建渲染数组,并且您正在擦除所有数据。您这样做是因为您尝试使用块增量作为将参数传递到具有website_actualites+10等增量的块的方法。块不是以这种方式工作的,而delta是静态的,因此Drupal可以在数据库中跟踪它们并根据缓存标志执行正确的缓存。您已在website_actualites中定义了增量hook_block_info(),但Drupal没有任何其他块增量的知识或配置信息。

如果您需要相同的块来显示不同的数量,那么只需定义几个块(在hook_block_info()中)并调用与您现在相同的辅助函数。如果需要配置块,则应使用hook_block_configure() API

现在您传递到主题函数的数据,您正在使用:$item->field_image['und'][0]从节点对象中提取字段数据。这里有几件事:字段由字段模块提供,字段模块具有用于检索字段数据的扩展API。您应该使用field_get_items()代替,它将返回与该实体的该字段关联的所有项目的数组(因为字段可以是多值的)并为您处理语言。另一件事是永远不要使用'und'使用常量LANGUAGE_NONE

$body = field_get_items('node', $item, 'body');
$field_image = field_get_items('node', $item, 'field_image');
$field_tags = field_get_items('node', $item, 'field_tags');

$data[$item->nid] = array(
  'title' => $item->title,
  'tags' => $field_tags ? $field_tags : FALSE,
  'body' => $body ? $body[0] : FALSE,
  'image' => $field_image ? $field_image[0] : FALSE,
  'nid' => $item->nid,
  'col-width' => $colWidth,
  'alias' => drupal_get_path_alias('node/'.$item->nid)
);

另一个问题是您将$block['content']设置为theme('website_actualites_output', ...)的结果。现在这个函数将返回标记,在我们需要渲染任何标记之前,Drupal在链中有更多的调用,现在调用它的问题是你现在不能在构建过程中的任何时候改变你的数据。

为了调用theme('website_actualites_output', ...); You need to have defined this theme function in a hook_theme() call,大概是你在另一个模块中完成了这个,这很好但是记得在module.info文件中添加对该模块的依赖。你真正想要做的只是向Drupal构建添加指令,而不是标记:

return array(
  '#theme' => 'website_actualites_output',
  '#title' => $static_title,
  '#content' => $static_content,
  '#data' => $data
);

然后我们来到你的模板,你的模板中有很多逻辑,它们只用于显示带有标记的内容,理想情况下没有,或者只有最小的计算。主题函数在hook_preprocess()之前调用hook_process(),然后将变量传递到模板中。

您正在使用此主题函数循环$data变量以显示标记 - 理想情况下,主题函数将只是已经处理并传递到其中的变量的标记:

网站actualites输出 - child.tpl.php

<div class="col-sm-<?php print $col_width; ?>">
  <?php if ($image): ?>
    <div class="img">
      <?php print render($image); ?>
    </div>
  <?php endif; ?>
  <?php if ($title): ?>
    <p><?php print render($title); ?></p>
  <?php endif; ?>
</div>

在这个示例中,您最好的选择是使用上述模板设置第二个主题函数website_actualites_output__child

/**
 * Implements hook_theme().
 */
function website_actualites_theme() {
  $templates = drupal_get_path('module', 'website_actualites') . '/templates';
  return array(
    'website_actualites_output__child' => array(
      'path' => $templates,
      'template' => 'website-actualites-output--child',
      'variables' => array(
        'col_width' => 4, // Default col width.
        'image' => NULL,
        'title' => NULL,
      ),
    ),
  );
}

然后预处理当前的主题函数:

/**
 * Implements hook_preprocess_HOOK().
 */
function website_actualites_preprocess_website_actualites_output($variables) {
  $processed_output = array();

  $data = $variables['data'];
  foreach ($data as $row) {
    $image = array(
      '#theme' => 'image',
      '#path' => file_create_url($row['image']['uri']),
      '#alt' => $image['alt'],
      '#attributes' => array('class' => array('img-responsive')),
    );

    $processed_output[] = array(
      '#theme' => 'website_actualites_output__child',
      '#col_width' => $row['col-width'],
      '#image' => array(
        '#theme' => 'link',
        '#path' => 'node/' . $row['nid'],
        '#text' => $image,
        '#options' => array('HTML' => TRUE),
      ),
      '#title' => array(
        '#theme' => 'link',
        '#path' => 'node/' . $row['nid'],
        '#text' => $row['title'],
      ),
    );
  }

  // Reassign the $data variable so that we can just render() it.
  // var_dump($processed_output) to get a better idea what's going on here.
  $variables['data'] = $processed_output;
}

然后,您在当前模板中需要做的就是:

<?php if ($data): ?>
  <?php print render($data); ?>
<?php endif; ?>

你可以把这包装成你喜欢的任何标记。

Drupal学习曲线很高,但请记住,如果其他人在您之后维护此代码,他们会期望您遵守Drupal编码标准并遵循Drupal构建的过程。

进一步阅读:Render Arrays in Drupal 7

希望这些信息有所帮助并使其更清晰。