You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Yii2中如何将API返回的JSON数据保存到数据库?

嘿,刚好我之前在Yii2里处理过类似的需求,给你一步步拆解怎么把API返回的JSON数据存到数据库:

步骤1:准备数据库表和ActiveRecord Model

首先你得有对应的数据表,假设我们要存的是设备的Ping记录,表结构可以这样设计(适配你返回的字段):

CREATE TABLE ping_records (
    id INT AUTO_INCREMENT PRIMARY KEY,
    msn VARCHAR(20) NOT NULL COMMENT '设备编号',
    ping_datetime DATETIME NOT NULL COMMENT 'Ping时间',
    ping_value INT NOT NULL COMMENT 'Ping值',
    UNIQUE KEY idx_msn_ping_time (msn, ping_datetime) -- 可选,防止同一设备同一时间的重复记录
);

然后用Yii2的Gii工具生成对应的ActiveRecord Model(或者手动写),比如命名为PingRecord,生成后记得在Model里配置好字段映射和验证规则:

// app/models/PingRecord.php
namespace app\models;

use yii\db\ActiveRecord;

class PingRecord extends ActiveRecord
{
    public static function tableName()
    {
        return 'ping_records';
    }

    public function rules()
    {
        return [
            [['msn', 'ping_datetime', 'ping_value'], 'required'],
            [['ping_datetime'], 'safe'],
            [['ping_value'], 'integer'],
            [['msn'], 'string', 'max' => 20],
            [['msn', 'ping_datetime'], 'unique', 'targetAttribute' => ['msn', 'ping_datetime']],
        ];
    }
}
步骤2:解析API返回的JSON数据

不管你是用curl还是Yii2自带的yii\httpclient\Client调用API,拿到返回的JSON字符串后,先把它转成PHP数组(或者对象,看你习惯):

// 假设$apiResponse是API返回的原始JSON字符串
$dataArray = json_decode($apiResponse, true); // 转成关联数组
// 如果想转成对象数组,就用json_decode($apiResponse),后面取值用$item->MSN这种方式
步骤3:保存数据(两种方式)

根据数据量大小,选择合适的保存方式:

方式一:单条循环保存(数据量小的时候用)

这种方式会自动触发Model的验证规则,适合数据量不多的场景:

use app\models\PingRecord;
use Yii;

foreach ($dataArray as $item) {
    $model = new PingRecord();
    // 赋值字段,注意和Model里的属性名对应
    $model->msn = $item['MSN'];
    // 把ISO格式的时间转成数据库支持的DATETIME格式
    $model->ping_datetime = date('Y-m-d H:i:s', strtotime($item['PingDateTime']));
    $model->ping_value = $item['PingValue'];

    // 保存并处理失败情况
    if (!$model->save()) {
        // 可以把错误日志记录下来,方便排查
        Yii::error("保存Ping记录失败: " . print_r($model->errors, true));
    }
}

方式二:批量插入(数据量大的时候用)

如果API返回的数据很多,单条保存效率太低,用批量插入能大幅提升性能,不过要注意批量插入不会自动触发验证,所以最好先做验证:

use app\models\PingRecord;
use Yii;
use yii\db\Command;

$validData = [];
foreach ($dataArray as $item) {
    $model = new PingRecord();
    $model->msn = $item['MSN'];
    $model->ping_datetime = date('Y-m-d H:i:s', strtotime($item['PingDateTime']));
    $model->ping_value = $item['PingValue'];

    // 先验证数据合法性
    if ($model->validate()) {
        $validData[] = $model->attributes;
    } else {
        Yii::error("Ping记录验证失败: " . print_r($model->errors, true));
    }
}

// 批量插入合法数据
if (!empty($validData)) {
    Yii::$app->db->createCommand()
        ->batchInsert(
            PingRecord::tableName(),
            ['msn', 'ping_datetime', 'ping_value'], // 要插入的字段名
            $validData // 待插入的数据数组
        )
        ->execute();
}
额外注意事项
  • 时间格式处理:API返回的2018-05-04T16:33:27是ISO8601格式,用strtotime可以直接转成时间戳,再格式化数据库需要的格式;如果担心时区问题,可以用DateTime类处理:
    $dateTime = new DateTime($item['PingDateTime']);
    $model->ping_datetime = $dateTime->format('Y-m-d H:i:s');
    
  • 重复数据处理:如果API可能返回重复的记录,除了给表加唯一键,也可以在保存前先查询是否存在,避免重复插入;
  • 异常捕获:如果调用API或者保存数据时可能出现网络问题、数据库连接问题,最好加上try-catch块捕获异常,避免程序崩溃。

内容的提问来源于stack exchange,提问作者Moeez

火山引擎 最新活动