Пользовательские модули Drupal и проблема с кешем

Мы создали несколько пользовательских модулей для сайта 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

Решение

Прежде всего, есть несколько проблем с этим кодом. Если вы собираетесь использовать Drupal, вам нужно придерживаться Стандарты кодирования Drupal. Избегайте использования верблюжьей оболочки для переменных, вместо этого следует использовать подчеркивание. Также вы должны использовать 2 пробела для отступа.

В вашей функции информации о блоке вы определяете один блок, но назначаете его неназначенной переменной:

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

$blocks['website_actualites'] = array(

Следующая проблема заключается в том, что вы звоните hook_block_view($delta)этот звонок будет уволен за каждый дельта блока, и независимо от дельты блока вы устанавливаете его null (также для дальнейшего использования NULL):

$block = null;

Таким образом, Drupal создает массив рендеринга для каждого блока, а вы стираете все данные. Вы делаете это, потому что вы пытаетесь использовать дельту блока как способ передачи параметра в блок с дельтой, подобной website_actualites+10, Блоки не предназначены для такой работы, а дельта-элементы должны быть статическими, чтобы 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', ...); Вы должны определить эту функцию темы в hook_theme() вызов, предположительно, вы сделали это в другом модуле, что прекрасно, но не забудьте добавить зависимость от этого модуля в ваш файл 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.

Дальнейшее чтение: Визуализация массивов в Друпале 7

Надеюсь, что эта информация помогает и делает ее немного понятнее.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]