如何在WordPress PHP函数中优雅地将JSON插入MySQL?
优化WordPress中API数据批量插入MySQL的代码
问题场景
从公开API获取约1000条JSON数据,每条包含20个字段,但部分字段可能在部分数据中缺失(直接省略而非返回空值)。原代码通过手动逐个检查字段是否存在来避免报错,代码冗余繁琐,需要更简洁高效的实现方式。
优化后的代码
function or_load_bookings() { global $wpdb; $client = new Client([ 'base_uri' => 'https://api.somesite.com/', 'auth' => ['user', 'pass'], 'headers' => ['Content-Type' => 'application/json'] ]); try { $from_date = '2018-01-01'; $to_date = '2023-01-10'; $property_ids = "133945,265690,338679"; $response = $client->request('GET', 'bookings', [ 'query' => [ 'limit' => '100', 'include_charges' => 'True', 'property_ids' => $property_ids, 'from' => $from_date, 'to' => $to_date ] ]); $json = json_decode($response->getBody()); // 重置数据表 $wpdb->query($wpdb->prepare('DROP TABLE IF EXISTS bookings')); $wpdb->query($wpdb->prepare('CREATE TABLE bookings ( adults int, arrival varchar(255), booked_utc varchar(255), check_in varchar(255), check_out varchar(255), children int, currency_code varchar(255), departure varchar(255), form_key varchar(255), guest_id bigint, id bigint, infants int, is_block tinyint, listing_site varchar(255), notes varchar(255), pets int, platform_reservation_number varchar(255), property_id bigint, `status` varchar(255), thread_ids varchar(255), total_amount decimal(10,2), total_host_fees decimal(10,2), total_paid decimal(10,2), `type` varchar(255) )')); // 定义字段映射:字段名 => [默认值, 可选处理回调] $field_mapping = [ 'adults' => ['', null], 'arrival' => ['', null], 'booked_utc' => ['', null], 'check_in' => ['', null], 'check_out' => ['', null], 'children' => ['', null], 'currency_code' => ['', null], 'departure' => ['', null], 'form_key' => ['', null], 'guest_id' => ['', null], 'id' => ['', null], 'infants' => ['', null], 'is_block' => [0, function($val) { return $val ? 1 : 0; }], 'listing_site' => ['', null], 'notes' => ['', null], 'pets' => ['', null], 'platform_reservation_number' => ['', null], 'property_id' => ['', null], 'status' => ['', null], 'thread_ids' => ['', null], 'total_amount' => ['', null], 'total_host_fees' => ['', null], 'total_paid' => ['', null], 'type' => ['', null] ]; // 提取所有字段名并生成SQL占位符 $fields = array_keys($field_mapping); $field_placeholders = implode(', ', array_fill(0, count($fields), '%s')); $insert_sql = "INSERT INTO bookings (" . implode(', ', $fields) . ") VALUES ($field_placeholders)"; $insert_count = 0; foreach($json->items as $item) { $values = []; foreach($fields as $field) { // 获取字段值,不存在则使用默认值 $val = property_exists($item, $field) ? $item->$field : $field_mapping[$field][0]; // 执行字段特殊处理逻辑 if ($field_mapping[$field][1]) { $val = $field_mapping[$field][1]($val); } $values[] = $val; } // 执行插入并统计成功条数 if ($wpdb->query($wpdb->prepare($insert_sql, $values))) { $insert_count++; } } return 'Loaded ' . $insert_count . ' bookings'; } catch (ClientException $e) { echo 'Request: '.Psr7\Message::toString($e->getRequest()) . '<br>'; echo 'Response: '.Psr7\Message::toString($e->getResponse()) . '<br>'; } }
优化说明
- 集中管理字段规则:通过
$field_mapping数组统一管理所有字段的默认值和特殊处理逻辑,避免重复的isset判断,新增或修改字段只需调整该数组,维护成本大幅降低。 - 动态生成SQL语句:自动从字段映射数组生成插入语句的字段列表和占位符,减少手动拼接SQL的出错概率,代码更简洁。
- 统一值处理逻辑:对需要特殊转换的字段(如
is_block的布尔值转数字),通过回调函数实现,逻辑清晰且可扩展。 - 安全参数绑定:利用
$wpdb->prepare的动态参数数组,确保所有值经过安全转义,彻底避免SQL注入风险。
额外效率优化建议
如果数据量较大(如1000条),可以使用批量插入减少数据库交互次数,提升执行效率:
// 批量插入示例(每50条执行一次) $batch_values = []; $batch_size = 50; foreach($json->items as $item) { $values = []; foreach($fields as $field) { $val = property_exists($item, $field) ? $item->$field : $field_mapping[$field][0]; if ($field_mapping[$field][1]) { $val = $field_mapping[$field][1]($val); } $values[] = $wpdb->_real_escape($val); } $batch_values[] = "('" . implode("', '", $values) . "')"; // 达到批量大小或循环结束时执行插入 if (count($batch_values) >= $batch_size || next($json->items) === false) { $batch_insert_sql = "INSERT INTO bookings (" . implode(', ', $fields) . ") VALUES " . implode(', ', $batch_values); $wpdb->query($batch_insert_sql); $insert_count += count($batch_values); $batch_values = []; } }
内容的提问来源于stack exchange,提问作者Timbo
相关产品推荐
相关产品推荐

