我有一个问题-我需要插入数据从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();
?>
发布于 2018-10-11 06:49:48
这就是你的问题
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循环之后插入/更新。通过构建我们可以在一个查询中插入的视频in数组。您不需要为JSON数据的每个循环(其设置方式)执行一次查询。
如下所示:
$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
的索引更改为复合(复合)“唯一”索引,该索引包含两个字段,分别是channelid
和videoId
。这两个参数必须相同,才能将该行视为重复行。
接下来,在channelId
上添加一个简单的索引(非惟一的)。您希望它有自己的索引,因为为了让复合索引正常工作,您通常不需要同时提供两个字段(按照索引的顺序)。这就是说,我确实忘记了(在DB和Mongo等其他东西之间),所以如果它是第一个,你也许可以使用它。你可以随时解释并确保它使用它。不管怎样,你想要那个索引,因为我们要用它来做查找,很好地索引它是很好的。
接下来,您必须完全摆脱videoId1
和videoId2
。如果您不想丢失其中的数据,那么可以创建一个迁移脚本,将这些值从这两个字段中提取出来,并为它们创建一个新行。
然后转到代码上。
$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)
,我就是这么做的。这使我们不必复制变量(它不应该出现在这里),但即使当您准备它时,它也会使它更容易。
命名约定,例如channelid
、videoId
和channelId
。这看起来似乎没什么大不了的,但事实确实如此。虽然每个人都有自己的方式,但最重要的部分是“保持一致”。我更喜欢没有大写的,空格的下划线,复数表名。所以对我来说,这些应该是channel_id
,video_id
。通过了解这一点并保持一致性,我不必再回顾一年前创建的表的模式,并怀疑它是channelid
、ChannelId
、channelID
、channelId
还是channel_id
。正如你所看到的,大小写的版本比小写的版本(4+和2)有更多的变化。列名中的空格在MySQL中是不允许的,因为您必须用回格对它们进行转义,所以这永远不是问题。
您覆盖了内部循环中的$row
变量,即用于JSON的变量,因此我将其改为$items
。您也不需要来自JSON的channelid
,因为您已经在查询(和url)中找到了它。
享受吧!
https://stackoverflow.com/questions/52748204
复制相似问题