首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Php将json数据从上到下插入到mysql中

Php将json数据从上到下插入到mysql中
EN

Stack Overflow用户
提问于 2018-10-11 04:21:22
回答 1查看 179关注 0票数 0

我有一个问题-我需要插入数据从json到mysql,但它是插入最后一个videoId,它是3个相同的videoId插入7EDPROQa4i0。我需要从上到下从json到数据库的插入。我不明白出了什么问题

JSON数据库

代码语言:javascript
复制
{
  "resultsPerPage": 3
 },
 "items": [
  {
   "id": {
    "videoId": "kHPqpxDE50c"
   },
   "snippet": {
    "channelId": "UCiP20o92_7jUYwj-ulVLifw",
    },
   }
  },
  {
   "id": {
    "videoId": "DbAlCl3kk-M"
   },
   "snippet": {
    "channelId": "UCiP20o92_7jUYwj-ulVLifw",
    },
   }
  },
  {
   "id": {
    "kind": "youtube#video",
    "videoId": "7EDPROQa4i0"
   },
   "snippet": {
    "channelId": "UCiP20o92_7jUYwj-ulVLifw",
    },
   }
  }
 ]
}

PHP代码:

代码语言:javascript
复制
    $loop = mysqli_query($conn, "SELECT channelid, videoId FROM users ORDER BY id")
    or die (mysqli_error($conn));

    while ($row = mysqli_fetch_array($loop))
    {
        $url = 'https://www.googleapis.com/youtube/v3/search?order=date&part=snippet&channelId='.$row['channelid'].'&maxResults=3&key=KEY';
        $content = file_get_contents($url);
        $json = json_decode($content, true);

        foreach($json['items'] as $row)
        {
            $channelid = $row['snippet']['channelId'];
            $videoId = $row['id']['videoId'];
            $videoId1 = $row['id']['videoId'];
            $videoId2 = $row['id']['videoId'];
            $sql = "INSERT INTO users(channelid, videoId, videoId1, videoId3) VALUES('$channelid', '$videoId', '$videoId1', '$videoId2')    
            ON DUPLICATE KEY UPDATE channelid='$channelid', videoId='$videoId', videoId1='$videoId1', videoId2='$videoId2';
            ";
            mysqli_query($conn, "SET NAMES utf8");
            if(!mysqli_query($conn,$sql))
            {
                die('Error : ' . mysqli_error($conn));
            }
        }
    }
$conn->close();
?>
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-10-11 06:49:48

这就是你的问题

代码语言:javascript
复制
foreach($json['items'] as $row){
    ...
    $videoId = $row['id']['videoId'];
    $videoId1 = $row['id']['videoId'];
    $videoId2 = $row['id']['videoId'];
     $sql = "INSERT INTO users(channelid, videoId, videoId1, videoId3) VALUES('$channelid', '$videoId', '$videoId1', '$videoId2')    
        ON DUPLICATE KEY UPDATE channelid='$channelid', videoId='$videoId', videoId1='$videoId1', videoId2='$videoId2';
        ";
    ...
}

基本上发生的是获取您的第一个JSON数据(我将只关注值部分):

代码语言:javascript
复制
 //iteration 1
 VALUES('UCiP20o92_7jUYwj-ulVLifw', 'kHPqpxDE50c', 'kHPqpxDE50c', 'kHPqpxDE50c')
//iteration 2
 VALUES('UCiP20o92_7jUYwj-ulVLifw', 'DbAlCl3kk-M', 'DbAlCl3kk-M', 'DbAlCl3kk-M')
//iteration 3
 VALUES('UCiP20o92_7jUYwj-ulVLifw', '7EDPROQa4i0', '7EDPROQa4i0', '7EDPROQa4i0')

现在想想会发生什么。由于您的表的设置方式(我可以补充说是不正确的),我敢打赌chanelid是唯一的。所以每次循环都会覆盖上一次循环中的id。

它是3个相同的videoId插入7EDPROQa4i0

顺便说一句,这就是你所看到的。

要修复它,您必须在JSON循环之后插入/更新。通过构建我们可以在一个查询中插入的视频in数组。您不需要为JSON数据的每个循环(其设置方式)执行一次查询。

如下所示:

代码语言:javascript
复制
$loop = mysqli_query($conn, "SELECT channelid, videoId FROM users ORDER BY id")
or die (mysqli_error($conn));

