对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左右,所以我可以访问导致循环中断的响应?
答案 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()来逐步执行逻辑,这很难解决。
古德勒克。