Drupal自定义模块Webform传递表单值时链接失效问题
我来帮你搞定这个Drupal自定义模块的链接问题!看你描述的失效链接Audi?token=01f89ea29aa5251f,明显是URL生成逻辑、参数传递方式出了问题,还有几处代码细节需要优化,咱们一步步拆解修复:
问题核心诊断
- 未解析的Webform Token:你直接把
[webform-submission:values:select_a_car]拼进URL,但这个Token只有在Webform的邮件模板上下文里才会被解析,手动拼接时会原样输出,导致URL格式混乱 - 不规范的URL拼接:手动拼接URL容易出现编码、路径错误,没有利用Drupal官方的URL生成API来处理查询参数
- 不必要的Webform实体保存:在
hook_preprocess_webform里每次加载表单都保存Webform配置,会频繁写入数据库,还可能覆盖其他设置 - 无过期机制的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
相关产品推荐
相关产品推荐

