You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:38:03