php - PHP injects bogus unreadable characters into array after it crosses a certain size
问题描述
This issue has been causing me a headache over the last month. What this code does is take a list of client sites and measures it against a list of contractor addresses. Each client site is a key to an array with 5 objects (5 nearest contractors) as its values. The problem happens when I give it more than ~30 client addresses to match it against my database (205 vendors) and find the closest 5 vendors for each site, PHP injects bogus characters(as pictured). Also, when these characters show up(they show up towards the end of the output), the array never finishes as it stops before the closing bracket or a few lines before that, this happens both before I use json_encode and after.
The bogus characters change around but they're usually : �</p>
What I've tried:
- Encoding everything to UTF-8 (This includes all values in the code as well as in the file settings themselves)
- Change my database from running off a CSV table to a MySQL table.
- Used JsonSerializable for my objects.
- Raising the memory limit in my php.ini.
- Fiddling with the json_encode options
What I know:
- The bogus characters are entered into the array itself, not after using json_encode().
- Results are the same whether I encode to UTF-8 or not.
- This didn't show up when I used json_encode for each client site separately (but was stuck not knowing how to append the json arrays into one large json array after the loop is done)
parseclientsite.php
<?php
$tmpName ="clientsitelist.xlsx";
require "vendor/autoload.php";
include("Libraries/SimpleXLSX.php");
include("database.php");
$xlsx = SimpleXLSX::parse($tmpName);
$xlsx = $xlsx->rows();
parseSiteFile($xlsx);
function parseSiteFile($siteArray){
$nomenclatureBuilding = ["Street Address", "Site Address", "Address", "Site", "street address", "Street address"];
$nomenclaturePostcode = ["Postcode", "Post code", "post code", "postcode", "Post Code"];
$n = 0;
$b = false;
$correctHeaders = $correctPairing = [];
$correctList = array();
foreach ($siteArray as $key => $value) {
if (!$b) {
//first row header
for ($i = 0; $i <= count($value) - 1; $i++) {
$correctHeaders[$value[$i]] = "";
if (in_array($value[$i], $nomenclatureBuilding,)) {
$streetColumn = trim($value[$i]);
}
if (in_array($value[$i], $nomenclaturePostcode,)) {
$postcodeColumn = trim($value[$i]);
}
}
$b = true;
continue;
}
foreach ($correctHeaders as $key2 => $value2) {
$correctPairing[$key2] = trim($value[$n]) ?? null;
$n++;
}
$n = 0;
if (isset($postcodeColumn)) {
$siteAddress = trim($correctPairing[$streetColumn] . " " . $correctPairing[$postcodeColumn] . ", Australia");
array_push($correctList, createSingleQuery($siteAddress));
} else {
$siteAddress = trim($correctPairing[$streetColumn] . ", Australia");
array_push($correctList, createSingleQuery($siteAddress));
}
}
echo json_encode($correctList, JSON_PARTIAL_OUTPUT_ON_ERROR| JSON_PRETTY_PRINT | JSON_UNESCAPED_LINE_TERMINATORS| JSON_INVALID_UTF8_IGNORE);
}
function createSingleQuery($siteAddress)
{
$httpClient = new Client();
$provider = new GoogleMaps($httpClient, null, 'key');
$geocoder = new StatefulGeocoder($provider, 'en');
$siteCoordinates = $geocoder->geocodeQuery(GeocodeQuery::create($siteAddress));
if ($siteCoordinates->isEmpty() == 1) {
$latitude1 = "0";
$longitude1 = "0";
} else {
$latitude1 = trim($siteCoordinates->get(0)->getCoordinates()->getLatitude());
$longitude1 = trim($siteCoordinates->get(0)->getCoordinates()->getLongitude());
}
$correctList[$siteAddress] = readDatabase($latitude1, $longitude1);
return $correctList;
}
?>
database.php
include("classes.php");
if (isset($_GET['location'])) {
$query = $_GET['location'];
singleQuery($query);
}
function readDatabase($latitude1, $longitude1){
$dbhost = 'localhost';
$dbuser = 'user';
$dbpass = 'password';
$conn = mysqli_connect($dbhost, $dbuser, $dbpass, 'vendors', 0,'/var/run/mysqld/mysqld.sock');
$sql = "SELECT BHS_Rate_Ex_GST, After_Hours_Rate_Ex_GST, Phone_Number, Company_Name, Street_Address, Charges_KM_Rate, Latitude, Longitude FROM mytable";
$result = $conn->query($sql);
$measurement = array();
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$vendorSite = array();
array_push($vendorSite, $row["Latitude"], $row["Longitude"]);
array_push($measurement, new Vendor(
$row["BHS_Rate_Ex_GST"],$row["After_Hours_Rate_Ex_GST"], $row["Phone_Number"], $row["Company_Name"], $row["Street_Address"], compareDistance($latitude1, $longitude1, $vendorSite), $row["Charges_KM_Rate"]));
}
usort($measurement,function($first,$second){
return $first->Distance <=> $second->Distance;
});
return $measurement = array_slice($measurement,0, 5);
}
$conn->close();
}
function compareDistance($latitude1, $longitude1, $vendorSite)
{
$earthMeanRadius = 6371;
$latitude2 = floatval($vendorSite[0]);
$longitude2 = floatval($vendorSite[1]);
$dLat = deg2rad($latitude2 - $latitude1);
$dLon = deg2rad($longitude2 - $longitude1);
$a = sin($dLat / 2) * sin($dLat / 2) + cos(deg2rad($latitude1)) * cos(deg2rad($latitude2)) * sin($dLon / 2) * sin($dLon / 2);
$c = 2 * asin(sqrt($a));
return round(($earthMeanRadius * $c), 2);
}
classes.php
class Vendor {
public function __construct($Cost, $Ah, $Phone, $Name, $Address, $Distance, $Travel) {
$this->Cost = $Cost;
$this->Ah = $Ah;
$this->Phone = $Phone;
$this->Name = $Name;
$this->Address = $Address;
$this->Distance = $Distance;
$this->Travel = $Travel;
}
public function __toString() {
return $this->Cost . ' ' . $this->Ah . ' ' .$this->Phone . ' ' . $this->Name
. ' ' . $this->Address . ' ' . $this->Distance. ' ' . $this->Travel;
}
}
解决方案
代码没问题,PHPstorm 的服务器是罪魁祸首。
推荐阅读
- mysql - 如何统一日期并添加各自的时间?
- kotlin - Jackson YAML 合并操作符反序列化错误
- python - 使用pygame中的坐标检查矩形列表中的矩形
- python - 如何解决 django 中的反向匹配错误
- javascript - 引导弹出窗口隐藏在 Firefox 浏览器的输入组内不起作用
- python - 如何在 mysql 数据库的表中添加 json 文件?
- scala - 是否将同步 HTTP 请求包装在被视为 CPU 或 IO 约束的 Future 中?
- javascript - 将一个字母替换为空时出错,然后将其与 javaScript 和 cypress 中的数字进行比较
- javascript - 如果使用 JS 调用,则不应用转换
- excel - 从单元格中的列表中提取重复项