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

PHP追加URL到XML文件时,定时任务执行后原有内容被覆盖如何解决

现有代码的核心问题

每次执行定时任务时的操作逻辑天然会覆盖旧内容:

  • 直接初始化全新的DOMDocument实例
  • 从头创建空的<urlset>根节点
  • 把本次遍历的1000条URL挂在这个新的空根节点下
  • 最后执行$dom->save($xFile)时,会用内存里这个全新的空结构+本次新数据,完整覆盖本地已有的XML文件,全程没有读取合并旧文件里的已有内容。
    另外原代码还存在两个冗余bug:
  • 加载XML的simplexml_load_file($xFile)返回结果全程没有被使用,属于无效代码
  • 创建<url>节点后没有把实际URL值写入节点,最终生成的XML只有空壳结构
  • $page++的计数放在了无校验判断的循环最外层,和实际数据处理进度不匹配,容易出现分页偏移错误

分步修正实现逻辑

1. 匹配你的业务场景拆分处理分支

你的运行逻辑是分多轮处理全量5000条数据,要先判断当前是“新一轮全量任务刚开始”,还是“同一轮任务的中间分页执行”:

  • 新一轮刚开始:直接清空旧XML,新建符合站点地图规范的空urlset结构
  • 同一轮的中间分页:加载已有XML的内容,把新校验通过的URL追加进去,不覆盖旧节点

2. 代码层面的具体调整点

  • 取消每次运行都新建DOM的逻辑,改为根据场景加载已有XML:
    • 检测到是任务首轮(缓存存的page值为0),就新建标准urlset结构
    • 否则就用DOMDocument::load()读取已有XML文件的全部内容,拿到已存在的urlset根节点
  • 遍历校验通过的新URL时,直接把新建的<url>节点append到已存在的根节点下,不要重新创建根节点
  • 分页计数逻辑修正:把$page++放到URL校验通过的判断分支里,和实际拉取、处理的偏移量对齐
  • 当检测到MySQL拉取的结果为空(也就是全量5000条处理完),再把缓存的page值重置为0,触发下一轮全量刷新时清空旧XML的逻辑

3. 修正后的核心代码片段参考

public function urlcheck()
{
    $xFile = $this->base_path."sitemap/path/urls.xml";
    $cache_key = 'valid_urls';
    $page = $this->cache->redis->get($cache_key) ?: 0;

    // 初始化DOM与根节点:分场景处理
    $dom = new DOMDocument('1.0','UTF-8');
    $dom->formatOutput = true;

    // 判断是否是新一轮任务(page=0代表从头开始拉取全量数据)
    if ($page == 0) {
        // 新建空的标准urlset根节点
        $root = $dom->createElement('urlset');
        $root->setAttribute('xsi:schemaLocation', 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd');
        $root->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
        $root->setAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9');
        $dom->appendChild($root);
    } else {
        // 同一轮的分页执行,加载已有XML内容
        if (file_exists($xFile)) {
            $dom->load($xFile);
            $root = $dom->getElementsByTagName('urlset')->item(0);
        } else {
            // 异常兜底:文件不存在时按新一轮逻辑新建
            $root = $dom->createElement('urlset');
            $root->setAttribute('xsi:schemaLocation', 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd');
            $root->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
            $root->setAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9');
            $dom->appendChild($root);
        }
    }

    // 拉取当前分页的URL数据
    $this->load->model('productnew/productnew_es6_m');
    $urls= $this->db->query("SELECT url FROM product_data where `active` = 1 limit ".$page.",1000")->result();

    foreach($urls as $val)
    {   
        // 这里放你原来的URL合法性校验逻辑
        $is_valid = true;
        if (!$is_valid) {
            $page++;
            continue;
        }
        // 校验通过的才追加到XML
        $url_node = $dom->createElement('url');
        $root->appendChild($url_node);

        $loc = $dom->createElement('loc', $val->url);
        $url_node->appendChild($loc);

        $lastmod = $dom->createElement('lastmod', date("Y-m-d"));
        $url_node->appendChild($lastmod);

        $page++;
    }

    // 保存合并后的完整XML,不会覆盖旧节点
    $dom->save($xFile) or die('XML Create Error');
    
    // 拉取结果为空,代表全量5000条处理完,重置page触发下一轮刷新
    if(empty($urls)){
        $page = 0;
    }
    print_r($page);
    $this->cache->redis->save($cache_key, $page, 432000);
}

额外注意细节
  • 不要用file_put_contents直接拼接XML字符串追加,很容易破坏XML的根节点闭合结构,一定要通过DOM对象的节点操作完成合并,保证XML结构合法
  • 当5000条数据全量处理完后,下一次任务启动时page=0,就会自动新建空的XML结构,满足“整体刷新”的需求,不需要手动删除旧文件

内容的提问来源于stack exchange,提问作者Jayakiran

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.22 12:15:04