php - 将数据存储到数组中,然后在while循环中一个一个地访问它
问题描述
背景
我在使用 MySql 制作的数据库中有一个表,其中包括几列。其中两个是“名称”和“地址”。
我有一个用 PHP 编写的函数,它接收两个地址并使用 Google 地图 API 返回它们之间的距离。此功能有效。
客观的
- 我想获取表“名称”和“地址”中的两列并将它们存储在 PHP 上的一个变量中。然后,我想将“地址”列中每一行的距离与脚本中硬编码的地址进行比较,并找出距离最短的地址。一旦找到距离最短的地址,我就会回显与之关联的“名称”。
问题
我的问题是我对如何实现数据的搜索和存储缺乏了解。到目前为止,我有这个尝试访问每个地址并计算距离:
$sql = "SELECT name, address FROM users";
$result = $conn->query($sql);
$distance = []; // an array so we can store our distance result in here
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
$distance[] = [
'name' => $row['name'], // user id so you can use it later
'distance' => getDistance($row['address'],$addressTo)
] // get the distance from api and save it on an array
}
}
// now somehow have to get the min distance and name associated with it from that array
- 由于某种原因,这甚至无法编译,在 while 循环结束时会出现解析错误
解析错误:语法错误,意外的 '}'
- 由于我对数组在 PHP 中的工作方式的理解有限,因此我处理此问题的方式不是很有效(至少在我对其他语言中的数组的理解下)。是否有一种功能或方法可以有效地提取地址和随附的相关名称来执行此操作?我将不胜感激。
距离函数
以供参考
function getDistance($addressFrom, $addressTo, $unit = ''){
// Google API key
$apiKey = ' The API key';
// Change address format
$formattedAddrFrom = str_replace(' ', '+', $addressFrom);
$formattedAddrTo = str_replace(' ', '+', $addressTo);
// Geocoding API request with start address
$geocodeFrom = file_get_contents('https://maps.googleapis.com/maps/api/geocode/json?address='.$formattedAddrFrom.'&sensor=false&key='.$apiKey);
$outputFrom = json_decode($geocodeFrom);
if(!empty($outputFrom->error_message)){
return $outputFrom->error_message;
}
// Geocoding API request with end address
$geocodeTo = file_get_contents('https://maps.googleapis.com/maps/api/geocode/json?address='.$formattedAddrTo.'&sensor=false&key='.$apiKey);
$outputTo = json_decode($geocodeTo);
if(!empty($outputTo->error_message)){
return $outputTo->error_message;
}
// Get latitude and longitude from the geodata
$latitudeFrom = $outputFrom->results[0]->geometry->location->lat;
$longitudeFrom = $outputFrom->results[0]->geometry->location->lng;
$latitudeTo = $outputTo->results[0]->geometry->location->lat;
$longitudeTo = $outputTo->results[0]->geometry->location->lng;
// Calculate distance between latitude and longitude
$theta = $longitudeFrom - $longitudeTo;
$dist = sin(deg2rad($latitudeFrom)) * sin(deg2rad($latitudeTo)) + cos(deg2rad($latitudeFrom)) * cos(deg2rad($latitudeTo)) * cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$miles = $dist * 60 * 1.1515;
// Convert unit and return distance
$unit = strtoupper($unit);
if($unit == "K"){
return round($miles * 1.609344, 2).' km';
}elseif($unit == "M"){
return round($miles * 1609.344, 2).' meters';
}else{
return round($miles, 2).' miles';
}
}
解决方案
遍历数据库中的每个条目并循环调用 API 会非常慢。另外,我注意到您的距离计算是从 lat 和 lng 执行的,而不是由 API 直接返回。
您将获得更好的性能(特别是如果您计划拥有大量数据),将每个地址的 lat 和 lng 存储在数据库中(这意味着您只需为每个新地址调用一次) ,然后在没有 API 调用的情况下执行计算。
更好的是只重写查询,以便它执行计算并返回最高结果。看看这个 db fiddle,里面有一些随机的城市。
https://dbfiddle.uk/?rdbms=mysql_5.5&fiddle=56014857919d57a9465938982caced7f
我输出了两个版本的查询,一个显示按距离排序的所有结果,一个限制为最高结果,这样您就可以看到所有城市的排名。
我没有检查距离公式。我试图从你的代码中直接转录,但我没有验证它是否准确,我只是让它在 mySQL 中工作,而且城市的排序似乎是正确的。我没有转换成英里或其他任何东西,所以你可能想在那里检查我的公式,但我假设你比我更了解正确的公式。我只是在这里提供一些 SQL。
计算结果后,在 php 中处理单位转换。
根据您期望拥有的数据量,像这样进行无限制的自我加入可能会减慢速度。有一些方法可以解决这个问题,但由于我不确切知道你的数据会是什么样子,我认为这是另一个话题。
此外,mySQL 中有一个 POINT 数据类型,它可能更适合这种类型的工作,并且可以采用空间索引,这可能会使对数据的任何查询性能更高,如果有很多数据,它可能值得研究。我个人从未使用过它,所以我只是将 lat 和 lng 分别存储在 DECIMAL 中。
https://dev.mysql.com/doc/refman/5.7/en/gis-data-formats.html
推荐阅读
- python - 让递归过程在循环场景中工作(开始 A -> B,然后 B -> A 无限期)
- c - strcat 和返回错误的差异
- java - 在 jersey 异步客户端中,如何等待所有调用完成然后执行一些代码
- python - 如何将选定的值从一种形式传递到另一种形式而不存储
- reactjs - .next 文件夹在生产模式下在 CentOS 上使用 Docker 缺少一些文件
- c++ - 创建字符串的可变参数模板函数
- istio - 用于内部 kube 服务的 ISTIO 服务网格
- c++ - in_avail() 在 sgetn(..,..) 调用后未返回正确的可用字节数
- reactjs - 反应中购物车应用程序中的项目ID问题
- css - '@media' 在 CSS 上无法正常工作以进行响应式设计