Как обмениваться переменными между двумя preprocess?

Главные вкладки

Аватар пользователя Victorzzz Victorzzz 25 января 2018 в 22:16

Есть theme_preprocess_views_view_unformatted и theme_preprocess_page

В theme_preprocess_views_view_unformatted я получаю некое значение, которое мне нужно затем использовать в theme_preprocess_page. Соответственно мне надо передать переменную. Это возможно?

Drupal 7

Комментарии

Аватар пользователя bumble bumble 25 января 2018 в 23:00

UPD - но важно, чтоб на момент когда переменная будет нужна, она уже была заполнена. Т.е. фактически, чтоб на момент выполнения theme_preprocess_page уже был выполнен theme_preprocess_views_view_unformatted.

Аватар пользователя Victorzzz Victorzzz 26 января 2018 в 0:11

Вообще я пока эксперементирую, как правильно сделать, и может быть не туда копаю, но пока я ещё только ищу варианты решения. Но задача примерно следующая:
На всех страницах сайта в подвал выводятся данные, генерируемые собственным модулем: массив со списком ID. Причем каждый раз в случайном порядке: shuffle(&array). Т.е. функция модуля генерит список id, а затем в page.tpl.php на основе этого списка выводятся блоки, по одному блоку на id из массива. В модуле я устанавливал переменную variable_set, а затем в page.tpl.php брал значения через variable_get.
Теперь понадобилось, чтобы на страницах views часть блоков (4) выводилась не в подвале, а посреди результатов вьюхи, между 5 и 6 рядом, а в подвал выводились только все оставшиеся, например ещё 7 блоков.
Итого например если у меня 11 id, и соответственно 11 блоков, то надо чтобы на всех страницах, кроме вьюх, в подвале выводилось 11 блоков, а на страницах вьюх 4 блока в результатах вьюхи в середине списка, и ещё 7 оставшихся в подвале.
При этом важно, чтобы блоки при каждом заходе на страницу, перемешивались между собой в случайном порядке.
views-view-unformatted.tpl.php у меня переопределен и просто 4 блока из 11 я могу вывести. Но настроить связь между views-view-unformatted.tpl.php и page.tpl.php у меня пока не получается

Аватар пользователя Semantics Semantics 26 января 2018 в 0:08

Victorzzz wrote:

В модуле я устанавливал переменную variable_set, а затем в page.tpl.php брал значения через variable_get.

Как минимум, это уже неправильно.
Вы если делаете variable_set(), то у вас кеш сбрасывается, если делаете это на каждой странице, то дико теряете в производительности.

Вам скорее подойдёт static-кеширование в helper-функции или синглтон

Аватар пользователя negociant negociant 26 января 2018 в 0:10

bumble wrote:

UPD - но важно, чтоб на момент когда переменная будет нужна, она уже была заполнена. Т.е. фактически, чтоб на момент выполнения theme_preprocess_page уже был выполнен theme_preprocess_views_view_unformatted.

1 - preprocess_page выполняется после preprocess_views_view_unformatted, хотя могло бы быть и наоборот.
2 - preprocess_views_view_unformatted выполняется сколько угодно раз. В какой из исполнения функции static переменная запишет нужное значение? Правильно - при последнем вызове. Продолжать костылить и проверять для какой вьюхи и для какого дисплея был вызван препроцесс?
3 - вообще идея передавать переменную в виде static между функциями является костылем, так как нельзя надеяться на порядок вызова функций и количество их вызовов.
4 - если в preprocess_page нужно получить какую то переменную, то нужно в теле функции определить нужное значение и записать его в переменную (опишите подробней, что нужно получить в переменную).
ХулиGUN wrote:

ИМХО, вы что-то делаете не так. Опишите саму задачу, а не что сделать нужно.

Это из серии когда не друпал разработчик почему то предлагает более здравую мысль, чем друпал разработчик.

Аватар пользователя bumble bumble 26 января 2018 в 0:15

Я не советовал так делать, а только отвечал на вопрос "как это можно сделать", и объяснил как с этим работать.

Аватар пользователя negociant negociant 26 января 2018 в 0:28

Victorzzz wrote:

Теперь понадобилось, чтобы на страницах views часть блоков (4) выводилась не в подвале, а посреди результатов вьюхи, между 5 и 6 рядом, а в подвал выводились только все оставшиеся, например ещё 7 блоков.

Определить, что открыта страница вьюхи можно функцией views_get_page_view . Эта же функция и возвращает объект вьюхи. Далее пишите свою логику отталкиваясь от результатов $view->result

