问题描述
我正在为 DB 条目构建循环调用 API 的 cron 作业,并且存在性能问题。
特别是这部分:
if (!empty($sudCode) && !empty($sudbroj) && isset($sudCode) && isset($sudbroj)) {
// echo $sudCode . "<br>";
// echo $sudbroj . "<br>";
$epredmet = ePredmeti($sudCode,$sudbroj);
// print_r($epredmet);
// echo "<br>";
if (isset($epredmet["data"]["prvi"]["lastUpdateTime"])) {
$lastUpdateTime = $epredmet["data"]["prvi"]["lastUpdateTime"];
$dateTime = str_replace("T"," ",$lastUpdateTime);
echo $nas . " - " . $dateTime . "<br>";
}
}
在线:
if (isset($epredmet["data"]["prvi"]["lastUpdateTime"])) {
我的数据库很少,当到达此行时,服务器在 2 分钟后转到 504 Gateway Time-out
。
托管公司表示它超时是因为 Apache Web 服务器等待 PHP 解析器处理数据,这意味着什么。
奇怪的是,如果我忽略了如果检查我脚本完成并且我得到结果但是注意:Trying to access array offset on value of type null in
因为我希望 API 调用后的 $epredmet
看起来像这样:
- array(1) { ["data"]=> array(1) { ["prvi"]=> NULL } } // case not found
- array(1) { ["data"]=> array(1) { ["prvi"]=> array(1) { ["lastUpdateTime"]=> NULL } } } // case found but lastUpdateTime is not set,null
- array(1) { ["data"]=> array(1) { ["prvi"]=> array(1) { ["lastUpdateTime"]=> string(23) "2021-06-14T22:51:22.171" } } } // case found and lastUpdateTime is set
所以我需要做的是过滤掉最后一个设置了 lastUpdateTime
的情况,我读到的所有内容都是建议用 isset
解决它,但由于某种原因,这破坏了我的脚本。
PHP V 7.4
请指教。
我附上完整的脚本,以防有人在其他地方发现问题:
function eSudovi()
{
$endpoint = "xxx";
$qry = '{"query":"query{sudovi {id,sudNaziv}}"}';
$headers = array();
$headers[] = 'Content-Type: application/json';
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$endpoint);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$qry);
curl_setopt($ch,CURLOPT_POST,CURLOPT_HTTPHEADER,$headers);
$result = curl_exec($ch);
curl_close($ch);
return json_decode($result,true);
}
$eSudovi = eSudovi()["data"]["sudovi"];
function findSudCode($val,$eSudovi)
{
foreach ($eSudovi as $key => $value) {
if ($value["sudNaziv"] == $val) {
return $value["id"];
}
}
}
function ePredmeti($sud,$pred)
{
$endpoint = "xxx";
$qry = '{"query":"query{ prvi:predmet(sud: ' . $sud . ',oznakabroj: \"' . $pred . '\") {lastUpdateTime}}"}';
$headers = array();
$headers[] = 'Content-Type: application/json';
$ch = curl_init();
curl_setopt($ch,$headers);
$result = curl_exec($ch);
curl_close($ch);
return json_decode($result,true);
}
$results = MysqLi_query($con,"
SELECT disTINCT predf_nas_br,predf_odv,predf_SUD,predf_SUDbroJ
FROM PREDMETIFView
WHERE predf_SUD <> '' AND predf_SUDbroJ <> '' AND predf_SUDbroJ NOT LIKE '% %'
UNION ALL
SELECT disTINCT predp_nas_br,predp_odv,predp_SUD,predp_SUDbroJ
FROM PREDMETIPView
WHERE predp_SUD <> '' AND predp_SUDbroJ <> '' AND predp_SUDbroJ NOT LIKE '% %'
;");
while ($row = $results->fetch_assoc()) {
foreach ($row as $key => $value) {
if ($key == "predf_nas_br") {
$nas = $value;
}
if ($key == "predf_SUD") {
$sud = trim($value);
if (!empty($sud) && isset($sud)) {
$sudCode = findSudCode($sud,$eSudovi);
}
};
if ($key == "predf_SUDbroJ") {
$sudbroj = trim($value);
};
if (!empty($sudCode) && !empty($sudbroj) && isset($sudCode) && isset($sudbroj)) {
// echo $sudCode . "<br>";
// echo $sudbroj . "<br>";
$epredmet = ePredmeti($sudCode,$sudbroj);
print_r($epredmet);
echo "<br>";
if (isset($epredmet["data"]["prvi"]["lastUpdateTime"])) {
$lastUpdateTime = $epredmet["data"]["prvi"]["lastUpdateTime"];
$dateTime = str_replace("T",$lastUpdateTime);
echo $nas . " - " . $dateTime . "<br>";
}
}
}
};
// preg_match('/\s/',$sudbroj)
编辑:
我也试过这个:
if (isset($epredmet["data"]["prvi"]["lastUpdateTime"]) && !empty($epredmet["data"]["prvi"]["lastUpdateTime"])) {
还有这个:
if (isset($epredmet["data"]["prvi"]) && !empty($epredmet["data"]["prvi"])) {
if (isset($epredmet["data"]["prvi"]["lastUpdateTime"]) && !empty($epredmet["data"]["prvi"]["lastUpdateTime"])) {
同样的事情,它会挂起,但如果没有它,它会与错误一起工作。
解决方法
像这样可以重用 curl 句柄(注意:还没有时间测试它,但你会明白的)。
class ePredmeti{
public $epredmet;
private $curl,$ini_opt;
function __construct(){
$endpoint ='xxx';
$headers = ['Content-Type: application/json'];
$timeout = 30;
$this->curl= curl_init();
$this->ini_opt=[
CURLOPT_URL => $endpoint,CURLOPT_RETURNTRANSFER => true,CURLOPT_POST => true,CURLOPT_HTTPHEADER => $headers,CURLOPT_CONNECTTIMEOUT => $timeout,CURLOPT_TIMEOUT => $timeout
];
}
public function _exec($sud,$pred){
$start=microtime(true);
$this->epredmet = null;
$query_opt=[
CURLOPT_POSTFIELDS=>
'{"query":"query{ prvi:predmet(sud: ' . $sud . ',oznakaBroj: \"' . $pred . '\") {lastUpdateTime}}"}'
];
curl_reset($this->curl);
curl_setopt_array($this->curl,$this->ini_opt);
curl_setopt_array($this->curl,$query_opt);
$ret = curl_exec($ch);
if (!curl_errno($this->curl)){
if(curl_getinfo($this->curl,CURLINFO_HTTP_CODE)!==200){
echo 'HTTP error: '.$http_code.'<br>';
}
else{
$this->epredmet = json_decode($ret,true);
}
}
else{
echo curl_error($this->curl).'<br>';
}
echo 'Took: '.(microtime(true)-$start).'<br>';
}
}
在 while()
之前放一些类似的东西:
$mycurl = new ePredmeti();
而不是 $epredmet = ePredmeti($sudCode,$sudBroj);
使用
$mycurl->_exec($sudCode,$sudBroj);
最后,您可以使用 if (isset($epredmet["data"]["prvi"]["lastUpdateTime"])) {
代替
if( isset($mycurl->epredmet["data"]["prvi"]["lastUpdateTime"]) ) {
最后一个有效,因为该类在出现任何错误时返回 null
,而 isset()
检查变量是否存在且不为空。