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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 14:37:04