Symfony 快速上手:一小时搭出能跑的 PHP 应用
先澄清一个拼写: "symphony" PHP 框架,正式名字是 Symfony。2005 年 Fabien Potencier 在 SensioLabs 把它从 "Sensio Framework" 改名时,曾短暂用过 Symphony,2006 年定稿为 Symfony,沿用至今。下面一律按 Symfony 讲。
Symfony 不是一个"单体框架",而是一组可独立复用的 PHP 组件(HttpFoundation、Routing、DependencyInjection、Console 等)再加一套把组件粘起来的全栈骨架。Laravel、Drupal、Magento 的底层都吃着 Symfony 组件。它的定位和 Laravel 不同:Laravel 是"开箱即走的整车",Symfony 是"把轮子、轴承、螺丝都标好型号,让你自己搭"。好处是长期可维护、企业级稳定;代价是上手曲线略陡。
为什么 2026 年还值得学?两个硬理由:一是 LTS 节奏——大版本给 3 年 bug 修复 + 5 年安全补丁,做要维护好几年的系统这是底气;二是它定义了现代 PHP 的共享词汇(PSR 规范、HTTP 消息对象、DI 容器),学会了等于学会了半个 PHP 生态。
截至 2026-08,在维护的版本线:
- Symfony 8.1(2026-05-29 发布,要求 PHP ≥ 8.4)——当前最新稳定
- Symfony 7.4(2025-11-27 发布,要求 PHP ≥ 8.2,LTS,bug 修复到 2028-11、安全到 2029-11)——求稳选它
- Symfony 6.4(LTS,bug 修复到 2026-11)
一、环境与安装
前置条件:
- PHP ≥ 8.4(8.1 线硬性要求),推荐 8.4
- 必需扩展:ctype、iconv、json、mbstring、openssl、pcre、session、simplexml、tokenizer
- Composer 2.x
- 国内用户记得放开插件:
composer config -g allow-plugins true。Composer 2.2+ 默认禁用插件自动加载,不放开会卡在 "loading plugin…"
check:requirements、本地 HTTPS 证书):curl -sS https://get.symfony.com/cli/installer | bash
# 把 ~/.symfony5/bin 加到 PATH,安装脚本结束时会提示具体路径
二、三秒钟建项目
# 完整 Web 应用:含 Twig、Doctrine、Security、Validator、Webpack Encore,开箱即用
symfony new myapp --webapp
# 或只要最小骨架(API / 微服务),之后按需加包
symfony new myapi
# 纯 Composer 等价写法
composer create-project symfony/skeleton:"8.1.*" myapi
注意:symfony new --full 与 website-skeleton 已弃用,新版统一为 --webapp。skeleton 只装核心 4–5 个组件,连控制器都不生成——别慌,这是设计,不是装错了。
跑起来:
cd myapp
symfony serve
# 浏览器开 https://127.0.0.1:8000
symfony serve 自带 HTTPS 和本地证书,比裸 php -S 省心。
三、目录结构(记住一处就够)
myapp/
├── bin/console # CLI 入口
├── config/
│ ├── packages/ # 各 bundle 配置
│ ├── routes/ # 路由定义(若用 yaml)
│ └── services.yaml # 服务容器配置
├── migrations/ # Doctrine 迁移
├── public/index.php # 唯一对外入口(web 根目录)
├── src/
│ ├── Controller/
│ ├── Entity/ # Doctrine 实体
│ ├── Form/
│ ├── Repository/
│ └── Kernel.php
├── templates/ # Twig 模板
├── var/cache/ var/log/
└── .env # 环境变量(含 DATABASE_URL)
唯一对外暴露的是 public/,web 服务器文档根必须指向它。
四、第一个路由 + 控制器 + 模板
src/Controller/DefaultController.php:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class DefaultController extends AbstractController
{
#[Route('/hello/{name}', name: 'app_hello')]
public function hello(string $name): Response
{
return $this->render('default/hello.html.twig', [
'name' => $name,
]);
}
}
注意路由用的是 Symfony\Component\Routing\Attribute\Route。Symfony 7 起老的 Annotation\Route 已经移除,别再照着旧教程抄 use ...Annotation\Route。模板放 templates/default/hello.html.twig:
{% extends 'base.html.twig' %}
{% block body %}
<h1>你好,{{ name }}!</h1>
{% endblock %}
访问 /hello/世界 即可。懒得手写?php bin/console make:controller 一键生成。
五、接数据库(Doctrine ORM)
.env 里配好连接:
DATABASE_URL="postgresql://app:pass@127.0.0.1:5432/app?serverVersion=16&charset=utf8"
建实体(用 MakerBundle,比手写快):
php bin/console make:entity Post
# 交互式加 title(string 255)、body(text)
php bin/console make:migration
php bin/console doctrine:migrations:migrate
生成的实体长这样(节选):
#[ORM\Entity]
class Post
{
#[ORM\Id, ORM\GeneratedValue, ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private string $title = '';
// getter / setter ...
}
取数据用 Repository,控制器里直接类型提示注入:
public function list(PostRepository $repo): Response
{
return $this->render('post/list.html.twig', [
'posts' => $repo->findAll(),
]);
}
六、表单与校验
在实体上加约束:
#[ORM\Column(length: 255)]
#[Assert\NotBlank]
#[Assert\Length(min: 3, max: 255)]
private string $title = '';
php bin/console make:form 生成表单类,控制器里 handleRequest + isValid 走标准流程,CSRF 默认开。Twig 里 {{ form(form) }} 一把渲染。
七、安全(登录鉴权)
php bin/console make:user
php bin/console make:auth
前者生成 User 实体 + UserProvider,后者生成登录表单与 Authenticator。config/packages/security.yaml 里声明防火墙和口令编码器。默认就带 CSRF、XSS 转义、SQL 注入防护。
八、调试三件套
- Web Debug Toolbar:每请求底部一条,SQL、事件、缓存命中、内存一目了然。
php bin/console debug:router看路由表,debug:container看服务,debug:config framework验配置。php bin/console cache:clear清缓存排错。
九、上线
生产环境:
APP_ENV=prod APP_DEBUG=0 composer install --no-dev --optimize-autoloader
php bin/console cache:clear
文档根指向 public/,用 FrankenPHP / Nginx + PHP-FPM / Docker 都行。Symfony 官方 Docker 镜像和 Platform.sh、SymfonyCloud 一条龙。
十、8.1 顺带提一句:无 HTTP 内核
Symfony 8.1 把 kernel 与 bundle 基础设施抽进了 DependencyInjection 组件,新增 AbstractKernel + KernelTrait——现在 CLI worker、消息消费、数据管道可以完全不依赖 HttpKernel。这意味着"用 Symfony 管理容器生命周期但不处理任何 HTTP 请求"第一次成为一等公民。做长期运行的后台任务或 ETL,这会省掉一层不必要的 HTTP 负担。
下一步
- 官方文档:symfony.com/doc/current
- 组件单独学:先吃透 Routing、DependencyInjection、Console 三个
- MakerBundle 几乎能生成一切样板,熟练后效率不输 Laravel
- 想求稳:把
8.1.*换成7.4.*(LTS),命令完全一致