В 7 Drupal, я писал всю логику прямо в шаблоне вьюса, в шаблоне полей переопределял их значение.
И в самом шаблоне делал необходимые запросы к базе и сравнивал с данными во вьюсе а потом уже менял значения полей в зависимости от условий. И меня это ни сколько не смущало, все работало и не ломалось.
Но в 8 Drupal twig и в него данные приходят уже готовые, остается только сделать вставки в нужных местах.
Вопрос: как в Drupal 8, изменять данные вьюса до того как они приетят в шаблон, какой хук использовать?
попробовал <?php functionhook_views_pre_render(ViewExecutable $view) ?>
, а чтобы изучить содержимое переменной $view, распечатывал ее через
<?php
drm($view) ?>
.
Проблема в том что переменная распечатывается один раз пока не обновишь страницу.
Сама переменная является большим массивом с данными, наверняка есть какие-то дополнительные методы, для того чтобы извлечь значения полей, фильтров и других параметров из этого массива, а потом записать их обратно, потому что напрямую по цепочке массива я до них дойти так и не смог.
На этом шаге полный тупик, не понял куда двигаться.
Сейчас только изучаю D8, но по опыту работы с 7 знаю, что переопределять поля менять структуру даных в зависимости от условий требуется практически в каждом проекте.
Комментарии
А можно хоть один конкретный пример из жизни, чтоб понимать о чем речь?
Пример кода сейчас привести не смогу.
Но вот пример из жизни
Допустим у нас сдаются в аренду объекты недвижимости или автомобили, не принципиально.
На этот предмет указана стоимость аренды за сутки.
И если срок аренды больше 7 дней то действует скидка 10%.
Ну и еще какие-то дополнительные условия могут применяться. Например, идти запрос в базу данных, по текущему пользователю, чтобы предоставить ему персональную скидку, если он накопил, какие нибудь баллы, бонусы, достиг какого-нибудь уровня.
Допустим, пользователь через фильтр выбрал даты, с какого по какое число он хочет арендовать предмет.
во вьюсе выводится базовая стоимость аренды в сутки.
Но в шаблон я хочу прокинуть дополнительную переменную в которой будет содержаться расчетная стоимость. То есть цена в сутки умноженная на количество дней, а так же с проверкой на условие: больше или меньше 7 дней.
Это всё легко делается прямо в админке вьюс через перезапись полей и "твиг-арифметику". Одной из наиболее мощных (и наиболее тщательно скрытых) возможностей вьюс является то, что при перезаписи полей можно пользоваться всей мощью языка твиг, а не только тупой подстановкой одного поля вместо другого.
При формировании вьюса нужно все необходимые для расчетов данные вывести в качестве полей и спрятать. Потом вся логика и расчеты с участием этих скрытых полей делаются прямо в админке путем перезаписи поля с использованием синтаксиса твиг. Просто прочтите доку по твигу или обучающий курс какой-нибудь. Результат гораздо более наглядный и легко сопровождаемый, чем стопитьсот строк спагетти-кода, рассованного по хукам.
Админка - конечно хорошо, так и буду поступать, потому что сейчас других решений не знаю, кроме тех что мне предлагают.
Но может быть вы знаете как это же сделать и использованием api?
В рамках этой задачи конечно подходит.
Но как я говорил, есть же и прямые запросы к базе, чтобы получить данные которые не закреплены за сущностью в виде каких-то полей, или, что еще интереснее, если эти данные будут подтягиваться с какого то сервиса, с удаленного сервера без какого-либо кеша и потом же выводиться.
Не строить же мне полностью всю логику с нуля из за этого, чтобы создать собственный вывод. Когда можно сказать что он уже есть, мне просто его надо видоизменить, пересчитать перезаписать, и т.д
Вот в качестве примера кусок работающего кода, цинично модифицирующего массив результатов:
* Implements hook_views_pre_render().
*/
function MODULE_views_pre_render(Drupal\views\ViewExecutable $view) {
if ($view->id() !== 'photo_slideshow' || !in_array($view->current_display, ['photo_gallery', 'artist_gallery', 'user_gallery'])) return;
/* debug($view->result[0], 'debug'); */
$unique_uuids = $new_view_result = [];
$new_row_index = 0;
// Loop through results and filter out duplicate results.
foreach ($view->result as $row) {
// Use UUID so this works for all entities
$uuid = $row->_entity->uuid();
if (!in_array($uuid, $unique_uuids)) {
$row->index = $new_row_index;
$new_view_result[] = $row;
$unique_uuids[] = $uuid;
$new_row_index++;
}
}
// Replace $view->result with new array. Apparently views requires sequentially keyed
// array of results instead of skipping keys (e.g. 0, 2, 4, etc), so we can't just
// unset the duplicates.
$view->result = $new_view_result;
// Update the view index to match the new number of rows.
$view->total_rows = $new_row_index;
if ( $view->total_rows > 8) return;
$view->field['field_picture']->options['settings']['photoswipe_node_style'] = /* $view->total_rows > 1 ? */ 'large_gallery_thumbnail' /* : '' */;
}
До этого хука дошёл, но при попытке распечатать $view->result браузер на рабочем ноутбуке умер.
Значит в правильном направлении, если это можно так назвать, шел
Там огромные рекурсивные массивы, на попытке их вывести целиком что хочешь умрет. Мне иногда помогают модули Devel и Devel Debug Log, но на некоторых массивах и они бессильны.
Да, вместо $view->result есть смысл попробовать вывести хотя бы $view->result[0], так информации меньше, а строки не сильно друг от друга отличаются.
Оъявите новый вьюмод у сущности.
Во вьюхе, вместо полей, выводите сущность(и) в новом вьюмоде
В препроцессе вьюмода описывайте нужную кастомную логику и результаты передавайте в шаблон
В шаблоне выводите всё что нужно
Какой хук для этого лучше всего подойдет?
как раз и хочется отделить логику от шаблона, чтобы не делать расчеты там, где из быть не должно
но ведь для фильтра вьюса это не подойдет? то есть в шаблон то я не смогу передать данные из фильтра
Это легко делается через интерфейс: /admin/structure/display-modes/view
я имел в виду то что вы сказали про препроцесс вьюмода.
Попробую поискать сейчас сам
Понимаю, что Вам этого слышать не хочется, но все это пздц какой говнокоддинг.
Объявите свой форматтер поля, это 1 плагинчик. Там, решайте всю логику.
И это будет работать везде, и в представлениях, и в обычном выводе материала, во всех других местах вывода полей.
Оставьте шаблонам те задачи, которые на них возложены.
Так я и не хочу лезть в шаблон, вопрос этому и посвящен.
Хочу узнать и понять где строится логика, как переопределить содержимое массива данных передаваемых потом в шаблон вьюса.
Ладно тут я еще такой пример привел, но другой пример, когда в зависимости от данных в одной строке, эти данные должны меняться в другой. И это нормально делается если пробежаться по массиву с нужным условием.
Но как получить доступ к массиву элементов выводимых во вьюсе, а тем более как переопределить их значения не пойму.
Вьюс мне нравится тем, что есть массив с которым можно работать, гибкая штука, которую я могу изменять как хочу.
но не пойму как добрать до этого массива в восьмерке.
Гляньте какие есть точки входа, подберите наиболее подходящую: https://api.drupal.org/api/drupal/core%21modules%21views%21views.api.php...