最稳妥方式是用 composer create-project slim/slim-skeleton 初始化项目,它自动集成 PSR-7 实现(nyholm/psr7)、错误处理、路由示例等完整骨架,避免手动配置导致的 404 或 getServerParams() 等隐形错误。

直接用 composer create-project 初始化 Slim 项目最稳妥
Slim 不是那种装上就能跑的“库”,它依赖特定目录结构和启动入口,直接 composer require slim/slim 后自己拼 index.php 容易漏掉 PSR-7 实现或错误处理器。官方推荐方式是生成完整骨架项目——省去手动配路由、中间件、异常处理的隐形坑。
执行这条命令:
composer create-project slim/slim-skeleton my-app
它会自动拉取 slim/slim、nyholm/psr7(现代 PSR-7 实现)、slim/psr7(兼容层)、php-di/php-di(可选容器),还带好 public/index.php 和基础路由示例。别跳过这步,否则后续调试 404 Not Found 或 Call to undefined method getServerParams() 会反复卡住。
-
my-app是项目目录名,可改,但别含空格或中文 - 如果提示
zlib_decode(): data error,说明 Composer 缓存损坏,先运行composer clear-cache - PHP 版本必须 ≥ 8.1,Slim 5 不再支持 7.x,硬降级会触发
TypeError: Unsupported operand types
手动 require Slim 时必须显式指定 PSR-7 实现
有人想最小化安装,只敲 composer require slim/slim,结果一跑就报 Class "Laminas\Diactoros\ServerRequest" not found 或类似找不到 PSR-7 类的错误——Slim 5 起彻底移除了对任何 PSR-7 库的硬依赖,你得自己选一个并注册。
推荐用 nyholm/psr7(轻、快、无扩展依赖):
composer require slim/slim:^5 nyholm/psr7
然后在 index.php 里手动绑定:
$app = \Slim\Factory\AppFactory::create();
$app->get('/', function ($request, $response) {
return $response->write('Hello');
});
$app->run();
- 不能只装
slim/slim就以为万事大吉,PSR-7 实现是运行前提 - 别用
laminas/laminas-diactoros(旧版 Diactoros),它在 PHP 8.2+ 有兼容问题,nyholm/psr7是当前事实标准 - 如果用了
php-di/php-di,记得调用\Slim\Factory\AppFactory::createFromContainer($container),否则容器不会生效
微服务场景下必须关掉 displayErrorDetails 并加日志中间件
Slim 默认开发模式会把完整堆栈暴露给 HTTP 响应体,微服务之间调用时,这个行为等于把内部路径、数据库凭证(万一误打日志)直接吐给上游服务,极其危险。
生产环境必须关掉,并接入结构化日志:
$app = \Slim\Factory\AppFactory::create(); $app->addErrorMiddleware(true, true, true); // 三个 bool 分别对应 displayErrorDetails / logErrors / logErrorDetails // 改成: $app->addErrorMiddleware(false, true, false);
- 第一个参数
false:禁用错误详情输出到响应体 - 第二个参数
true:确保错误仍写入日志(需提前配置Psr\Log\LoggerInterface) - 第三个参数
false:不记录敏感上下文(如$_SERVER全量数据) - 若用 Monolog,通过
$app->add(new \Monolog\Handler\StreamHandler('php://stderr'))接入,别依赖默认行为
路由参数捕获后类型永远是 string,别假设自动转 int
写 $app->get('/user/{id}', ...) 然后在回调里直接 $id + 1?会得到 "1231" 这种字符串拼接结果。Slim 的路由参数全为 string,PHP 不会隐式转换,尤其在数据库查询或类型严格校验时容易翻车。
安全做法是显式过滤:
$app->get('/user/{id}', function ($request, $response, $args) {
$id = filter_var($args['id'], FILTER_VALIDATE_INT);
if ($id === false) {
return $response->withStatus(400)->write('Invalid ID');
}
// 此时 $id 是 int
});
- 别依赖
(int)强转,(int)"123abc"会得123,静默截断很危险 - RESTful 场景下,ID 为空、负数、超长数字都该单独校验,Slim 不做这些
- 如果用 PHP 8+,可以配合
match表达式做更清晰的类型分支,但别省略验证步骤










