Slim

技术栈
后端框架
phpmicro-frameworkrestmiddlewarepsr-7psr-15

概览

Slim\n\nSlim 是 PHP 微框架,专注于 HTTP 请求处理和路由分发。它遵循 PSR-7 和 PSR-15 标准,最适合构建 RESTful API 和小型 Web 应用。\n\n### 核心特性\n\n- 极简设计:核心仅处理路由和中间件\n- PSR-7 原生:完整的 HTTP 消息实现\n- PSR-15 中间件:标准中间件架构\n- 依赖注入:与任何 DI 容器兼容\n- 无约定:自由的项目结构\n- 性能出色:轻量核心,响应迅速\n- 可扩展:丰富的第三方中间件生态\n- Slim 4:最新版,更现代的架构

安装

1. 环境准备

  • OS:Linux / macOS / Windows
  • PHP:>= 8.1(Slim 4)
  • PHP 扩展:json, mbstring, PDO(数据库可选)
  • Composer:最新稳定版
  • Web 服务器:PHP 内置服务器 / Apache / nginx

2. 安装命令

创建项目

composer require slim/slim:"4.*"
composer require slim/psr7
composer require slim/http

安装常用中间件

# 路由缓存
composer require slim/flash

# CORS
composer require tuupola/cors-middleware

# 认证
composer require tuupola/slim-jwt-auth

项目结构

my-api/
├── public/
│   └── index.php    # 入口文件
├── src/
│   ├── Middleware/   # 自定义中间件
│   └── Actions/      # 请求处理器
├── config/
│   └── routes.php    # 路由定义
└── composer.json

启动开发服务器

php -S localhost:8080 -t public/

3. 常见安装问题

PSR-7 实现缺失

composer require slim/psr7
# 或使用 laminas-diactoros
composer require laminas/laminas-diactoros

路由分组报错

确保安装了 slim/http 提供 ResponseFactory

JSON 响应类型

$response->getBody()->write(json_encode($data));
return $response->withHeader('Content-Type', 'application/json');

国内镜像

composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

示例

Hello World:Slim 4 REST API

目标

创建 Slim 4 最小 REST API,展示路由、请求处理和 JSON 响应。

完整代码

1. public/index.php — 入口文件

<?php

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;

require __DIR__ . '/../vendor/autoload.php';

$app = AppFactory::create();

// 可选:添加错误中间件
$app->addErrorMiddleware(true, true, true);

// Hello 端点
$app->get('/api/hello', function (Request $request, Response $response) {
    $payload = json_encode([
        'message' => 'Hello, Vibe!',
        'framework' => 'Slim 4',
        'php_version' => PHP_VERSION,
        'timestamp' => date('c'),
    ], JSON_PRETTY_PRINT);

    $response->getBody()->write($payload);
    return $response->withHeader('Content-Type', 'application/json');
});

// 带参数端点
$app->get('/api/hello/{name}', function (Request $request, Response $response, array $args) {
    $payload = json_encode([
        'message' => "Hello, {$args['name']}!",
        'powered_by' => 'Slim Framework',
    ]);

    $response->getBody()->write($payload);
    return $response->withHeader('Content-Type', 'application/json');
});

// POST 示例
$app->post('/api/echo', function (Request $request, Response $response) {
    $body = json_decode($request->getBody()->__toString(), true);

    $payload = json_encode([
        'you_sent' => $body,
        'received_at' => date('c'),
    ]);

    $response->getBody()->write($payload);
    return $response->withHeader('Content-Type', 'application/json');
});

$app->run();

运行步骤

php -S localhost:8080 -t public/

预期输出

curl http://localhost:8080/api/hello
# {"message":"Hello, Vibe!","framework":"Slim 4","php_version":"8.2.0","timestamp":"..."}

curl http://localhost:8080/api/hello/Vibe
# {"message":"Hello, Vibe!","powered_by":"Slim Framework"}

