0

I am trying to override the entity view controller for a commerce product view, so that I can redirect the user based on certain conditions.

I am trying to do this through the RouteSubscriber::alterRoutes implementation.

class RouteSubscriber extends RouteSubscriberBase {

  /**
   * {@inheritdoc}
   */
  protected function alterRoutes(RouteCollection $collection) {
    if ($route = $collection->get('entity.commerce_product.canonical')) {
      $route->addDefaults(['_controller' => '\Drupal\mymodule\Controller\ProductViewController::view']);
    }
  }

}

My custom controller is acknowledged, but I'm getting the following error:

RuntimeException: Controller "Drupal\mymodule\Controller\ProductViewController::view()" requires that you provide a value for the "$_entity" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one. in Symfony\Component\HttpKernel\Controller\ArgumentResolver->getArguments() (line 78 of /var/www/html/vendor/symfony/http-kernel/Controller/ArgumentResolver.php).

My ProductViewController extends the Drupal\Core\Entity\Controller\EntityViewController.

class ProductViewController extends EntityViewController {

  public function view(EntityInterface $_entity, $view_mode = 'full')
  {
    return parent::view($_entity, $view_mode); 
  }

}

Can anyone tell what additional route context parameters I need to add to get this working?

2
  • Can you add the code from your controller?
    – sonfd
    Commented Feb 10, 2021 at 22:56
  • @sonfd Currently the controller only has the override method (nothing in it), but I will add it. I believe this error is occurring because the route configuration is incorrect.
    – bfuzze
    Commented Feb 11, 2021 at 0:20

2 Answers 2

0

I figured this out. The problem was the argument name. Once I changed $_entity to $commerce_product in the controller::view method it started working.

class ProductViewController extends EntityViewController {

  public function view(EntityInterface $commerce_product, $view_mode = 'full')
  {
    return parent::view($commerce_product, $view_mode); 
  }

}

I figured this out by looking for other classes that extend EntityViewController and I found NodeViewController and the variable name was the only significant difference.

Such specific variable naming conventions is a bit unconventional imxp, but I believe I have seen this is other places in this Drupal 8.

Anyway, thanks for the assistance @sonfd and I hope this helps others.

1
  • Oh woops, I just updated my answer with the same stuff.
    – sonfd
    Commented Feb 11, 2021 at 15:22
0

I think you may be unsetting some things in your alterRoutes method doing it the way you are. (However, I can't tell if or why that's happening after looking at Route::addDefaults().)

I'm doing the same thing for a media entity's route. My alterRoutes method is a little different - I'm using Route::setDefault().

public function alterRoutes(RouteCollection $collection) {
  if ($route = $collection->get('entity.media.canonical')) {
    $route->setDefault('_controller', '\Drupal\my_module\Controller\MyController::view');
  }
}

Additionally, the variable names in your controller methods are important - they must match the variable name from the route definition. See the documentation for Using parameters in routes

In most PHP code the name of the variable does not matter but here it does: the name of the method argument must match the slug. Conversely, if the method argument name matches the name of the slug, the parameter will be passed in, irrespective of the order of arguments.

1
  • I get the same error with setDefault. Thanks.
    – bfuzze
    Commented Feb 11, 2021 at 14:37

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.