PHP循环过早退出

时间:2015-06-28 10:43:08

标签: php json laravel-5 guzzle

对PHP很新,我被困在(我认为)一个奇怪的问题上。我将这个文件拼接在一起(它被分成几个不同的函数)进行测试,并且更容易解释这个问题。

这是Laravel中的一个基本的while循环,它似乎过早地退出但奇怪的是没有退出到循环之后的行,但是在循环之前退出然后再次进入。不能为我的生活锻炼为什么。我在整个函数中添加了一些日志事件,因此我可以尝试了解发生了什么。

这是正确地将数据提取和写入数据库直到第7页,然后我得到了一个" Start API Helper"日志上的事件,但永远不会得到一个" End API帮助"。所以在第7页的某处导致while循环退出上面的行,将pagecount重置为0.然后重新进入循环,获取第一批产品并在写入时抛出SQL重复键异常。我知道它会在循环之前退出,因为我得到了一个"之前",之后"新客户"在日志中。当然,页面数量正在重置。怎么会发生这种情况?

任何帮助都会非常感激。

public function store()
{
    $items = array();
    Log::info('Before while');
    $pagecount = 0;
    $prodcount = 1;
     while ($prodcount > 0) {
        Log::info('Top of while');
        $prodcount = 0; // Reset product counter
        Log::info('Page Count:'.$pagecount);
        Log::info('Start API Helper');
    $headers = array(
        'NETOAPI_KEY' => env('NETO_API_KEY'),
        'Content-Type' => 'application/json',
        'Accept' => 'application/json',
        'NETOAPI_ACTION' => 'GetItem'
    );
    Log::info('Headers Declared');
    $body = '{
        "Filter": {
            "DateAddedFrom" : "2013-06-01 12:00:00",
            "Page": "'.$pagecount.'",
            "Limit": "500",
            "OutputSelector": [
                **Lots of JSON here - removed for readability**
            ]
        }
    }'; 

    Log::info('Start API Helper');
    $client = new client();
    Log::info('New Client');
    try {
       $res = $client->post(env('NETO_API_URL'), [ 'headers' => $headers , 'body' => $body ]);
    } catch (RequestException $e) {
        echo $e->getRequest();
        Log::error($e->getRequest());
        if ($e->hasResponse()) {
            echo $e->getResponse();
            Log::error($e->getResponse());
        }
    }
    Log::info('End API Helper');
    $items = json_decode(utf8_encode($res->getBody()), true);
        foreach($items["Item"] as $item)
        {
            // JSON is returning an empty array for empty strings. Need to convert to empty string for SQL save.
            foreach($item as $key => $value){
                if (empty($value)) {
                     $item["$key"] = "";
                }
            }
            $Product = new Item;
            $Product->SKU = array_get($item, 'SKU');
            ** LOTS OF DB FIELDS REMOVED FROM HERE FOR READABILITY**
            $Product->save();
            $prodcount++;               
        } 
        $pagecount++;
        Log::info($prodcount.' products written to DB:');
        Log::info('Bottom of while'); 
    };
    Log::info('Exited While'); 
    return 'Complete';
}

更新:我已将ELoquent SQL客户端修改为firstorNew,以避免任何潜在的重复键错误。现在,日志显示相同的'而退出'在第7页(偶尔第8页),然后在第0页重新进入循环,但最奇怪的是它似乎最终有2个循环运行的实例。然后最终3个实例,然后是4.然后它抛出一个内存耗尽异常。日志看起来像。

local.INFO: Page Count:1
local.INFO: Page Count:2
local.INFO: Page Count:3
local.INFO: Page Count:4 
local.INFO: Page Count:5 
local.INFO: Page Count:6 
local.INFO: Page Count:7 
local.INFO: Page Count:8
local.INFO: Page Count:0
local.INFO: Page Count:9
local.INFO: Page Count:1
local.INFO: Page Count:10 
local.INFO: Page Count:2
local.INFO: Page Count:11 
local.INFO: Page Count:3
local.INFO: Page Count:12 

......等等......

错误的JSON API响应是否可能导致此问题?也许我会尝试将分页限制在25左右,所以我可以访问导致循环中断的响应?

1 个答案:

答案 0 :(得分:0)

从第7页开始,我猜你会用完所有要处理的行,并且以下API调用会以某种方式失败:

try {
       $res = $client->post(env('NETO_API_URL'), [ 'headers' => $headers , 'body' => $body ]);
    } catch (RequestException $e) {
        echo $e->getRequest();
        Log::error($e->getRequest());
        if ($e->hasResponse()) {
            echo $e->getResponse();
            Log::error($e->getResponse());
        }
    }

关于你的循环重新输入的方式可能是因为你将store方法包装在另一个try重试的catch中?因为我无法在函数中看到任何尝试捕获,这将指示循环重新启动。

我的建议是将你的方法重写为do-while循环并修改你的while条件:

while ($prodcount === 500)

这样可以确保您不会进行任何后续的API调用,而这些调用对您来说没有任何意义,也可以降低代码中出现问题的可能性。

另一个很好的检查是在您的回复对象上:

if (!isset($items["Item"])) {
    echo 'Response contains no "Item" value';
    exit;
}

除此之外,如果不添加更多日志记录和更多var_dump()/ print_r()来逐步执行逻辑,这很难解决。

古德勒克。