Как добавить пользовательскую вкладку на страницу профиля пользователя?

11

Мне нужно добавить пользовательскую вкладку на странице профиля пользователя. Я определил свой маршрут, как показано ниже:

mymodule.routing.yml

mymodule.account:
path: '/user/{user}/custom'
defaults: 
  _form: '\Drupal\mymodule\Form\MyModuleUserSettingsForm'
  _title: 'Custom Settings'
  user: \d+
requirements:
  _permission: 'access content'

mymodule.links.task.yml

mymodule.account:
  title: Mymodule Settings
  route_name: mymodule.account
  base_route: entity.user.canonical

mymodule.links.menu.yml

mymodule.account:
  title: My module Settings
  parent: entity.user.canonical
  route_name: mymodule.account

Затем после очистки кеш вкладка появляется на странице профиля. Но когда я открываю URL / user / 1 / custom, я вижу сообщение о том, что страница не найдена.

ARUN
источник
1
user: \ d + должен идти в соответствии с требованиями - внесите это изменение, очистите весь кеш, проверьте, не появилась ли еще страница.
Кевин

Ответы:

5

Ваша проблема в mymodule.routing.ymlфайле, большая проблема в месте user: \d+, эта строка должна быть под requirements:разделом, другая проблема - отступ. Итак, окончательный код должен быть:

mymodule.account:
  path: '/user/{user}/custom'
  defaults: 
    _form: '\Drupal\mymodule\Form\MyModuleUserSettingsForm'
    _title: 'Custom Settings'
  requirements:
    _permission: 'access content'
    user: \d+

И, конечно, вам нужно определение класса формы в src/Form/MyModuleUserSettingsForm.php

<?php

namespace Drupal\mymodule\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * Class MyModuleUserSettingsForm.
 *
 * @package Drupal\mymodule\Form
 */
class MyModuleUserSettingsForm extends FormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'simple_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['title'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Title'),
      '#maxlength' => 64,
      '#size' => 64,
      '#required' => TRUE,
    ];
    $form['submit'] = [
      '#type' => 'submit',
      '#value' => t('Submit'),
    ];

    return $form;
  }

  public function validateForm(array &$form, FormStateInterface $form_state) {  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {  }

}

И mymodule.info.ymlфайл для завершения вашего модуля (в данном случае с именем mymodule)

name: My Module
type: module
description: 'My module'
core: 8.x
package: Custom

Справка: Структура маршрутов

Адриан Сид Альмагуер
источник
Интересно, что в структуре маршрутов не упоминается user:ни ключ, ни то, куда он должен идти ... Возможно, документы должны быть улучшены / отредактированы? или я что то пропустил?
Нет Sssweat
nvm, я вижу, он находится под _entity_access: и они использовали узел в качестве примера, поэтому мой CTRL + F "user:" ничего не нашел.
Нет Sssweat
3

Есть два способа загрузить форму, используя маршрут. Вы можете либо загрузить обратный вызов, который загружает форму и возвращает ее как часть массива сборки, либо вы можете загрузить форму напрямую, установив параметр _form в значение по умолчанию.

Вы можете выполнить поиск по базе кода, чтобы найти рабочие примеры, скопировать их в свой mymodule.routing.yml, отредактировать их в соответствии с вашими потребностями, а затем перестроить кеш.

Загрузка формы от обратного вызова:

В контактном модуле есть рабочий пример:

/core/modules/contact/contact.routing.yml

entity.user.contact_form:
  path: '/user/{user}/contact'
  defaults:
    _title: 'Contact'
    _controller: '\Drupal\contact\Controller\ContactController::contactPersonalPage'
  requirements:
    _access_contact_personal_tab: 'TRUE'
    user: \d+

Затем в /core/modules/contact/src/Controller/ContactController.php

Вы можете увидеть пример того, как загрузить форму в обратном вызове:

  public function contactPersonalPage(UserInterface $user) {
    // Do not continue if the user does not have an email address configured.
    if (!$user->getEmail()) {
      throw new NotFoundHttpException();
    }

    $message = $this->entityManager()->getStorage('contact_message')->create(array(
      'contact_form' => 'personal',
      'recipient' => $user->id(),
    ));

    $form = $this->entityFormBuilder()->getForm($message);
    $form['#title'] = $this->t('Contact @username', array('@username' => $user->getDisplayName()));
    $form['#cache']['contexts'][] = 'user.permissions';
    return $form;
  }

Форма загрузки прямо с маршрута:

Если вы хотите загрузить форму напрямую, используя _form по умолчанию, в модуле ярлыков есть пример по адресу /core/modules/shortcut/shortcut.routing.yml

shortcut.set_switch:
  path: '/user/{user}/shortcuts'
  defaults:
    _form: 'Drupal\shortcut\Form\SwitchShortcutSet'
    _title: 'Shortcuts'
  requirements:
    _custom_access: 'Drupal\shortcut\Form\SwitchShortcutSet::checkAccess'
  options:
    _admin_route: TRUE
    user: \d+

В этом случае пользователь передается в качестве параметра в форму, см. /Core/modules/shortcut/src/Form/SwitchShortcutSet.php

  public function buildForm(array $form, FormStateInterface $form_state, UserInterface $user = NULL) {
oknate
источник
1

Несколько вещей, которые я могу заметить ...

У вас есть ВСЕ, названное mymodule.account. Я бы немного разнообразил это. Подумайте об этом на странице задач:

mymodule.account_tab:
  title: Mymodule Settings
  route_name: mymodule.account
  base_route: entity.user.canonical

Я также не верю, что вам нужно что-либо в меню для этого.

Между этими двумя вам должно быть хорошо идти! Не стесняйтесь обращаться ко мне напрямую, если вы не можете понять это, потому что я - ПРОСТО - заставил это работать на моем порте D8 Apply For Role!

Jnicola
источник
1

В modulename.routing.yml вы должны передать аргумент пользователя, как показано ниже

profile.user_information:
  path: '/user/{user}/profile'
  defaults:
    _form: '\Drupal\profile\Form\UserInformation'
    _title: 'UserInformation'
  requirements:
    _permission: 'access content'
  options:
    user: \d+

и в modulename.links.task.yml у вас есть код, как показано ниже

profile.user_information:
  title: User profile
  route_name: profile.user_information
  base_route: entity.user.canonical
Debasish
источник