curl -X POST http://localhost:8080/api/echo \
  -H "Content-Type: application/json" \
  -d '{"foo":"bar"}'
# {"you_sent":{"foo":"bar"},"received_at":"2024-01-01T00:00:00+00:00"}

教程

Slim 4 入门教程:Task API 服务

1. 背景

Slim 是构建轻量 API 的最佳 PHP 框架。本教程将构建完整的 Task CRUD API,掌握路由分组、中间件模式和 PSR-7 消息处理。

2. 前置概念

概念 说明
PSR-7 Request/Response HTTP 消息抽象
PSR-15 Middleware 请求-响应处理链
Route Groups 路由分组共享中间件
Closure vs Class Handler 闭包处理器 vs 类处理器

3. 分步操作

步骤一:项目初始化

mkdir task-api &;& cd task-api
composer require slim/slim:"4.*"
composer require slim/psr7
mkdir -p public src/Handlers

步骤二:数据库初始化

CREATE TABLE tasks (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT NOT NULL,
    description TEXT,
    status TEXT DEFAULT 'pending',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

步骤三: 入口文件 public/index.php

<?php

require __DIR__ . '/../vendor/autoload.php';

use Slim\Factory\AppFactory;

$app = AppFactory::create();
$app->addErrorMiddleware(true, true, true);

// 加载路由
(require __DIR__ . '/../config/routes.php')($app);

$app->run();

步骤四:路由 config/routes.php

<?php

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\App;

return function (App $app) {
    $pdo = new PDO('sqlite:../data/tasks.db');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $app->group('/api/tasks', function ($group) use ($pdo) {

        $group->get('', function (Request $req, Response $res) use ($pdo): Response {
            $stmt = $pdo->query('SELECT * FROM tasks ORDER BY id DESC');
            $payload = json_encode($stmt->fetchAll(PDO::FETCH_ASSOC));
            $res->getBody()->write($payload);
            return $res->withHeader('Content-Type', 'application/json');
        });

        $group->post('', function (Request $req, Response $res) use ($pdo): Response {
            $data = json_decode($req->getBody()->__toString(), true);

            $stmt = $pdo->prepare('INSERT INTO tasks (title, description) VALUES (:title, :description)');
            $stmt->execute([
                ':title' => $data['title'],
                ':description' => $data['description'] ?? '',
            ]);

            $id = $pdo->lastInsertId();
            $payload = json_encode(['id' => $id, 'message' => 'Task created']);

            $res->getBody()->write($payload);
            return $res->withHeader('Content-Type', 'application/json')->withStatus(201);
        });

        $group->put('/{id}', function (Request $req, Response $res, array $args) use ($pdo): Response {
            $data = json_decode($req->getBody()->__toString(), true);

            $stmt = $pdo->prepare('UPDATE tasks SET title = :title, status = :status, updated_at = CURRENT_TIMESTAMP WHERE id = :id');
            $stmt->execute([
                ':title' => $data['title'] ?? '',
                ':status' => $data['status'] ?? 'pending',
                ':id' => $args['id'],
            ]);

            $payload = json_encode(['message' => 'Task updated']);
            $res->getBody()->write($payload);
            return $res->withHeader('Content-Type', 'application/json');
        });

        $group->delete('/{id}', function (Request $req, Response $res, array $args) use ($pdo): Response {
            $stmt = $pdo->prepare('DELETE FROM tasks WHERE id = :id');
            $stmt->execute([':id' => $args['id']]);

            return $res->withStatus(204);
        });
    });
};

4. 验证

php -S localhost:8080 -t public/

curl -X POST http://localhost:8080/api/tasks \
  -H "Content-Type: application/json" \
  -d '{"title":"Learn Slim 4"}'

curl http://localhost:8080/api/tasks

5. 思考题

  1. 如何将闭包路由重构为独立的 Action 类?
  2. 如何添加 JSON 校验中间件?
  3. 如何集成 Eloquent ORM 替代原生 PDO?