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

Drupal自定义模块Webform传递表单值时链接失效问题

我来帮你搞定这个Drupal自定义模块的链接问题!看你描述的失效链接Audi?token=01f89ea29aa5251f,明显是URL生成逻辑、参数传递方式出了问题,还有几处代码细节需要优化,咱们一步步拆解修复:

问题核心诊断
  1. 未解析的Webform Token:你直接把[webform-submission:values:select_a_car]拼进URL,但这个Token只有在Webform的邮件模板上下文里才会被解析,手动拼接时会原样输出,导致URL格式混乱
  2. 不规范的URL拼接:手动拼接URL容易出现编码、路径错误,没有利用Drupal官方的URL生成API来处理查询参数
  3. 不必要的Webform实体保存:在hook_preprocess_webform里每次加载表单都保存Webform配置,会频繁写入数据库,还可能覆盖其他设置
  4. 无过期机制的Token存储:State API里的Token不会自动清理,长期运行会积累无效数据
修复步骤与代码修改

1. 正确生成带参数的Webform-2链接

在webformcustom_validator函数里,直接从FormState获取提交值,用Drupal的Url类生成规范的URL,避免Token解析问题:

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;

function webformcustom_validator(&$form, FormStateInterface $form_state) {
  // 直接从表单状态获取提交的邮箱和车型值
  $email = $form_state->getValue('email_address');
  $selected_car = $form_state->getValue('select_a_car');

  $webform = \Drupal::entityTypeManager()
    ->getStorage('webform')
    ->load('get_offers');
  $email_handler = $webform->getHandler('email');
  $configuration = $email_handler->getConfiguration();

  // 生成随机Token并关联邮箱存储到State
  $token = bin2hex(openssl_random_pseudo_bytes(8));
  \Drupal::state()->set('webformcustom_' . $token, $email);
  
  // 使用Drupal官方API生成带查询参数的绝对URL
  $webform2_url = Url::fromRoute(
    'entity.webform.canonical',
    ['webform' => 'provide_a_quote'],
    [
      'absolute' => TRUE,
      'query' => [
        'select_a_car' => $selected_car,
        'token' => $token,
      ],
    ]
  )->toString();

  // 插入正确的链接到邮件内容
  $configuration['settings']['body'] = '<a href="' . $webform2_url . '">Submit offer</a>';
  $email_handler->setConfiguration($configuration);
}

2. 优化Webform-2的收件人设置逻辑

不要在预处理器里频繁保存Webform实体,改用hook_webform_submission_presave在提交时动态设置收件人,同时用完Token后清理:

use Drupal\webform\WebformSubmissionInterface;

/**
 * Implements hook_webform_submission_presave().
 */
function webformcustom_webform_submission_presave(WebformSubmissionInterface $webform_submission) {
  $webform_id = $webform_submission->getWebform()->id();
  if ($webform_id !== 'provide_a_quote') {
    return;
  }

  // 获取URL中的Token
  $token = \Drupal::request()->query->get('token');
  if (!$token) {
    return;
  }

  // 从State中取出关联的邮箱
  $email = \Drupal::state()->get('webformcustom_' . $token);
  if (!$email) {
    return;
  }

  // 动态设置邮件处理器的收件人,无需保存Webform实体
  $email_handler = $webform_submission->getWebform()->getHandler('email');
  if ($email_handler) {
    $handler_config = $email_handler->getConfiguration();
    $handler_config['settings']['to_mail'] = $email;
    $email_handler->setConfiguration($handler_config);
  }

  // 清理已使用的Token,避免重复利用
  \Drupal::state()->delete('webformcustom_' . $token);
}

3. 可选:添加Token过期机制(推荐)

为了避免State中积累无效Token,可以添加24小时过期逻辑:

  • 修改验证器中的Token存储:
// 存储邮箱和过期时间(当前时间+24小时)
$expire_time = \Drupal::time()->getRequestTime() + 86400;
\Drupal::state()->set('webformcustom_' . $token, [
  'email' => $email,
  'expire' => $expire_time,
]);
  • 修改presave中的Token校验:
$token_data = \Drupal::state()->get('webformcustom_' . $token);
if (!$token_data || \Drupal::time()->getRequestTime() > $token_data['expire']) {
  return;
}
$email = $token_data['email'];
// 后续收件人设置逻辑...
\Drupal::state()->delete('webformcustom_' . $token);
为什么原来的链接失效?

你之前手动拼接URL时,未解析的[webform-submission:values:select_a_car]直接被当成了字符串,导致URL格式错误(比如变成provide-a-quote/?select_a_car=[webform-submission:values:select_a_car]&token=xxx),浏览器解析时会出现路径或参数识别问题,最终导致链接无法正确指向Webform-2。

用Drupal官方的Url类生成URL会自动处理参数编码和路径拼接,确保链接格式完全正确,同时直接从FormState获取提交值,避免依赖Webform Token的上下文解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 10:58:15