- 🇳🇱Netherlands johnv
In D11.1, I encounter the same problem, using a n (exposed) Views filter.
The problem is that the pager settings limit the RANGE for the SQL statement, .
In views/src/ViewExecutable->execute():
public function execute($display_id = NULL) { ... // Let modules modify the view just prior to executing it. $module_handler = \Drupal::moduleHandler(); $module_handler->invokeAll('views_pre_execute', [$this]); ... if ($cache->cacheGet('results')) { ... } else { $this->query->execute($this); // Enforce the array key rule as documented in // views_plugin_query::execute(). $this->result = array_values($this->result); $this->_postExecute(); $cache->cacheSet('results'); } // Let modules modify the view just after executing it. $module_handler->invokeAll('views_post_execute', [$this]); return $this->executed = TRUE; }
That
$this->query->execute($this);
calls src/Plugin/views/query/Sql->execute(), where you see that when 'limit' is set, the query itself is limiting the fetched result data, instead of read all data before pagination :public function execute(ViewExecutable $view) { ... if ($query) { $additional_arguments = \Drupal::moduleHandler()->invokeAll('views_query_substitutions', [$view]); ... try { if ($view->pager->useCountQuery() || !empty($view->get_total_rows)) { $view->pager->executeCountQuery($count_query); } // Let the pager modify the query to add limits. $view->pager->preExecute($query); if (!empty($this->limit) || !empty($this->offset)) { // We can't have an offset without a limit, so provide a very large limit instead. $limit = intval(!empty($this->limit) ? $this->limit : 999999); $offset = intval(!empty($this->offset) ? $this->offset : 0); $query->range($offset, $limit); } $result = $query->execute(); ... $view->pager->postExecute($view->result); $view->pager->updatePageInfo(); $view->total_rows = $view->pager->getTotalItems(); // Load all entities contained in the results. $this->loadEntities($view->result); } ... }
The
$result = $query->execute();
contains a Query->preExecute() with an alter hook, which might be used to remove the RANGE and update the 'total_rows' statistic:
public function preExecute(?SelectInterface $query = NULL) {
...
// Modules may alter all queries or only those having a particular tag.
if (isset($this->alterTags)) {
\Drupal::moduleHandler()->alter($hooks, $query);
}
...
}Then, there is a views_post_execute() hook to restore the pager if needed.
- 🇬🇧United Kingdom sergiur London, UK
If anyone is looking for a workaround in the meantime, you could try adding a contextual filter to the view that is set to ‘exclude’ and/or ‘multiple’ as needed, and passing in the items you want to remove through the contextual filter. This doesn’t mess up pagination.
- 🇳🇱Netherlands johnv
That won't work if you want the user to make the selection (via the exposed filter), would it?
- 🇬🇧United Kingdom sergiur London, UK
I don't know about exposed filters, the original scope of this issue referred to cases where you need to remove results programmatically in a hook_views_pre_view hook or another views hook
- 🇩🇪Germany Peter Majmesku 🇩🇪Düsseldorf
I found a solution regarding to custom exposed filters and the pager counter, which might help you.
There is this Pager-ID field in the views pager settings. After trying a couple things, I've tried to set a different numeric ID there, too. Afterwards this pager and other pagers worked correctly. The description of this field also already suggests, that it can help, if there are "problems". So there might be some side effects, which can be worked around by this field setting. Maybe this information helps others also.
Lost a couple of hours with this not quite intuitive pager behavior in views...