PHP动态子数组键存在性检查及数据库写入问题求助
解决stdClass对象遍历后变量残留导致数据库写入错误的问题
我明白你的问题了:当遍历包含不同属性的stdClass对象数组时,缺失length属性的对象会沿用前一次循环中$length变量的值,导致数据库的NoCarrages字段写入错误内容。这是因为PHP中变量在循环外不会自动重置,未被重新赋值的变量会保留之前的值。
核心解决方案思路
我们需要确保每次循环开始时,所有要插入数据库的变量都被初始化为默认值(比如空字符串),或者直接在插入时检查对象是否存在对应属性,不存在则传入空值。下面提供两种可行的修改方案:
方案1:循环前初始化所有变量(推荐)
在遍历每个$obj之前,先将所有需要用到的变量重置为空,这样即使对象缺失某个属性,变量也不会保留上一次的旧值:
require("../../../../sysscripts/rail/OpenLDBWS.php"); $OpenLDBWS = new OpenLDBWS("my_token"); $data = $OpenLDBWS->GetDepartureBoard(100,"$Station"); header("Content-Type: text/plain"); $results=$data->GetStationBoardResult; $generatedAt=$results->generatedAt; $origin_crs=$results->crs; $message=$results->nrccMessages->message->{'_'}; $platform=$results->platformAvailable; /* The services... */ $service=$results->trainServices->service; if( is_array( $service ) ){ foreach( $service as $index => $obj ){ // 初始化所有需要插入的变量为空,避免旧值残留 $serviceID = ''; $std = ''; $etd = ''; $operator = ''; $length = ''; $isCancelled = ''; $cancelReason = ''; $delayReason = ''; $DeleteCode = ''; $DeleteTime = ''; // 遍历对象属性,覆盖已初始化的变量 $objVars = get_object_vars( $obj ); foreach( $objVars as $key => $value ){ ${$key} = $value; } // 处理关联属性,同时做存在性检查避免报错 $origin_location = isset($origin->location->locationName) ? $origin->location->locationName : ''; $generatedAt = date("Y-m-d H:i"); $dest_location = isset($destination->location->locationName) ? $destination->location->locationName : ''; $crsName = isset($destination->location->crs) ? $destination->location->crs : ''; $via = isset($destination->location->via) ? $destination->location->via : ''; // 构建插入SQL $insertSQL = sprintf("INSERT INTO UKRail_departboards (RecordDate, ServiceID, Origin_location, Origin_crs, Platform, ScheduleTime, Estimated, Dest_location, Dest_crs, Operator, Message, IsCancelled, CancelReason, DelayedReason, DeleteCode, NoCarrages, Via, DeleteTime) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", GetSQLValueString($generatedAt, "date"), GetSQLValueString($serviceID, "text"), GetSQLValueString($origin_location, "text"), GetSQLValueString($origin_crs, "text"), GetSQLValueString($platform, "text"), GetSQLValueString($std, "text"), GetSQLValueString($etd, "text"), GetSQLValueString($dest_location, "text"), GetSQLValueString($crsName, "text"), GetSQLValueString($operator, "text"), GetSQLValueString($message, "text"), GetSQLValueString($isCancelled, "text"), GetSQLValueString($cancelReason, "text"), GetSQLValueString($delayReason, "text"), GetSQLValueString($DeleteCode, "text"), GetSQLValueString($length, "text"), GetSQLValueString($via, "text"), GetSQLValueString($DeleteTime, "text") ); mysql_select_db($database_ex, $ex); $Result1 = mysql_query($insertSQL, $ex) or die(mysql_error()); } }
方案2:直接在SQL插入时检查属性存在性
如果你不想初始化所有变量,可以直接在构建SQL时,针对可能缺失的字段(比如length)检查对象是否存在该属性,不存在则传入空值:
// 只修改SQL中NoCarrages对应的部分,其他代码不变 GetSQLValueString(property_exists($obj, 'length') ? $obj->length : '', "text")
这种方式更简洁,不需要遍历赋值变量,直接从对象中取值,避免了变量残留的问题。
额外提示
注意你当前使用的mysql_*函数已经被PHP官方废弃,建议后续迁移到mysqli_*或PDO扩展,提升代码的安全性和兼容性。
内容的提问来源于stack exchange,提问作者DCJones
相关产品推荐
相关产品推荐

