入门篇 - 构建 Todo API

知识库
知识库文档
/tech-stacks/symfony/tutorial/入门篇 - 构建 Todo API.md

文档

Symfony 入门教程:构建 Todo API

1. 背景

Symfony 是 PHP 企业级首选框架。本教程带你构建一个 Todo REST API,掌握控制器、ORM (Doctrine)、验证和序列化的核心用法。

2. 前置概念

概念 说明
Entity Doctrine ORM 映射到数据库表
Repository 实体查询类
Validation Symfony Validator 约束验证
Serializer 对象 ↔ JSON 序列化
Maker Bundle make: 命令快速生成代码

3. 分步操作

步骤一:创建项目

symfony new todo-api --webapp
cd todo-api

步骤二:创建 Todo 实体

php bin/console make:entity Todo

按提示输入字段:

  • titlestring255 → not null
  • descriptiontext → nullable
  • completedboolean → default false

编辑 src/Entity/Todo.php 添加验证:

<?php

namespace App\Entity;

use App\Repository\TodoRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

#[ORM\Entity(repositoryClass: TodoRepository::class)]
class Todo
{
    #[ORM\Id, ORM\GeneratedValue, ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    #[Assert\NotBlank, Assert\Length(min: 3, max: 255)]
    private ?string $title = null;

    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $description = null;

    #[ORM\Column]
    private bool $completed = false;

    // getters & setters...
}

步骤三:迁移数据库

php bin/console make:migration
php bin/console doctrine:migrations:migrate

步骤四:创建控制器

php bin/console make:controller TodoController
<?php

namespace App\Controller;

use App\Entity\Todo;
use App\Repository\TodoRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Validator\Validator\ValidatorInterface;

#[Route('/api/todos')]
class TodoController extends AbstractController
{
    #[Route('', methods: ['GET'])]
    public function index(TodoRepository $repo): JsonResponse
    {
        return $this->json($repo->findAll());
    }

    #[Route('', methods: ['POST'])]
    public function create(Request $request, EntityManagerInterface $em, ValidatorInterface $validator): JsonResponse
    {
        $data = json_decode($request->getContent(), true);
        $todo = new Todo();
        $todo->setTitle($data['title'] ?? '');
        if (isset($data['description'])) $todo->setDescription($data['description']);

        $errors = $validator->validate($todo);
        if (count($errors) > 0) {
            return $this->json(['errors' => (string) $errors], 422);
        }

        $em->persist($todo);
        $em->flush();

        return $this->json($todo, 201);
    }

    #[Route('/{id}', methods: ['GET'])]
    public function show(Todo $todo): JsonResponse
    {
        return $this->json($todo);
    }

    #[Route('/{id}', methods: ['PUT'])]
    public function update(Request $request, Todo $todo, EntityManagerInterface $em): JsonResponse
    {
        $data = json_decode($request->getContent(), true);

        if (isset($data['title'])) $todo->setTitle($data['title']);
        if (isset($data['description'])) $todo->setDescription($data['description']);
        if (isset($data['completed'])) $todo->setCompleted($data['completed']);

        $em->flush();

        return $this->json($todo);
    }

    #[Route('/{id}', methods: ['DELETE'])]
    public function delete(Todo $todo, EntityManagerInterface $em): JsonResponse
    {
        $em->remove($todo);
        $em->flush();
        return $this->json(null, 204);
    }
}

4. 验证

curl -X POST http://localhost:8000/api/todos \
  -H "Content-Type: application/json" \
  -d '{"title":"学习 Symfony"}'

curl http://localhost:8000/api/todos

5. 思考题

  1. 如何用 DTO 解耦请求数据和实体?
  2. 如何使用 API Platform 代替手动编写 CRUD?
  3. 如何添加 JWT 认证保护 API?

信息

路径
/tech-stacks/symfony/tutorial/入门篇 - 构建 Todo API.md
更新时间
2026/5/31