4

Is there a way to specify an argument to pass to a custom access callback, specifically an argument that isn't part of the path? Like in Drupal 7 you could do this:

function mymodule_menu() {
  $items['abc/$val'] = array(
    'page callback' => 'mymodule_abc_view',
    'access callback' => 'mymodule_abcdef_access',
    'access arguments' => array(1, 'test1'),
  );
  $items['def/$val'] = array(
    'page callback' => 'mymodule_def_view',
    'access callback' => 'mymodule_abcdef_access',
    'access arguments' => array(1, 'test2'),
  );
  return $items;
}

function mymodule_abc_access($val, $type) {
  return ($val['some_prop'] == $type);
}

So in Drupal 8 I would have this in mymodule.routing.yml:

mymodule.abc:
  path: 'abc/{val}'
  defaults:
    _controller: '\Drupal\mymodule\Controller\MyModuleController::abc'
  requirements:
    _custom_access: '\Drupal\mymodule\Controller\MyModuleController::abcDefAccess'

mymodule.def:
  path: 'def/{val}'
  defaults:
    _controller: '\Drupal\mymodule\Controller\MyModuleController::def'
  requirements:
    _custom_access: '\Drupal\mymodule\Controller\MyModuleController::abcDefAccess'

And in MyModuleController:

public function abcDefAccess($val, $type) {
  return AccessResult::allowedIf($val->someProp == $type);
}

But is there any way to pass 'test1' or 'test2' as $type? Otherwise I guess I would just have to make a separate access function for each type.

1
  • 1
    I don't have an answer, but after reading this page: drupal.org/node/2122195, it seems like you've implemented a "Simplified custom access checker" and that you'd be able to do more complex things if you implement a full custom access check class that extends AccessInterface and use the arguments in the associated service to pass in your variables.
    – user72086
    Commented May 5, 2017 at 12:19

3 Answers 3

2

In D8 you can use custom route arguments:

Passing arguments to controllers

All keys under the defaults section which do not start with an underscore will be passed in as arguments to the controller. Name your arguments appropriately for the arguments of the controller. For example a routing.yml file with the following:

example.content:
  path: '/example' 
  defaults: 
    _controller: '\Drupal\example\Controller\ExampleController::content' 
    custom_arg: 12
  requirements: 
    _permission: 'access content'

Will pass on $custom_arg to the controller, so your content method can take $custom_arg:

  public function content(Request $request, $custom_arg) {
    // Now can use $custom_arg (which will get 12 here) and $request.
  }

Source: https://www.drupal.org/docs/8/api/routing-system/structure-of-routes

While the documentation is for a controller, the same applies to other route callbacks, like in your case an access callback:

public function abcDefAccess($val, $custom_arg) {
  return AccessResult::allowedIf($val->someProp == $custom_arg);
}
0
3

Your route:

regportal_user.orders:
  path: '/user/{user}/orders'
  defaults:
    _entity_view: 'user.orders'
    _title: 'Управление заказами'
  requirements:
    _custom_access: '\Drupal\regportal_user\Controller\RegportalUserController::accessOwnOrders'

Your controller:

  /**
   * Checks access for a regportal_user.orders route.
   *
   * @param \Drupal\Core\Session\AccountInterface $account
   *   Run access checks for this account.
   *
   * @return \Drupal\Core\Access\AccessResult
   */
  public function accessOwnOrders(AccountInterface $account, $user) {
    if ($account->id() == $user) {
      return AccessResult::allowed();
    }

    return AccessResult::forbidden();
  }
2

As @4k4 said, adding a non-underscored default to the route entry will send that exact string as a parameter to the custom access controller, as long as the parameter names match up. Since your abcDefAccess method wants $type, just add type to your routing definitions. So mymodule.routing.yml becomes:

mymodule.abc:
  path: 'abc/{val}'
  defaults:
    _controller: '\Drupal\mymodule\Controller\MyModuleController::abc'
    type: 'abc'
  requirements:
    _custom_access: '\Drupal\mymodule\Controller\MyModuleController::abcDefAccess'

mymodule.def:
  path: 'def/{val}'
  defaults:
    _controller: '\Drupal\mymodule\Controller\MyModuleController::def'
    type: 'def'
  requirements:
    _custom_access: '\Drupal\mymodule\Controller\MyModuleController::abcDefAccess'

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.