尝试访问 API 调用循环中类型为 null 和 isset 问题的数组偏移量 - 504 网关超时服务器

问题描述

我正在为 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() 检查变量是否存在且不为空。