前提条件:
1.数据接口模型为(json):
{
page: 1, //页码
table: "comm_log", //表名
item: [ //数据
{
},{
}
]
}
2.数据总量 的数据接口模型为:
{
table: "comm_account",
count: 49693
}
基本流程
namespace app\db_interface\common;
use think\Db;
class Outface
{
//根据表名查询该表是否存在
public function isExist($table){
$isTable = Db::connect(config('outfaceDb'))->query('SHOW TABLES LIKE "'.$table.'";');
if($isTable){
//表存在
return 1;
}else{
//表不存在
return 0;
}
}
//根据表名查询该表的所有字段名
public function getFiledName($table){
$filed_arr = [];
$filed = Db::connect(config('outfaceDb'))->query('show columns from '.$table.';');
foreach ($filed as $key=>$value){
$filed_arr[$value['Field']] = '';
}
return $filed_arr;
}
//根据表名查询该表的主键
public function getTablePrimaryKey($table){
$primaryKey = NULL;
$filed = Db::connect(config('outfaceDb'))->query('show columns from '.$table.';');
foreach ($filed as $key=>$value){
if(strpos($value['Key'],'PRI') !== false){
$primaryKey = $value['Field'];
}
}
// dump($filed);
return $primaryKey;
}
//curl从数据接口获取1条数据
public function getOneData($url){
$headerArray =array("Content-type:application/json;","Accept:application/json");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch,CURLOPT_HTTPHEADER,$headerArray);
$output = curl_exec($ch);
curl_close($ch);
$output = json_decode($output,true);
$res = $output['item'][0];
return $res;
}
//curl从数据接口获取对应页所有条数据
public function getAllData($url){
$headerArray =array("Content-type:application/json;","Accept:application/json");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch,CURLOPT_HTTPHEADER,$headerArray);
$output = curl_exec($ch);
curl_close($ch);
$output = json_decode($output,true);
return $output;
}
//数据字段匹配
//$table_field : 数据表字段
//$face_data : 接口数据
public function matchField($table_field, $face_data){
foreach ($face_data as $face_key=>$face_value){
$have = 0;
foreach ($table_field as $table_key=>$table_value){
if ($face_key === $table_key){
$have = 1;
}
}
if ( !$have){
return 0;
}
}
return 1;
}
/*
数据插入demo
$table_arr: 需要插入的数据表的字段数组
$data_arr: 需要插入的数据
$table: 需要插入的数据表的名称
$primaryKey: 需要插入的数据表的主键
*/
public function insertDataItem($table_arr, $data_arr, $table, $primaryKey)
{
$data = [];
$error = [];
foreach ($data_arr['item'] as $value){
foreach ($value as $key=>$v){
$table_arr[$key] = $v;
}
$status = $this->matchPrimaryKey($primaryKey, $table_arr[$primaryKey], $table);
if ($status > 0){
$str = $primaryKey.":".$table_arr[$primaryKey]."已存在";
array_push($error, $str );
}else{
array_push($data,$table_arr);
}
}
$res = [];
$res['error'] = $error;
$seccesCount = Db::connect(config('outfaceDb'))->table($table)->insertAll($data);
$res['seccesCount'] = $seccesCount;
return $res;
}
/*
主键匹配判断
$key: 主键名称
$key_data: 主键的数据
$table: 需要插入的数据表的名称
*/
private function matchPrimaryKey($key, $key_data, $table)
{
$status = Db::connect(config('outfaceDb'))->table($table)->where($key,$key_data)->count();
return $status;
}
}
逻辑实现
public function outCheck(){
// 检测需要插入数据的表名是否已经输入
$table = Request::instance()->param('table');
if ($table == NULL){
$error = ["status"=>0 , 'msg'=>'数据表未知'];
exit(json_encode($error));
}
// 检测获取数据的接口地址是否已经输入
$url = Request::instance()->param('url');
if ($url == NULL){
$error = ["status"=>0 , 'msg'=>'数据接口未知'];
exit(json_encode($error));
}
$url = str_replace("-","/",$url);
// 检测获取数据的接口地址是否已经输入
$count_url = Request::instance()->param('curl');
if ($count_url == NULL){
$error = ["status"=>0 , 'msg'=>'数量数据接口未知'];
exit(json_encode($error));
}
$count_url = str_replace("-","/",$count_url);
// 数据接口可用性测试
// 从需要插入数据的数据库检测相应数据表是否存在并获取相应数据表的所有字段
$outface = new Outface();
$isTable = $outface->isExist($table); //数据表存在性检测
if (!$isTable){
exit(json_encode(['status'=>0, 'msg'=>$table.'数据表不存在']));
}
$new_table = $outface->getFiledName($table); //数据表所有字段获取
$primaryKey = $outface->getTablePrimaryKey($table); //数据表主键获取
if ($primaryKey == NULL){
exit(json_encode(["status"=>0 , 'msg'=>'数据接口未知']));
}
$data = $outface->getOneData($url); //接口数据模型获取
// 数据字段匹配检测
$isMatch = $outface->matchField($new_table, $data);
if($isMatch){
$show_res = []; //请求返回信息组
$show_res['error'] = [];
// 插入数据
$count_arr = $outface-> getAllData($count_url);
$n = ceil($count_arr['count']/100); //获取循环次数
$sucessNum = 0;
for ($i=1; $i<=$n; $i++){
$durl = $url."/page/".$i;
$all_data = $outface-> getAllData($durl); //获取当前页面的所有数据
$insert_res= $outface->insertDataItem($new_table, $all_data, $table, $primaryKey);
$sucessNum += $insert_res['seccesCount'];
foreach ($insert_res['error'] as $v){
array_push($show_res['error'], $v);
}
}
$show_res['msg'] = '通过接口'.$url.'成功向表'.$table."插入".$sucessNum."条数据";
exit(json_encode($show_res));
}else{
exit(json_encode(['status'=>0, 'msg'=>'接口'.$url."与".$table.'数据表字段不匹配,检测接口与数据表是否对应或表结构是否有误']));
}
}
前端实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数据对接</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.bootcss.com/qs/6.7.0/qs.min.js"></script>
<style>
.centerDiv{
width: 50%;
background-color: #e3e3e3;
float: left;
padding: 20px;
}
.resInfo{
width: 50%;
float: left;
min-height: 300px;
}
</style>
</head>
<body >
<div id="app">
<div class="centerDiv">
<form>
<div class="form-group">
<label for="exampleInputEmail1">表名:</label>
<input type="text" v-model="table" class="form-control" id="exampleInputEmail1" placeholder="table">
</div>
<div class="form-group">
<label for="exampleInputPassword2">接口地址</label>
<input type="text" v-model='url' class="form-control" id="exampleInputPassword2" placeholder="url">
</div>
<div class="form-group">
<label for="exampleInputPassword3">数量数据接口地址</label>
<input type="text" v-model='curl' class="form-control" id="exampleInputPassword3" placeholder="curl">
</div>
</form>
<button type="button" @click="submitBtnClick" class="btn btn-primary btn-lg btn-block">submit button</button>
</div>
<div class="resInfo">
<p>{
{
resInfo.msg }}</p>
<ul>
<li v-for="(value, index) in resInfo.error" :key="index">
{
{
value }}
</li>
</ul>
</div>
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
table: '',
url: '',
curl: '',
resInfo:"",
},
methods:{
submitBtnClick(){
let qs =Qs;
axios
.post('http://www.tp5.com/index.php/admin/index/outCheck',
qs.stringify({
table: this.table,
url: this.url,
curl: this.curl,
}))
.then(res => {
// console.log(res.data);
this.resInfo = res.data
})
.catch(function (error) {
// 请求失败处理
console.log(error);
});
},
},
})
</script>
</body>
</html>