Composer 通过 scripts 封装 php -S 命令并配合 router.php 显式引入 autoload.php,解决内置服务器不自动加载类的问题;router.php 需位于项目根目录且首行 require DIR . '/vendor/autoload.php',-t public/ 指定静态资源目录,未命中文件则交由 router.php 处理。

Composer 本身不直接启动 PHP 内置服务器,但能通过 scripts 配置项封装并增强启动逻辑——关键在于让 php -S 正确加载 router.php 并识别 Composer 自动加载机制。
为什么直接 php -S localhost:8000 会报 Class not found
PHP 内置服务器默认不执行 autoload.php,所有依赖类(包括你 require 的 vendor 包)在请求时无法自动加载。即使 index.php 开头写了 require 'vendor/autoload.php',也仅对该文件生效;而路由分发时若用到其他入口或中间件,容易漏载。
-
router.php必须显式引入vendor/autoload.php,否则路由逻辑中 new 一个Monolog\Logger就会失败 - 内置服务器的
-t参数只控制文档根目录,不影响自动加载路径 - 不要依赖当前工作目录下存在
autoload.php—— 启动脚本可能从任意路径调用
在 composer.json 中定义可复用的启动脚本
利用 Composer 的 scripts 功能,把带 router 和自动加载的命令固化下来,避免每次手动敲一长串。
{
"scripts": {
"serve": [
"echo 'Starting dev server on http://localhost:8000'",
"php -S localhost:8000 -t public/ router.php"
]
}
}
注意两点:
立即学习“PHP免费学习笔记(深入)”;
- 脚本数组中第一条是纯提示,不会影响执行;第二条才是真实命令
-
-t public/表示静态资源(如public/index.php)由内置服务器直接服务,但所有未匹配静态文件的请求都会被router.php拦截 - 确保
router.php和composer.json在同一项目根目录,且内容开头有:require __DIR__ . '/vendor/autoload.php';
router.php 必须处理好自动加载与请求转发
这个文件不只是“转发给 index.php”,它得先兜住自动加载,再决定是否交由框架或原生逻辑处理。
-
return false是 PHP 内置服务器的约定:表示“我不处理,请你按文件系统找” - 别用
require或include_once替代include,否则某些框架(如 Slim)的重复初始化会出错 - 如果项目用的是 Laravel,应改用
public/index.php而非index.php,路径必须严格匹配
运行前务必检查 vendor/autoload.php 是否存在
很多人执行 composer serve 报错说找不到类,其实只是忘了先装依赖。Composer 不会自动帮你跑 install。
- 首次使用前必须运行:
composer install - 如果
vendor/是 gitignored,CI 或新环境部署时容易遗漏这步 - 可在
scripts.serve前加个检查逻辑(用 shell 命令),但跨平台兼容性差;更稳妥的做法是写进 README 或 CI 脚本里
最常被忽略的一点:PHP 内置服务器的 router.php 是每个请求都重执行的,所以自动加载语句不能省,也不能靠全局变量缓存 —— 每次都要重新 require autoload.php。











