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

Laravel 10考勤机数据同步问题:连接成功但返回空字符串

考勤机数据同步到Laravel应用时连接成功但返回空字符串的问题解决

问题描述

我在将考勤机数据同步到Laravel 10(PHP 8.1)应用时遇到问题:连接考勤机成功,但返回空字符串,fgets()调用返回false。之前试过ZKLib但响应太慢,所以自己用fsockopen实现同步逻辑。

相关代码

控制器同步方法

public function tarikDataAbsen(AttendanceMachineInformation $attendanceMachineInformation): JsonResponse
{
    $ip = $attendanceMachineInformation->ip_address;
    $port = $attendanceMachineInformation->port;
    $key = $attendanceMachineInformation->key;

    $connect = fsockopen($ip, $port, $errno, $errstr, 1);
    dd($connect); // 打印显示连接资源正常
    $buffer = "";
    if ($connect) {
        $soapRequest = "<GetAttLog><ArgComKey xsi:type=\"xsd:integer\">" . $key . "</ArgComKey><Arg><PIN xsi:type=\"xsd:integer\">All</PIN></Arg></GetAttLog>";
        $newLine = "\r\n";
        fwrite($connect, "POST /iWsService HTTP/1.0" . $newLine);
        fwrite($connect, "Content-Type: text/xml" . $newLine);
        fwrite($connect, "Content-Length: " . strlen($soapRequest) . $newLine . $newLine);
        fwrite($connect, $soapRequest . $newLine);
        while ($response = fgets($connect, 1024)) {
            $buffer .= $response;
        }
    } else {
        echo "Koneksi Gagal";
    }

    $buffer = $this->parseData($buffer, "<GetAttLogResponse>", "</GetAttLogResponse>");
    // dd($buffer);
    $buffer = explode("\r\n", $buffer);

    $export = [];
    for ($a = 0, $aMax = count($buffer); $a < $aMax; $a++) {
        $data = $this->parseData($buffer[$a], "<Row>", "</Row>");
        $export[$a]['pin'] = $this->parseData($data, "<PIN>", "</PIN>");
        $export[$a]['waktu'] = $this->parseData($data, "<DateTime>", "</DateTime>");
        $export[$a]['status'] = $this->parseData($data, "<Status>", "</Status>");
    }
    return response()->json($export);
}

数据解析方法

private function parseData($data, $p1, $p2): string
{
    $data = ' ' . $data;
    $hasil = '';
    $awal = strpos($data, $p1);
    if ($awal != '') {
        $akhir = strpos(strstr($data, $p1), $p2);
        if ($akhir != '') {
            $hasil = substr($data, ($awal + strlen($p1)), ($akhir - strlen($p1)));
        }
    }

    return $hasil;
}

连接资源打印显示正常,但fgets()返回false,导致最终无数据返回。


解决步骤

1. 移除代码中断语句

代码中dd($connect)会直接终止后续所有逻辑执行,包括请求发送和响应读取,这是导致无数据的直接原因。
处理: 删除dd($connect);这一行,让代码完整执行。

2. 修正HTTP请求格式

考勤机SOAP接口对请求格式通常有严格要求,调整以下几点:

  • 将HTTP协议版本从HTTP/1.0改为HTTP/1.1,并增加必填的Host头
  • 用mb_strlen($soapRequest, '8bit')准确计算请求内容的字节长度(避免strlen()处理UTF-8时的误差)
  • 明确指定字符集和连接关闭策略

修改后的请求发送代码:

if ($connect) {
    $soapRequest = "<GetAttLog><ArgComKey xsi:type=\"xsd:integer\">" . $key . "</ArgComKey><Arg><PIN xsi:type=\"xsd:integer\">All</PIN></Arg></GetAttLog>";
    $newLine = "\r\n";
    $contentLength = mb_strlen($soapRequest, '8bit');
    fwrite($connect, "POST /iWsService HTTP/1.1" . $newLine);
    fwrite($connect, "Host: " . $ip . $newLine);
    fwrite($connect, "Content-Type: text/xml; charset=utf-8" . $newLine);
    fwrite($connect, "Content-Length: " . $contentLength . $newLine);
    fwrite($connect, "Connection: Close" . $newLine . $newLine);
    fwrite($connect, $soapRequest);
    
    // 读取响应
    while (!feof($connect)) {
        $buffer .= fgets($connect, 1024);
    }
    fclose($connect); // 主动关闭连接
}

3. 调整超时与读取逻辑

  • 延长fsockopen的超时时间,从1秒改为5秒:fsockopen($ip, $port, $errno, $errstr, 5);
  • 用feof()判断连接状态,避免fgets()提前返回false

4. 优化解析方法逻辑

原parseData方法中,strpos返回0时会被错误判断为空字符串,导致无法匹配开头的标签。修改判断逻辑为严格的!== false:

private function parseData($data, $p1, $p2): string
{
    $hasil = '';
    $awal = strpos($data, $p1);
    if ($awal !== false) {
        $subData = substr($data, $awal + strlen($p1));
        $akhir = strpos($subData, $p2);
        if ($akhir !== false) {
            $hasil = substr($subData, 0, $akhir);
        }
    }

    return $hasil;
}

5. 调试完整响应

在解析SOAP响应前,先打印完整的$buffer,确认是否存在HTTP错误(如400 Bad Request),以便定位接口问题:

// 在解析前添加
dd($buffer);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 04:47:08