PHP中匹配提交数组与MySQL字段实现票务数据正确更新
问题描述
我有如下结构的MySQL数据库表,需要在预订表单提交时,将正确的票种与对应数值匹配,完成表数据更新:
| listing_id | regular_ticket | _other_ticket[0][name] | _other_ticket[1][name] | regular_ticket_sold | _other_ticket[0][sold] | _other_ticket[1][sold] |
|---|---|---|---|---|---|---|
| 149 | regular-ticket | solo-ticket | group-ticket | 5 | 2 | 1 |
表单提交后得到的数组示例:
- 购买所有票种时:
{"listing_id":"149","date_start":"2023-04-28","date_end":"2023-04-28","tickets":[{"ticket":"regular-ticket","value":"1"},{"ticket":"solo-ticket","value":"1"},{"ticket":"group-ticket","value":"1"}]}
- 仅选择一种票种时:
{"listing_id":"149","date_start":"2023-04-28","date_end":"2023-04-28","tickets":[{"ticket":"solo-ticket","value":"1"}]}
我尝试的代码
// update tickets sold function update_ticket_sold( $tickets, $listing_id ) { $countable = array_column($tickets,'value'); //get ticket count from array $other_tickets = get_post_meta( $listing_id, '_other_tickets', true); if (!empty($tickets[0]['ticket']) && $tickets[0]['ticket'] == 'regular-ticket') { //$tickets_count = (float) $countable[0]; $already_sold_tickets = (int) get_post_meta($listing_id,'regular_ticket_sold',true); $sold_now = $already_sold_tickets + (float) $countable[0]; update_post_meta($listing_id,'regular_ticket_sold',$sold_now); } if(isset($other_tickets) && is_array(($other_tickets))){ $i = 0; foreach ($other_tickets as $key => $ticket) { if(in_array(($ticket['sold']),array_column($tickets,'sold'))) { $column = '_other_tickets[][sold]'; $already_sold_tickets = (int) get_post_meta($listing_id,$column,true); $sold_now = $already_sold_tickets + (float) $countable[$i]; update_post_meta($listing_id,$column,$sold_now); $i++; } } } }
期望效果
- regular_ticket票种对应更新regular_ticket_sold字段
- **_other_ticket[0][name]票种对应更新_other_ticket[0][sold]**字段
- **_other_ticket[1][name]票种对应更新_other_ticket[1][sold]**字段
当前问题
普通票选中时能正确更新数据库,但其他票种选中时无法更新,还会出现“Undefined array key 1”和“Undefined array key 2”的警告。
缩小问题范围后的情况
现在仅需解决票种与对应销量的正确映射问题。例如未购买solo-ticket但购买了group-ticket时,group-ticket的数值会错误映射到solo-ticket的销量字段。以下是简化后的测试代码:
function update_ticket_sold( array $tickets, $_other_tickets ) { $countable = array_column($tickets,'value'); //get ticket count from array $other_tickets = $_other_tickets; if(isset($other_tickets) && is_array(($other_tickets))) foreach (array_values($other_tickets) as $i => $ticket) { $column = '_other_tickets[ {$i}][sold]'; $already_sold_tickets = 0; $sold_now = $already_sold_tickets + (float) $countable[$i]; echo "Debug Objects: " . $i . ":" . $ticket['name'] . " = " . $countable[$i] . " Sold: " . $sold_now . "\n"; } } } // Sample arrays used // Dynamic Tickets as selected by user $tickets = [ array ( "ticket" => "solo-ticket", "value" => "0" ), array ( "ticket" => "group-ticket", "value" => "1" ) ]; // Dynamic Other Ticket types set in the database $_other_tickets = [ array ( "name" => "solo-ticket", "value" => "1" ), array ( "name" => "group-ticket", "value" => "1" ) ]; // Run function print_r(update_ticket_sold($tickets, $_other_tickets ));
解决方案
核心问题是依赖数组索引匹配票种和销量,当提交的票种顺序/数量与数据库不一致时,就会出现映射错误。正确做法是先把提交的tickets数组转换成以票种名称为键的关联数组,直接通过票种名称匹配购买数量。
修改后的测试代码:
function update_ticket_sold(array $tickets, $_other_tickets) { // 构建票种-购买数量的关联数组 $ticketQuantities = []; foreach ($tickets as $ticket) { $ticketQuantities[$ticket['ticket']] = (float)$ticket['value']; } if (isset($_other_tickets) && is_array($_other_tickets)) { foreach (array_values($_other_tickets) as $i => $ticket) { $ticketName = $ticket['name']; // 未购买的票种默认数量为0,避免索引错误 $quantity = $ticketQuantities[$ticketName] ?? 0; $column = "_other_tickets[{$i}][sold]"; $already_sold_tickets = 0; // 实际场景替换为get_post_meta获取已售数量 $sold_now = $already_sold_tickets + $quantity; echo "Debug Objects: " . $i . ":" . $ticketName . " = " . $quantity . " Sold: " . $sold_now . "\n"; // 实际场景执行update_post_meta($listing_id, $column, $sold_now); } } } // 测试用例:只买group-ticket $tickets = [ ["ticket" => "group-ticket", "value" => "1"] ]; $_other_tickets = [ ["name" => "solo-ticket", "value" => "1"], ["name" => "group-ticket", "value" => "1"] ]; update_ticket_sold($tickets, $_other_tickets);
关键改进点
- 构建映射数组:
$ticketQuantities直接通过票种名称关联购买数量,彻底摆脱索引依赖 - 安全取值:用
??运算符处理未购买的票种,默认数量为0,消除Undefined索引警告 - 精准匹配:遍历数据库票种时,直接通过名称从映射数组取对应数量,确保映射正确
整合完整业务逻辑的版本:
function update_ticket_sold($tickets, $listing_id) { // 构建票种-购买数量的关联数组 $ticketQuantities = []; foreach ($tickets as $ticket) { $ticketQuantities[$ticket['ticket']] = (float)$ticket['value']; } // 更新普通票 if (isset($ticketQuantities['regular-ticket'])) { $already_sold = (int)get_post_meta($listing_id, 'regular_ticket_sold', true); $sold_now = $already_sold + $ticketQuantities['regular-ticket']; update_post_meta($listing_id, 'regular_ticket_sold', $sold_now); } // 更新其他票种 $other_tickets = get_post_meta($listing_id, '_other_tickets', true); if (isset($other_tickets) && is_array($other_tickets)) { foreach (array_values($other_tickets) as $i => $ticket) { $ticketName = $ticket['name']; $quantity = $ticketQuantities[$ticketName] ?? 0; $column = "_other_tickets[{$i}][sold]"; $already_sold = (int)get_post_meta($listing_id, $column, true); $sold_now = $already_sold + $quantity; update_post_meta($listing_id, $column, $sold_now); } } }
这个版本无论提交的票种顺序如何,都能精准对应数据库字段完成更新。
内容的提问来源于stack exchange,提问作者Kudown lod
相关产品推荐
相关产品推荐

