How do I write the following Drupal 8 EntityQuery so that it only returns nodes that the current user has access to?

$query = \Drupal::entityQuery('node')
  ->condition('type', 'article');

The above query will return all nodes, even unpublished ones. Depending on how you use the results (like a list of nodes), users could see titles or other information from unpublished nodes.

$query = \Drupal::entityQuery('node')
  ->condition('type', 'article')
  ->condition('status', 1);

When I add the "status" condition, I now get a list of only published nodes. But I would like people with administer nodes permission to see all the nodes.

Basically, is there a way to simulate the "admin or published" filter, like on Views?


2 Answers 2


Entity queries by default consider the node grants system, you actually have to opt out of that to get everything when using node grants.

The problem is that drupal core doesn't actually implement that API for the status, that only becomes relevant when using modules that do.

So unfortunately, the only way to simulate "admin or published" is to do it yourself. Check the permission, if the user doesn't have it, add the status = 1 condition. Note that views uses "administer nodes" but technically, that's actuallly wrong, "bypass node access" would make more sense, that would be consistent with what is being checked when trying to access node/ID of an unpublished node. But in your own code, you can use whatever makes sense for you, including a custom permission.

Alternatively, you could use a module like https://www.drupal.org/project/view_unpublished, which does populate grant records and your entity query will just work. In fact, I just closed a bug report where someone reported the behavior you want as a bug when using that module: https://www.drupal.org/project/view_unpublished/issues/2871272.

  • Wow, that's very unexpected behaviour. The fact that you have to opt out of access checks (using $query->accessCheck(FALSE);) to me implies that all access checks are performed otherwise. Granted there are always some that aren't run in an entity query (i.e. hook_entity_access()). But surely adding a check for status is trivial? Should this be an issue in Drupal core?
    – leon.nk
    Commented Oct 27, 2021 at 15:25

As of Drupal 9.2.0, you do it using the following:

// This gets all articles the current user can view.
$ids = \Drupal::entityQuery('node')
  ->condition('type', 'article')

// This gets all articles that exist regardless of access.
$ids = \Drupal::entityQuery('node')
  ->condition('type', 'article')

From https://www.drupal.org/node/3201242.

Your Answer

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

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