You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Drupal7转Drupal8:如何正确覆写节点删除操作?

正确覆写Drupal 8节点删除操作的实现方式

嘿,从Drupal7转到D8确实得适应不少架构变化,尤其是表单这块——ConfirmFormBase是官方推荐的正确路子,你选的方向没错!下面给你一步步拆解扎实的实现方式:

1. 完整实现自定义删除确认表单(ConfirmFormBase)

你已经创建了src/Form/DeleteXXXConfirm.php,下面是带关键注释的可运行代码示例:

namespace Drupal\XXX\Form;

use Drupal\Core\Form\ConfirmFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\node\Entity\Node;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * 自定义节点删除确认表单.
 */
class DeleteXXXConfirm extends ConfirmFormBase {

  /**
   * 要删除的节点对象.
   *
   * @var \Drupal\node\Entity\Node
   */
  protected $node;

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    // 表单唯一ID,需与模块名对应
    return 'xxx_node_delete_confirm';
  }

  /**
   * {@inheritdoc}
   */
  public function getQuestion() {
    // 确认表单标题,用节点标题动态替换
    return $this->t('Are you sure you want to delete the node %title?', ['%title' => $this->node->getTitle()]);
  }

  /**
   * {@inheritdoc}
   */
  public function getCancelUrl() {
    // 取消操作后的跳转URL,这里跳回节点详情页
    return Url::fromRoute('entity.node.canonical', ['node' => $this->node->id()]);
  }

  /**
   * {@inheritdoc}
   */
  public function getConfirmText() {
    // 自定义确认按钮文字,默认是"Delete"
    return $this->t('Delete Node');
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, $node = NULL) {
    // 加载目标节点,不存在则抛出404
    $this->node = Node::load($node);
    if (!$this->node) {
      throw new NotFoundHttpException();
    }
    // 调用父类方法生成基础确认表单结构
    return parent::buildForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    // 自定义删除逻辑,可按需调整
    // 1. 执行默认节点删除操作(如需保留原生行为)
    $this->node->delete();

    // 2. 添加自定义操作:比如记录日志、触发关联事件
    $this->messenger()->addStatus($this->t('Node %title has been deleted.', ['%title' => $this->node->getTitle()]));

    // 3. 设置提交后的跳转目标,这里跳回内容列表页
    $form_state->setRedirect('system.admin_content');
  }

}

2. 替换默认节点删除表单路由

要让Drupal使用你的自定义表单,需要通过hook_route_alter替换原生路由,在模块的.module文件中添加:

/**
 * Implements hook_route_alter().
 */
function xxx_route_alter(&$routes) {
  // 替换默认的节点删除确认路由
  if (isset($routes['entity.node.delete_form'])) {
    $routes['entity.node.delete_form']->setDefault('_form', '\Drupal\XXX\Form\DeleteXXXConfirm');
  }
}

3. 配合hook_node_delete做后续处理(可选)

你提到Drupal8仍支持hook_node_delete,这个钩子在节点删除后触发,适合做关联数据清理、日志记录等操作,在.module文件中添加:

/**
 * Implements hook_node_delete().
 */
function xxx_node_delete($node) {
  // 节点删除后的自定义逻辑示例
  \Drupal::logger('xxx')->notice('Node @nid (@title) has been deleted.', [
    '@nid' => $node->id(),
    '@title' => $node->getTitle(),
  ]);
}

关键注意事项

  • 模块名统一:把代码中的XXX替换成你的实际模块名,包括命名空间、钩子前缀
  • 权限控制:自定义表单会继承原生节点删除权限,如需特殊权限,可在buildForm中添加权限检查并抛出AccessDeniedException
  • 缓存清理:修改代码后必须执行缓存清理(drush cr或后台手动清理),否则路由和表单不会生效

内容的提问来源于stack exchange,提问作者user82521

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:17:41