php将json数据从上到下插入mysql?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (169)

嘿我有问题我需要从json插入数据到mysql但它插入最后一个videoId和它的3相同videoId插入7EDPROQa4i0我需要从json数据库从上到下插入我无法理解什么是错的

JSON数据库

{
  "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代码:

    $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();
?>
提问于
用户回答回答于

这是你的问题

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数据(我将只关注值部分):

 //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循环后插入/更新。通过构建一个视频ID数组,我们可以在一个查询中插入。对于JSON数据的每个循环(它的设置方式),您不需要1个查询。

喜欢这个:

$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);    
    $channelid = $row['snippet']['channelId'];
    $videos = [];
    $i = 0;
    foreach($json['items'] as $row)
    {
        $key  = 0==$i ? 'videoId' : 'videoId'.$i;
        $videos[$key] = $row['id']['videoId']; 
    }

    $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复合(复合)“唯一”索引,该索引包含2个字段channelidvideoId字段。对于要被视为重复的行,这两者必须相同。

接下来添加一个简单的索引(非唯一)channelId。你希望它拥有它自己的索引,因为对于复合的一般来说,你不会提供两个字段(按索引的顺序)。这就是说我忘记了(在数据库和Mongo之类的其他东西之间),所以你可以使用一个,如果它是第一个。您可以随时解释并确保使用它。无论如何,你想要那个索引,因为我们将使用它来进行查找并很好地索引它是好的。

接下来,您将不得不摆脱videoId1videoId2彻底。如果你有数据,你不想丢失,你可以创建一个迁移脚本,将从这两个字段中提取值并为它们创建一个新行。

然后到代码上。

$loop = mysqli_query($conn, "SELECT DISTINCT channelid 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'];
        $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。其余的应该是自我解释的。

当您拉出数据时,您只需循环结果,因为每行将是1个视频。从长远来看,这将使事情变得更简单,承诺。

其他事情

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

你可以VALUES(column)在复制部分使用,我做了。这使我们不必复制变量(这不应该在这里),但即使你准备它,它也会使它变得更容易。

命名约定,如channelidVS videoIdVS channelId。这似乎不是什么大不了的事,但确实如此。虽然每个人都有自己的方式,但最重要的部分是“保持一致”。我更喜欢没有大写,空格下划线,多个表名。对我来说,这些将是channel_idvideo_id。通过了解这一点,并正在洽我没有回头看我一年前做了一个表的模式,不知道,如果它是channelidChannelIdchannelIDchannelIdchannel_id。正如您所看到的那样,套装版本的变体更多,然后是小写版本(4+ vs 2)。列名中的空格在MySQL中是非首发的,因为你必须用反对来逃避它们,所以这绝不是一个问题。

请享用!

扫码关注云+社区

领取腾讯云代金券