Рейтинг:2

How to create a view filter which display nodes if "field1" - "field2"

флаг sa

I have a content type with 2 fields: field1 and field2

I would like to create a view filter which display node based on a calculation on those two fields.

The filter should display only nodes if field1 - field2 is lower then a given amount.

Here is my try: At the end of the code, I don't know how to create the query

 class Myfilter extends FilterPluginBase implements ContainerFactoryPluginInterface {

  protected ViewsHandlerManager $joinHandler;

  private int $amount;

  public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteMatchInterface $route_match, ViewsHandlerManager $join_handler) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->joinHandler = $join_handler;
    $this->amount = 0;
    if (($node = $route_match->getParameter('node')) && ($node->bundle()=='my_bundle')) {
      $this->amount = $node->get('field_inv_amount')->value;
    }

  }

  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration, $plugin_id, $plugin_definition,
      $container->get('current_route_match'),
      $container->get('plugin.manager.views.join')
    );
  }

  public function query() {
    //parent::query();
    
    $fields = [
      'field1',
      'field2',
    ];
    foreach ($fields as $field) {
      $table_field_name = 'node__' . $field;
      $configuration = [
        'table' => $table_field_name,
        'field' => 'nid',
        'left_table' => 'node_field_data',
        'left_field' => 'nid',
        'operator' => '=',
      ];
      $join = $this->joinHandler->createInstance('standard', $configuration);
      $this->query->addRelationship($table_field_name, $join, 'node_field_data');
    }
    // I am stuck here... field1-field2 should be < $this->amount
    $this->query->addWhere( ???? );
  }

}

Any hint will be appreciated

beltouche avatar
флаг cn
В качестве альтернативы вы можете рассмотреть возможность использования https://www.drupal.org/project/computed_field и фильтрации по вычисляемому полю.
Baud avatar
флаг sa
@beltouche спасибо. Я также могу заполнить обычное поле во время node_presave, но, поскольку у меня много таких случаев, я бы предпочел понять, как создавать такие запросы. (Я использую обычный sql, это легко, поэтому я предполагаю, что это можно сделать с помощью объекта $query)
Рейтинг:1
флаг ua

У вас есть несколько ошибок:

'поле' => 'нид', должно быть 'поле' => 'entity_id',

$ присоединиться = линия должна использовать Drupal\views\Views::pluginManager('присоединиться')


Вы можете использовать addWhereExpression, рабочий пример:

  запрос публичной функции () {

    $поля = [
      'поле_номер1',
      'поле_номер2',
    ];

    foreach ($fields как $field) {
      $table_field_name = 'узел__' . $поле;
      $ конфигурация = [
        'таблица' => $table_field_name,
        'поле' => 'entity_id',
        'left_table' => 'node_field_data',
        'left_field' => 'нид',
        'оператор' => '=',
      ];
      $join = $this->joinHandler->createInstance('standard', $configuration);
      $this->query->addRelationship($table_field_name, $join, 'node_field_data');
    }

    // Вычитает и фильтрует меньше суммы.
    $this->query->addWhereExpression('AND', 'node__field_num1.field_num1_value - node__field_num2.field_num2_value <' . $this->amount);

  }
Baud avatar
флаг sa
Большое спасибо !, это работает как шарм! Небольшое примечание: `$this->joinHandler` не нужно заменять на `Drupal\views\Views::pluginManager('join')`, потому что я использовал DI: `$container->get('plugin.manager .views.join')` выполняет ту же работу.
No Sssweat avatar
флаг ua
Ах да [внедрение зависимостей](https://www.drupal.org/docs/drupal-apis/services-and-dependency-injection/services-and-dependency-injection-in-drupal-8#s-injecting-dependencies -в-контроллеры-форм-и-блоков), как-то я это проглядел.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.