Composer autoload 找不到 mysqli 等原生类是因为它们由 PHP 解释器启动时注册,与 Composer 无关;问题通常源于扩展未启用、PHP 版本阉割或 php.ini 配置不一致。

Composer autoload 为什么找不到系统原生类
Composer 的 autoload 机制默认只处理 PHP 文件中声明的类(class、interface、trait),且仅在启用自动加载时触发。它**不会执行任何文件的顶层代码**,更不会“加载”或“包含”像 mysqli、curl_init() 这类 PHP 内置扩展提供的原生类/函数——这些是 PHP 解释器启动时就已注册的,跟 Composer 无关。
如果你遇到 “Class ‘mysqli’ not found” 或类似报错,问题不在 Composer 配置,而在于:
– 对应扩展未启用(如 extension=mysqli 没在 php.ini 中开启)
– 使用了阉割版 PHP(如某些 Docker 镜像默认不装 pdo_mysql)
– 在 CLI 和 Web SAPI 下 php.ini 不一致,导致扩展只在一个环境生效
如何用 Composer 加载无命名空间的全局函数文件
Composer 支持通过 files 类型自动引入纯函数文件(即不含 class 声明、无命名空间、只有函数定义或常量定义的 PHP 文件)。这类文件会在每次调用 composer autoloader 时被 require_once 一次。
操作步骤:
– 在 composer.json 的 autoload.files 数组中添加路径
– 运行 composer dump-autoload 生效
– 确保路径为相对于 composer.json 的相对路径(不是绝对路径,也不是 URL)
示例:
"autoload": {
"files": [
"src/helpers.php",
"lib/legacy_functions.php"
]
}
注意:
– files 中的文件会被无条件加载,哪怕你只 new 了一个类
– 不支持通配符(如 "src/*.php"),必须逐个列出
– 若文件里有重复的函数定义(比如两次 function my_util()),会导致致命错误,上线前务必检查加载顺序和冲突
psr-4 + files 混合使用时的常见陷阱
当项目同时用了 psr-4(面向类)和 files(面向函数)时,容易误以为“所有代码都走 autoload”,从而写出不可靠逻辑:
– 错误假设:在 files 文件中 new 一个 psr-4 类,认为它一定能加载 → 实际上,files 执行时机早于类自动加载触发点,若该类尚未被 require,就会报错
– 错误写法:
// helpers.php
function create_db_connection() {
return new \App\Database\Connection(); // ❌ 可能失败:Connection 类还没被 autoload 加载
}
– 正确做法:把类实例化逻辑移到实际调用处,或确保 files 中只做函数声明、不执行依赖其他类的代码
– 另一个坑:开发时本地 vendor/autoload.php 已加载,但测试脚本直接 require 'helpers.php',会绕过 files 机制,造成行为不一致
替代方案:何时该放弃 files,改用显式 require
files 是方便,但不是万能。以下情况建议放弃它,改用显式 require 或重构:
– 文件体积大、含大量初始化逻辑(如连接数据库、读配置),不该在每次请求都无条件执行
– 函数之间有强依赖顺序(A 必须在 B 之前加载),而 files 数组顺序不总可靠(尤其跨包时)
– 需要按需加载(比如 CLI 命令才需要某组函数),而非全站加载
– 项目已用 PSR-12 或严格静态分析,而 files 引入的函数无法被 IDE 或 PHPStan 正确识别作用域
此时更可控的方式是:
– 将函数封装进工具类(哪怕只是 final class Helpers + 静态方法)
– 或在入口文件(如 index.php 或命令类 handle() 方法开头)显式 require_once
– 或用 Composer 的 autoload-dev.files 仅在开发/测试时加载
真正难的不是让文件被加载,而是让加载时机、作用域和可维护性对齐业务真实需求。很多人卡在“为什么写了 files 却没生效”,其实问题往往出在路径拼错、没运行 dump-autoload,或者根本误解了“加载”的含义。