<?php
/* 
 * Implements hook_preprocess_page
 */
function THEMENAME_preprocess_page(&$variables){
  
$view views_get_page_view();
  if(isset(
$view) && $view->name == 'YOUR_VIEWS_MACHINE_NAME') {
    
// результаты вьюхи в массиве $view->result
  
}
}
?>
Аватар пользователя Victorzzz Victorzzz 26 января 2018 в 17:24

negociant wrote:

Определить, что открыта страница вьюхи можно функцией views_get_page_view . Эта же функция и возвращает объект вьюхи. Далее пишите свою логику отталкиваясь от результатов $view->result

Спасибо. Да, конечно. Это само собой. Моя ошибка была в том, что я зачем-то решил логику раскидать на несколько preprocess функций. Частично задуманное заработало при использовании variable_set и variable_get, но это, во-первых, как написали выше, неверно с точки зрения производительности, а во-вторых все равно не работало так как задумано, из-за изначально неправильной логики.

В итоге я весь расчет условий поместил в hook_preprocess(), после чего обмен переменными между препроцессами стал не нужен и все стало на свои места.

<?php
/**
 * Implements hook_preprocess().
 */
function mytheme_preprocess(&$variables$hook) {
...
}
?>

https://api.drupal.org/api/drupal/includes%21theme.inc/function/template...

Аватар пользователя negociant negociant 26 января 2018 в 17:54
1

Victorzzz wrote:

Моя ошибка была в том, что я зачем-то решил логику раскидать на несколько preprocess функций.

Victorzzz wrote:

но это, во-первых, как написали выше, неверно с точки зрения производительности

Victorzzz wrote:

В итоге я весь расчет условий поместил в hook_preprocess()

Сильный ход вынести всю логику в hook_preprocess, который вызывается перед каждым препроцессом. hook_preprocess может быть вызван сотни раз для одной страницы и вы в каждом из них будете производить свои вычисления? Это фиаско, братан.

Аватар пользователя Victorzzz Victorzzz 26 января 2018 в 18:20

Ну я сделал вот так:

<?php
function mytheme_preprocess(&$variables$hook) {
  
  if (
$hook == 'node' || $hook == 'page' || $hook == 'views_view_unformatted') {
    
логика тут
  
}

}

?>

Вот так у меня к примеру в шаблоне вьюхи не видит переменную $my_var

<?php
function mytheme_preprocess_page(&$variables$hook) {
  
$variables['my_var'] = 'value';
}
?>

Вот из документации друпала: https://www.drupal.org/docs/7/theming/overriding-themable-output/setting...

<?php
function drop_preprocess(&$variables$hook) {

  

// Shared between the 'foo' and 'bar' theming hooks.
  
if ($hook == 'foo' || $hook == 'bar') {
    
$variables['foobar_item'] = 'foobar item';
  }

  

// Specific to 'foo'.
  
if ($hook == 'foo') {
    
$variables['foo_item'] = 'foo item';
  }
  
// Specific to 'bar'.
  
elseif ($hook == 'bar') {
    
$variables['bar_items'] = 'bar item';
  }
}
?>
Аватар пользователя negociant negociant 26 января 2018 в 18:34

Victorzzz wrote:

if ($hook == 'node' || $hook == 'page' || $hook == 'views_view_unformatted') {
    
логика тут
  
}

Так а сколько раз в конечном итоге будут вызваны preprocess_node/preprocess_views_view_unformatted и hook_preprocess?

Аватар пользователя Victorzzz Victorzzz 26 января 2018 в 18:41

Хорошо, признаю, я не прав. Как мне заставить views-view-unformatted--myview--page.tpl.php увидеть мой $my_var из

<?php
function THEMENAME_preprocess_page(&$variables){
...
$variables['my_var'] = 'value';
...
}
?>

Вместо Notice: Undefined variable: my_var ?

Аватар пользователя negociant negociant 26 января 2018 в 18:51

Victorzzz wrote:

Хорошо, признаю, я не прав. Как мне заставить views-view-unformatted--myview--page.tpl.php увидеть мой $my_var из

Получить $my_var точно так же, как и в preprocess_page.

Аватар пользователя Victorzzz Victorzzz 26 января 2018 в 19:02

preprocess:

<?php
function mytheme_preprocess_page(&$variables) {
  
$variables['my_var'] = 'My Value';
}
?>

views-view-unformatted--myview--page.tpl.php:


<?php print $my_var?>

Итог: Notice: Undefined variable: my_var в функции include() ...