Change record status: 
Project: 
Introduced in branch: 
8.x
Description: 

Read New Symfony-based routing system and Route access control may be stacked for background information on routes.

For hook_menu() entries that used an access callback to check the access to an entity, the route should use _entity_access as the requirement.

_entity_create_access can be used to check access for creating a new entity of a given type. That requirement also support specifying a bundle as either a static value or as a reference to a given route parameter.

Drupal 7

function user_menu() {
  $items['user/%user'] = array(
    'title' => 'My account',
    'page callback' => 'user_view_page',
    'page arguments' => array(1),
    'access callback' => 'user_view_access',
    'access arguments' => array(1),
  );
  $items['user/%user/cancel'] = array(
    'title' => 'Cancel account',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('user_cancel_confirm_form', 1),
    'access callback' => 'user_cancel_access',
    'access arguments' => array(1),
    'file' => 'user.pages.inc',
  );
  $items['admin/structure/taxonomy/add'] = array(
    'title' => 'Add vocabulary',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('taxonomy_form_vocabulary'),
    'access arguments' => array('administer taxonomy'),
    'type' => MENU_LOCAL_ACTION,
    'file' => 'taxonomy.admin.inc',
  );
  $items['admin/structure/taxonomy/%taxonomy_vocabulary_machine_name/add'] = array(
    'title' => 'Add term',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('taxonomy_form_term', array(), 3),
    'access arguments' => array('administer taxonomy'),
    'type' => MENU_LOCAL_ACTION,
    'file' => 'taxonomy.admin.inc',
  );
}

Drupal 8

user.view:
  path: '/user/{account}'
  defaults:
    _controller: 'Drupal\user\UserController::view'
  requirements:
    _entity_access: 'account.view'
user.cancel:
  path: '/user/{account}/cancel'
  defaults:
    _form: 'Drupal\user\Form\CancelConfirmForm'
  requirements:
    _entity_access: 'account.delete'

taxonomy.vocabulary_add:
  path: '/admin/structure/taxonomy/add'
  defaults:
    _entity_form: 'taxonomy_vocabulary'
  requirements:
    _entity_create_access: 'taxonomy_vocabulary'

taxonomy.term_add:
  path: '/admin/structure/taxonomy/manage/{taxonomy_vocabulary}/add'
  defaults:
    _controller: '\Drupal\taxonomy\Controller\TaxonomyController::addForm'
  requirements:
    _entity_create_access: 'taxonomy_term:{taxonomy_vocabulary}'

Where the form is 'param.operation', and param must match the {param} in the route pattern.

Impacts: 
Module developers

Comments

jonhattan’s picture

... and you declare an access handler in the entity type annotations. See for example:

 *   handlers = {
...
 *     "access" = "Drupal\taxonomy\TermAccessControlHandler",
...

in https://api.drupal.org/api/drupal/core!modules!taxonomy!src!Entity!Term....

Then, class TermAccessControlHandler extends EntityAccessControlHandler and implements checkAccess() and checkCreateAccess().

OTOH, if you want to override other module's entity access, you want to implement hook_entity_access() or hook_ENTITY_TYPE_access(), and respectively hook_entity_create_access() or hook_ENTITY_TYPE_create_access().