Composer如何与PHP的内置Web服务器协同工作? (脚本启动)

13次阅读

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

Composer如何与PHP的内置Web服务器协同工作? (脚本启动)

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 一个 MonologLogger 就会失败
  • 内置服务器的 -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.phpcomposer.json 在同一项目根目录,且内容开头有:
    require __DIR__ . '/vendor/autoload.php';

router.php 必须处理好自动加载与请求转发

这个文件不只是“转发给 index.php”,它得先兜住自动加载,再决定是否交由框架或原生逻辑处理。

 require __DIR__ . '/vendor/autoload.php'; } else {     die('vendor/autoload.php not found. Run "composer install" first.'); }  // 简单路由:所有非静态资源请求都交给 public/index.php if (preg_match('/.(?:png|jpg|jpeg|gif|css|js|ico|xml|txt|pdf|woff2|ttf)$/', $_SERVER["REQUEST_URI"])) {     return false; // 让内置服务器自己处理静态文件 }  // 其他请求全部代理给 public/index.php(或你的实际入口) $_SERVER['SCRIPT_NAME'] = '/index.php'; $_SERVER['SCRIPT_FILENAME'] = __DIR__ . '/public/index.php'; include __DIR__ . '/public/index.php'; 
  • return false 是 PHP 内置服务器的约定:表示“我不处理,请你按文件系统找”
  • 别用 requireinclude_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

text=ZqhQzanResources