while ($row = mysqli_fetch_array($loop))
{
    $channelid = $row['channelid'];
    $url = 'https://www.googleapis.com/youtube/v3/search?order=date&part=snippet&channelId='.$channelid .'&maxResults=3&key=KEY';
    $content = file_get_contents($url); 
    $json = json_decode($content, true);    

    if(!isset($json['items'])) continue; //skip if no items

    $videos = ['videoId'=>'','videoId1'=>'','videoId2'=>''];
    $i = 0;
    foreach($json['items'] as $items)
    {
        $key  = 0==$i ? 'videoId' : 'videoId'.$i;
        $videos[$key] = $items['id']['videoId']; 
        ++$i;
    }

    $sql = "INSERT INTO users(channelid, videoId, videoId1, videoId3) VALUES('$channelid', '{$videos['videoId']}', '{$videos['videoId1']}', '{$videos['videoId2']}')    
        ON DUPLICATE KEY UPDATE channelid=VALUES(channelid), videoId=VALUES(videoId), videoId1=VALUES(videoId1), videoId2=VALUES(videoId2);
        ";
    mysqli_query($conn, "SET NAMES utf8");
    if(!mysqli_query($conn,$sql))
    {
        die('Error : ' . mysqli_error($conn));
    }
}

这就解决了当前的问题。然而,这里有一个更大的问题,那就是表是如何设置的,以及如何使用它。在你拥有它的方式,你被限制在3个视频,即使这是你需要的全部,在某些时候你可能想要更多。每个人都想要更多,这是既定的。要将其更新为具有4个、5个或6个列,需要在中添加额外的列,这是不好的。

更深层的问题

更好的方法是对每个视频使用1行。那么我们如何做到这一点呢?

首先要做的是导出这个表(这样您就有了一个备份)

然后将channelid的索引更改为复合(复合)“唯一”索引,该索引包含两个字段,分别是channelidvideoId。这两个参数必须相同,才能将该行视为重复行。

接下来,在channelId上添加一个简单的索引(非惟一的)。您希望它有自己的索引,因为为了让复合索引正常工作,您通常不需要同时提供两个字段(按照索引的顺序)。这就是说,我确实忘记了(在DB和Mongo等其他东西之间),所以如果它是第一个,你也许可以使用它。你可以随时解释并确保它使用它。不管怎样,你想要那个索引,因为我们要用它来做查找,很好地索引它是很好的。

接下来,您必须完全摆脱videoId1videoId2。如果您不想丢失其中的数据,那么可以创建一个迁移脚本,将这些值从这两个字段中提取出来,并为它们创建一个新行。

然后转到代码上。

代码语言:javascript
复制
$loop = mysqli_query($conn, "SELECT DISTINCT channelid FROM users ORDER BY id")
or die (mysqli_error($conn));

while ($row = mysqli_fetch_array($loop))
{
    $channelid = $row['channelid'];
    $url = 'https://www.googleapis.com/youtube/v3/search?order=date&part=snippet&channelId='.$channelid .'&maxResults=3&key=KEY';
    $content = file_get_contents($url);
    $json = json_decode($content, true);

    if(!isset($json['items'])) continue; //skip if no items

    foreach($json['items'] as $items)
    {
        $videoId = $items['id']['videoId'];
        $sql = "INSERT INTO users(channelid, videoId) VALUES('$channelid', '$videoId')    
        ON DUPLICATE KEY UPDATE channelid=VALUES(channelid), videoId=VALUES(videoId);
        ";
        mysqli_query($conn, "SET NAMES utf8");
        if(!mysqli_query($conn,$sql))
        {
            die('Error : ' . mysqli_error($conn));
        }
    }
}

这更接近于原始查询,但我们在第一个查询和DISTINCT中只使用了一个字段。其余部分应该不言而喻。

当你提取数据时,你只需要循环结果,因为每一行都是一个视频。从长远来看,这会让事情变得更简单,我保证。

Other things

您还会遇到SQL注入问题,因为这可能不太容易破解,但为什么要冒这个风险呢?任何时候,只要将数据连接到查询中,就会打开SQLInjection的大门。即使数据是100%安全的,您也不会因为总是准备查询而损失任何东西。有很多关于如何做到这一点的教程。

您可以在复制部分中使用VALUES(column),我就是这么做的。这使我们不必复制变量(它不应该出现在这里),但即使当您准备它时,它也会使它更容易。

命名约定,例如channelidvideoIdchannelId。这看起来似乎没什么大不了的,但事实确实如此。虽然每个人都有自己的方式,但最重要的部分是“保持一致”。我更喜欢没有大写的,空格的下划线,复数表名。所以对我来说,这些应该是channel_idvideo_id。通过了解这一点并保持一致性,我不必再回顾一年前创建的表的模式,并怀疑它是channelidChannelIdchannelIDchannelId还是channel_id。正如你所看到的,大小写的版本比小写的版本(4+和2)有更多的变化。列名中的空格在MySQL中是不允许的,因为您必须用回格对它们进行转义,所以这永远不是问题。

您覆盖了内部循环中的$row变量,即用于JSON的变量,因此我将其改为$items。您也不需要来自JSON的channelid,因为您已经在查询(和url)中找到了它。

享受吧!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52748204

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档