8

Inside a block plugin I'm creating a table (in Drupal8). Like so

            $header = [
                t('Name'),
                t('Number'),
                t('Rank'),
            ];
            $nids = \Drupal::entityQuery('node')
                ->extend('Drupal\Core\Database\Query\TableSortExtender')
                ->orderByHeader($header)
                ->condition('type', 'my_content_type')
                ->condition('status', 1)
                ->pager(5)
                ->execute();
            foreach ($nids as $nid) {
                $node            = \Drupal\node\Entity\NODE::load($nid);
                $row = [
                    'data' => [
                        $node->title->value,
                        $node->field_number->value,
                        $node->field_rank->value,
                    ],
                ];
                $rows[] = $row;
              }
            $render = [
                'table'           => [
                    '#prefix'        => '<h1>Entries</h1>',
                    '#theme'         => 'table',
                    '#attributes'    => [
                        'data-striping' => 0
                    ],
                    '#header' => $header,
                    '#rows'   => $rows,
                ],
            ];
            return $render;

Without the code below

 ->extend('Drupal\Core\Database\Query\TableSortExtender')
 ->orderByHeader($header)

the table renders just fine, but if I do include it I get the error

Call to undefined method Drupal\Core\Entity\Query\Sql\Query::extend()

I'm guessing that it ->extend does not work on EntityQueries, but if that's the case how can I add table sorting to my table?

UPDATE: I've changed my $header array to include 'field' like so

            $header = [
                [
                    'data'  => t('Title'),
                    'field' => 'title'
                ],
                [
                    'data'  => t('Race'),
                    'field' => 'field_number'
                ],
                [
                    'data'  => t('Time'),
                    'field' => 'field_rank',
                ],
            ];

and tried adding

 ->tableSort($header)

to the query and removing extend and orderByHeader from the query but then I receive the following error

Drupal\Core\Entity\Query\QueryException: '' not found in Drupal\Core\Entity\Query\Sql\Tables->ensureEntityTable()

UPDATE 2: I tried changing the $header array to use a specifier and type property like so.

                    'data'      => t('Name'),
                    'type'      => 'field',
                    'specifier' => [
                        'field'    => 'title',
                        'column'   => 'value',
                    ],

But I end up with the same error and get an additional error

Undefined index: specifier in Drupal\Core\Entity\Query\QueryBase->tableSort()

2 Answers 2

7

Following some of the information found in Berdirs answer and comments I was able to arrive at a solution.

I formatted my header like so:

            $header = [
                'title'      => [
                    'data'      => t('title'),
                    'field'     => 'title',
                    'specifier' => 'title',
                ],
                'number'       => [
                    'data'      => t('Number'),
                    'field'     => 'field_number',
                    'specifier' => 'field_number',
                ],
                'time'       => [
                    'data'      => t('Time'),
                    'field'     => 'field_rank',
                    'specifier' => 'field_rank',
                ],
            ],

I then performed the EntityQuery like so

            $nids = \Drupal::entityQuery('node')
                ->tableSort($header)
                ->condition('type', 'my_content_type')
                ->condition('status', 1)
                ->pager($items_per_page)
                ->execute();

I formatted my rows like so

                $row = [
                    'data' => [
                        $node->title->value,
                        $node->field_number->value,
                        $node->field_rank->value,
                ];

After that generating the table was easy

            $render = [
                'table'           => [
                    '#prefix'        => '<h1>Entries</h1>',
                    '#theme'         => 'table',
                    '#attributes'    => [
                        'data-striping' => 0
                    ],
                    '#header' => $header,
                    '#rows'   => $rows,
                ],
            ];

The important parts I was missing is the proper format for $header. And using ->tableSort($header) instead of ->extend('Drupal\Core\Database\Query\TableSortExtender') ->orderByHeader($header) in my entityQuery

5

Entity query doesn't support extend() as you guessed and it also doesn't have any built in support for anything like Tablesort.

You should still be able to define the $header (your example is not correct, it needs to have a key for the field at least and optionally default sort order) and then use tablesort_get_order() and tablesort_get_sort() to get the field to sort on as well as the sort direction.

Edit: Turns out entity query does support that with tableSort(), but as I said, your header definition is not correct, see comments.

3
  • Would tablesort_get_order() just be added as part of the query? Like ->condition('type','my_content_type')->tablesort_get_order($headers)->tablesort_get_sort($headers)?
    – Amy
    Apr 17, 2017 at 21:09
  • Also I just found tableSort. Doesn't that take care of both of those? Either way I can't seem to get it to work.
    – Amy
    Apr 17, 2017 at 21:18
  • Indeed, tableSort() seems to be basically this, wasn't aware this existed. This should definitely work if your header definition is correct, which your above example is not as I mentioned. See \Drupal\user\UserListBuilder::load and the buildHeader() method for a correct example
    – Berdir
    Apr 17, 2017 at 22:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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