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

PHP中可否同时使用||和&&?逻辑判断导致日志邮件重复发送排查

问题定位与修复方案

核心错误1:运算符优先级导致逻辑判断完全错误

PHP中&&的优先级高于||,你原有判断条件:

if (!$lastRun || filectime($log) < strtotime($lastRun) && $this->checkIfAlreadyExists($content) === false) {
    continue;
}

实际执行顺序为:

if (!$lastRun || (filectime($log) < strtotime($lastRun) && $this->checkIfAlreadyExists($content) === false)) {
    continue;
}

和你预期的逻辑完全不符:当已经有上次运行记录时,只有「文件时间早于上次运行+日志不含指定文本」两个条件同时满足才会跳过,只要日志含指定文本,哪怕已经处理过也不会跳过,直接加入发送列表,就会导致重复发送。你删掉&&之后的部分后,条件变成只要有上次运行记录且文件时间早于上次运行就跳过,自然就不会重复发送了,和你遇到的现象完全吻合。

核心错误2:判断逻辑写反

你预期的跳过规则是:只要满足以下任意一个条件就跳过该文件,不加入发送列表

  • 日志中不存在你要检测的指定文本
  • 不是第一次运行,且文件修改时间早于上次运行时间(已处理过)
    原条件完全写反了判断规则,导致已经处理过的符合文本要求的文件不会被过滤。

其他次要错误

  • fclose参数错误:你fopen返回的文件句柄是$open,但你写了fclose($log),$log是文件名字符串,会导致资源泄漏
  • 使用filectime不准确:ctime是文件inode修改时间,判断文件内容是否更新应该用filemtime(文件内容修改时间)
  • $logs变量未初始化:直接在循环里写$logs[]会报Undefined variable警告
  • 正则匹配没必要用preg_match_all:只要判断指定文本是否存在,用preg_match即可,性能更好

修复后完整代码

public function start() {
    $pattern = $this->config["twp_pattern"] ?? '*.log';
    $pathLog = (isset($this->config["twp_path"])) ? trim($this->config["twp_path"], '/') : 'var/log';
    $lastRun = (isset($this->config['twp_last_run'])) ? str_replace('T', ' ', $this->config['twp_last_run']) : false;
    $path = getcwd() . '/' . $pathLog . '/' . $pattern;
    $this->now = new \DateTime();
    // 初始化日志数组
    $logs = [];

    foreach (glob($path) as $log) {
        $open = fopen($log, 'r') or die ('File opening failed');
        $content = fread($open, filesize($log));
        var_dump($content);
        // 修正fclose参数
        fclose($open);
        
        // 修正逻辑:只要不含指定文本,或者已经处理过的文件,直接跳过
        if (
            $this->checkIfAlreadyExists($content) === false
            || ($lastRun && filemtime($log) < strtotime($lastRun))
        ) {
            continue;
        }
        $logs[] = $log;
    }

    $success = true;
    if (!empty($logs)) {
        $success = $this->sendMail($logs);
    }

    if($success === false){
        return false;
    }
    $this->setLastRun();
    return true;
}

public function checkIfAlreadyExists($content){
    // 改用preg_match,只要匹配到一次就返回真
    if (!preg_match('/already exists/', $content)) {
        echo "is not there";
        return false;
    }else{
        echo "is there";
        return true;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 21:15:06