3

Using Drupal 8, I am trying to create a view plugin to add a relationship to an existing view. I'm basing the code off of this example https://www.foreach.be/blog/how-build-complex-filters-drupal-8 since I haven't found an explanation of how to add a relationship in D8.

I don't have any error messages but I'm not sure what I need to do to get this working.

I have a class file for the plugin at module_name/src/Plugin/views/relationship/CustomRelationship.php

// CustomRelationship.php

<?php

namespace Drupal\custom_module\Plugin\views\relationship;

use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\Plugin\views\relationship\RelationshipPluginBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;

/**
 * Add custom view relationship
 *
 * @ingroup views_relationship_handlers
 *
 * @ViewsRelationship("custom_relationship")
 */

class CustomRelationship extends RelationshipPluginBase {

  /**
   * Relationship plugin.
   *
   *
   */
  public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
    parent::init($view, $display, $options);
    $this->valueTitle = t('Node Revision');
  }

  public function query() {

    $configuration = array(
      'table' => 'node_revision',
      'field' => 'nid',
      'left_table' => 'node_field_revision',
      'left_field' => 'nid',
      );

    $join = Views::pluginManager('join')->createInstance('standard', $configuration);
    $this->query->addRelationship('node_revision', $join, 'node_field_revision');

  }

}

And in the main module folder there is a views.inc file

// custom_module.views.inc

<?php
/**
 * Implements hook_views_data_alter().
 */
function custom_module_views_data_alter(&$data) {
  $data['custom_module']['custom_relationship'] = array(
    'title' => t('Node Revision'),
    'help' => t('Provide node revision relationship.'),
    'relationship' => array(
      // ID of relationship handler plugin to use.
      'id' => 'custom_relationship',
    ),  
  );
}
5

You shouldn't need to create a Views relationship plugin, although that might depend on any special cases with your relationship.

I've got two custom entities - a student and a school, which have been scaffolded using Drupal console. The Student has an entity reference field (school_id) which relates a Student to a School but the opposite relationship - Students belonging to a School - isn't generated by default. So to create the relationship that can be used in views, I built this hook method:

/**
 * Implements hook_views_data_alter().
 */
function school_student_views_data_alter(array &$data) {
  $data['school']['student']['relationship'] = [
    'title' => t('Student'),
    'label' => t('Student'),
    'group' => 'School',
    'help' => t('Reference to students of a school'),
    'id' => 'standard',
    'base' => 'student',
    'base field' => 'school_id',
    'field' => 'id',
  ];
}

If you examine the $data array, you'll see all the data for all your views tables. It's a big list with lots of array elements. It'll make sense when you look at it. Set a breakpoint in your views_data_alter hook to inspect it (or use dpr/kpr/dpm).

What we're doing is creating a relationship from one table to another, as this relationship currently doesn't exist. I believe that the array element names 'school' and 'student' should refer to the table names we are dealing with. We're creating a relationship data alter and so 'relationship' is the child array element we need to create. Below that is just configuration.

title refers to the relationship title in your "Add relationship" modal window

label is the default name of the relationship when you create it

group is the name of the relationship group your new relationship belongs to

help is helper text/description for the relationship

This next bit is important!

id refers to the the name of the views relationship plugin you are needing to use. Because I'm not creating a complex relationship (basically a simple inner join), I'm using the Standard views relationship plugin (found in Drupal\views\Plugin\views\relationship\Standard).

Finally, base is the base table we're creating the relationship from.

base field is the join field in our base table and finally field is the field in the school table we're creating our join to.

So in use, views will create a join that in SQL looks like:

INNER JOIN {student} student_school ON school.id = student_school.school_id

Hopefully this makes sense and helps you or others out.

  • 2
    The auto-generated code from console is meant to be modified. There's a file called something like SchoolViewsData.php that you could modify the getViewsData function more directly rather than using a hook_views_data_alter. – greggles Feb 25 at 23:33
1

In your custom_module.views.inc file you probably need to attach your relationship to the node 'table' so instead of

  $data['custom_module']['custom_relationship'] = array(

you want

  $data['node']['custom_relationship'] = array(

... or maybe node_field_data

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.