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

JS调用PHP接口报错:Unexpected token '<'问题求助

问题描述

通过JS的fetch调用PHP接口时,执行fetch环节立即抛出错误:Error: Unexpected token '<'。尝试在fetch后添加console.log无法执行,移除JS中的<>标签也未解决问题,附上完整代码请求排查。

相关代码

index.php

<?php
session_start();

use GuzzleHttp\Client;

require 'vendor/autoload.php';

header('Content-Type: application/json');

$apiKey = 'API_KEY';
$model = 'gpt-3.5-turbo';
$endpoint = 'https://api.openai.com/v1/chat/completions';

$userMessage = trim($_POST['message']); 

if (!isset($_SESSION['chat_history'])) {
    $_SESSION['chat_history'] = [];
}

if (!empty($userMessage)) {
    $_SESSION['chat_history'][] = ['role' => 'user', 'content' => $userMessage];
}

$_SESSION['chat_history'] = array_filter($_SESSION['chat_history'], function($message) {
    return !empty($message['content']);
});

$client = new Client();

try {
    $response = $client->post($endpoint, [
        'headers' => [
            'Authorization' => 'Bearer ' . $apiKey,
            'Content-Type' => 'application/json',
        ],
        'json' => [
            'model' => $model,
            'messages' => $_SESSION['chat_history'],
            'max_tokens' => 50,
        ],
    ]);

    $body = $response->getBody();
    $data = json_decode($body, true);

    if (isset($data['choices'][0]['message']['content'])) {
        $botMessage = $data['choices'][0]['message']['content'];
        $_SESSION['chat_history'][] = ['role' => 'assistant', 'content' => $botMessage];
        echo json_encode(['message' => $botMessage]);
    } else {
        echo json_encode(['error' => 'No response from ChatGPT']);
    }

} catch (Exception $e) {
    echo json_encode(['error' => $e->getMessage()]);
}

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
?>

script.js

document.getElementById('chatForm').addEventListener('submit', function (e) {
    e.preventDefault();

    const userMessage = document.getElementById('userMessage').value;
    const chatHistory = document.getElementById('chatHistory');


    chatHistory.innerHTML += `<p><strong>User: </strong> ${userMessage}</p>`;
    document.getElementById('userMessage').value = '';

    
    fetch('index.php', {  // fetching
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: 'message=' + encodeURIComponent(userMessage)
    })
        .then(response => response.json())
        .then(data => {
            if (data.message) {
                chatHistory.innerHTML += `<p><strong>Bot:</strong> ${data.message}</p>`;
                console.log("Gone!")
            } else {
                chatHistory.innerHTML += `<p><strong>Error:</strong> ${data.error}</p>`;
            }
            chatHistory.scrollTop = chatHistory.scrollHeight;
        })
        .catch(error => {
            chatHistory.innerHTML += `<p>Error: ${error.message}</p>`;
            chatHistory.scrollTop = chatHistory.scrollHeight;
        });
});

问题原因及解决办法

核心原因

Unexpected token '<' 说明PHP接口返回的不是合法JSON,而是HTML内容(比如PHP错误提示、警告信息)。你把ini_set('display_errors', 1);放在代码末尾,当PHP执行过程中出现错误时,错误信息会在header('Content-Type: application/json');之后输出,导致返回内容混有HTML格式的错误提示,破坏了JSON结构。

具体问题点

  1. 错误配置位置错误:ini_set和error_reporting放在代码最后,无法提前捕获初始化阶段的错误(比如Guzzle未安装、vendor/autoload.php不存在),这些错误会以HTML形式输出,和JSON内容混合。
  2. 可能存在依赖缺失:如果vendor/autoload.php不存在(未执行composer install安装Guzzle),PHP会直接输出致命错误的HTML页面,导致fetch解析JSON失败。

解决步骤

  1. 调整错误配置位置:把错误配置代码移到PHP最开头,确保错误能被正确捕获或输出格式可控:
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

session_start();

use GuzzleHttp\Client;

require 'vendor/autoload.php';

header('Content-Type: application/json');
// 后续代码不变
  1. 检查依赖安装:确认已执行composer require guzzlehttp/guzzle,确保vendor/autoload.php存在。如果未安装,先执行该命令。
  2. 调试返回内容:在fetch的then里先打印原始响应,确认返回的具体内容:
fetch('index.php', {
    // 原有配置不变
})
.then(response => {
    // 先打印原始响应文本,排查返回内容
    return response.text().then(text => {
        console.log('Raw response:', text);
        return JSON.parse(text);
    });
})
// 后续then/catch逻辑不变

通过打印原始响应,能快速定位是哪部分错误导致的HTML输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 20:26:16