PHP POST请求中含重复键的screening_questions数组重组问询
问题
我用PHP向API提交表单数据,该API要求screening_questions字段使用重复键。目前大部分字段已正确放入请求数组,但screening_questions是嵌套数组形式,合并展开时因为键名重复,只会保留最后一组数据。我需要把嵌套的screening_questions数组展开成包含重复键的结构:
原数组
Array ( [candidate[resume]] => CURLFile Object ( [name] => /nas/content/live/powerhrg2/wp-content/uploads/gravity_forms/5-51403278f6166fe42c507d417f729fc5/2023/02/Power-HRG-Tech-Spec256.pdf [mime] => application/pdf [postname] => Power-HRG-Tech-Spec256.pdf ) [candidate[first_name]] => John [candidate[last_name]] => Johnson [candidate[email]] => john.johnson@email.net [candidate[phone]] => 555-555-5555 [job_posting_public_id] => 28038a67e70c7e235fa725bbf8b6e167d9e3efee1e43a304d73be8408c6f24a2 [candidate[source_id]] => 7795 [0] => Array ( [screening_questions[][id]] => 1 [screening_questions[][answer]] => false ) [1] => Array ( [screening_questions[][id]] => 6 [screening_questions[][answer]] => true ) [2] => Array ( [screening_questions[][id]] => 11 [screening_questions[][answer]] => true ) [3] => Array ( [screening_questions[][id]] => 16 [screening_questions[][answer]] => true ) )
目标数组
Array ( [candidate[resume]] => CURLFile Object ( [name] => /nas/content/live/powerhrg2/wp-content/uploads/gravity_forms/5-51403278f6166fe42c507d417f729fc5/2023/02/Power-HRG-Tech-Spec256.pdf [mime] => application/pdf [postname] => Power-HRG-Tech-Spec256.pdf ) [candidate[first_name]] => John [candidate[last_name]] => Johnson [candidate[email]] => john.johnson@email.net [candidate[phone]] => 555-555-5555 [job_posting_public_id] => 28038a67e70c7e235fa725bbf8b6e167d9e3efee1e43a304d73be8408c6f24a2 [candidate[source_id]] => 7795 [screening_questions[][id]] => 1 [screening_questions[][answer]] => false [screening_questions[][id]] => 6 [screening_questions[][answer]] => true [screening_questions[][id]] => 11 [screening_questions[][answer]] => true [screening_questions[][id]] => 16 [screening_questions[][answer]] => true )
我暂时想不到合并或扁平化这些数组的方法,也想了解是否有其他格式可实现带唯一值的重复screening_questions键提交。以下是我的完整代码:
add_action( 'gform_after_submission_5', 'post_to_third_party', 10, 2 ); function post_to_third_party( $entry, $form ) { // get regular form field data $first_name = rgar( $entry, '1' ); $last_name = rgar( $entry, '3' ); $phone = rgar( $entry, '11' ); $phone = preg_replace("/[^0-9]/", "", $phone); $phone = preg_replace('/^1?(\d{3})(\d{3})(\d{4})$/', '$1-$2-$3', $phone); $email = rgar( $entry, '6' ); $resume = GFFormsModel::get_physical_file_path( rgar( $entry, '7' ) ); $resume = new CURLFile($resume, mime_content_type($resume), basename($resume)); $job = get_job(); // get current job ID & source ID $job_id = $job['id']; $source_id = $job['source_id']; // get screening questions id & answer data foreach ( $form['fields'] as $field ) { if ($field['type'] === 'radio') { $field_values[] = preg_replace('/[^0-9.]/', '', $field->get_value_export( $entry, $field->id )); // i.e. converts 'yes-1' to '1' $field_names[] = $field->get_value_export( $entry, $field->id, true ); // yes } } // remove empty data $field_values = array_slice(array_filter($field_values),0); $field_names = array_slice(array_filter($field_names),0); // combine screening id & answer $screening_questions = array_combine($field_values, $field_names); foreach ($screening_questions as $screening_question=>$sq) { // value must be true/false, not yes/no if ($sq == 'yes') { $sq = 'true'; } else { $sq = 'false'; } $question[] = array('screening_questions[][id]' => $screening_question, 'screening_questions[][answer]' => $sq); } // create an array of form data to send via the API $body = array( 'candidate[resume]' => $resume, 'candidate[first_name]' => $first_name, 'candidate[last_name]' => $last_name, 'candidate[email]' => $email, 'candidate[phone]' => $phone, 'job_posting_public_id' => $job_id, 'candidate[source_id]' => $source_id, ); foreach ($question as $q) { array_push($body,$q); } $post_url = 'https://pr29718.nitro-web.beta.hq.powerapp.cloud/recruiting/api/v2/candidates'; // TEST URL $pass = 'AMC0HNUK30RTFATWWKBJTW'; // TEST TOKEN $headers = array( 'Host: pr29718.nitro-web.beta.hq.powerapp.cloud', 'Authorization: '.$pass, ); // Uncomment the below line to debug, if necessary GFCommon::log_debug( 'gform_after_submission: body => ' . print_r( $body, true ) ); // Uncomment the below line to debug, if necessary GFCommon::log_debug( 'gform_after_submission: headers => ' . print_r( $headers, true ) ); // Nitro API request via cURL $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => 'https://pr29718.nitro-web.beta.hq.powerapp.cloud/recruiting/api/v2/candidates', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POST => true, CURLOPT_POSTFIELDS => $body, CURLOPT_HEADER => true, CURLOPT_HTTPHEADER => $headers, )); $response = curl_exec($curl); curl_close($curl); // Uncomment below line to debug, if necessary GFCommon::log_debug( 'gform_after_submission: response => ' . print_r( $response, true ) ); }
解决方案
方法1:直接构建适配cURL的重复键请求体
PHP关联数组不允许重复键,但cURL处理CURLOPT_POSTFIELDS时,若传入索引数组(每个元素是单个键值对的关联数组),会自动生成带重复键的表单数据。修改构建请求体的逻辑:
// 省略前面获取字段的代码... // 初始化body为索引数组,逐个添加字段 $body = []; // 添加固定字段 $body[] = ['candidate[resume]' => $resume]; $body[] = ['candidate[first_name]' => $first_name]; $body[] = ['candidate[last_name]' => $last_name]; $body[] = ['candidate[email]' => $email]; $body[] = ['candidate[phone]' => $phone]; $body[] = ['job_posting_public_id' => $job_id]; $body[] = ['candidate[source_id]' => $source_id]; // 处理筛选问题,将每个id和answer拆分为独立元素 foreach ($screening_questions as $screening_question=>$sq) { $sq = $sq == 'yes' ? 'true' : 'false'; $body[] = ['screening_questions[][id]' => $screening_question]; $body[] = ['screening_questions[][answer]' => $sq]; } // 后续cURL代码保持不变
方法2:API支持的话用JSON格式提交(更规范)
如果API接受application/json请求体,可以用嵌套数组替代重复键,结构更清晰:
// 省略前面获取字段的代码... // 构建JSON结构的请求体 $jsonBody = [ 'candidate' => [ 'first_name' => $first_name, 'last_name' => $last_name, 'email' => $email, 'phone' => $phone, 'source_id' => $source_id // 注意:文件上传通常不支持JSON格式,若需传简历仍用表单提交 ], 'job_posting_public_id' => $job_id, 'screening_questions' => [] ]; // 添加筛选问题 foreach ($screening_questions as $id => $answer) { $jsonBody['screening_questions'][] = [ 'id' => $id, 'answer' => $answer === 'yes' ? true : false ]; } // 修改cURL配置发送JSON $headers[] = 'Content-Type: application/json'; curl_setopt_array($curl, [ CURLOPT_URL => 'https://pr29718.nitro-web.beta.hq.powerapp.cloud/recruiting/api/v2/candidates', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => json_encode($jsonBody), CURLOPT_HEADER => true, CURLOPT_HTTPHEADER => $headers, ]);
内容的提问来源于stack exchange,提问作者Trisha
相关产品推荐
相关产品推荐

