Reputation: 2274
I am a Drupal newbie. I have written a custom module in Drupal 8 and it works and displays some content.
I want to add a tab in the user's profile that links to my custom module.
As far as I understand, I need to write a route and a task. This is what I have done :
my_module.routing.yml
my_module.some_route_name:
path: '/user/{user}/some_path'
defaults:
_controller: '\Drupal\my_module\Controller\MyModuleController::content'
_title: 'Some Title'
requirements:
_permission: 'access content'
options:
user: \d+
my_module.links.tasks.yml
my_module.some_task_name:
route_name: my_module.some_route_name
base_route: entity.user.canonical
title: 'Some Title'
I have done this and the route works as it should, however no tab shows up in my user's profile page.
It should look something like this :
I have partially resolved the issue by creating a hook as per Drupal API 8.6 (menu_local_tasks_alter) and this is what I wrote :
function my_module_menu_local_tasks_alter(&$data, $route_name, \Drupal\Core\Cache\RefinableCacheableDependencyInterface &$cacheability) {
$url = Drupal\Core\Url::fromRoute('my_module.some_route_name');
if ($route_name == 'entity.user.canonical') {
$data['tabs'][0]['my_module.some_route_name'] = [
'#theme' => 'menu_local_task',
'#link' => [
'title' => t('Some Title'),
'url' => $url,
'localized_options' => [
'attributes' => [
'title' => t('Add content'),
],
],
],
];
// The tab we're adding is dependent on a user's access to add content.
$cacheability
->addCacheTags([
'user.permissions',
]);
}
}
This works if I replace the {user} part of my route's path with 1. When I have {user} in the path, it now complains with the following error :
The website encountered an unexpected error. Please try again later.</br></br><em class="placeholder">Symfony\Component\Routing\Exception\MissingMandatoryParametersException</em>: Some mandatory parameters are missing ("user") to generate a URL for route ...
I have also made sure to provide my content method in my controller with a user object $user that implements AccountInterface as described here: https://www.drupal.org/docs/8/api/routing-system/using-parameters-in-routes , however, I still get the same error message.
Upvotes: 3
Views: 3373
Reputation: 435
In case anyone stumbles on this in the future, here's an easier way that doesn't require the HOOK_menu_local_tasks_alter
implementation, and corrects a typo in the OP's code:
entity.my_entity.my_route:
path: '/admin/my_entity/{my_entity}/my_route' # Or similar
defaults:
_controller: '\Drupal\my_module\Controller\MyController::content'
_title: 'My Route Title'
options:
parameters:
my_entity:
type: entity:my_entity
requirements:
_permission: 'my_permission'
Note the singular task
not tasks
in the OP's post.
entity.my_entity.my_route:
route_name: entity.my_entity.my_route
base_route: entity.my_entity.canonical
title: 'My Route Title'
Then write your controller as you would in @cesar-moore's post, with the first parameter upcast, as he notes, as MyEntity $my_entity
. No need for any alterations. This route will now show a new tab on every page of your entity: View, Edit, or similar.
Upvotes: 2
Reputation: 318
You don't need the hook, I just tested with your routing and _task definitions and it works fine for me.
This is my controller:
class MyModuleController {
public function content($user) {
return [
'#markup' => "user: $user"
];
}
}
This renders as: "user: 1" at the "/user/1/some_path" URL.
I think you are also trying to use Drupal's automatic paramater upcasting, but that is optional.
To solve the exception (Symfony\Component\Routing\Exception\MissingMandatoryParametersException).
You have to add the mandatory parameter in your route. Just add the user (['user' => 1]
):
$url = Drupal\Core\Url::fromRoute('my_module.some_route_name', ['user' => 1]);
Upvotes: 2