Symfony
Symfony 是一个成熟、模块化的 PHP 框架,由 SensioLabs(现 Symfony SAS)开发维护。它不仅是众多 PHP 框架的底层基础(包括 Laravel),也是一个可以直接使用的全栈框架。Symfony 的组件化设计使得开发者可以选择单独使用任何 Symfony 组件,而无需引入整个框架。本节将全面介绍 Symfony 框架的核心概念和使用方法。
基础概念
Symfony 的特点
| 特性 | 说明 |
|---|---|
| 组件化 | 40+ 可独立使用的组件 |
| 灵活性 | 不强制使用特定组件 |
| 企业级 | 长期支持版本(LTS) |
| 性能 | 高度优化,支持 HTTP/2 和 HTTP/3 |
| 社区 | 大型活跃社区 |
| 文档 | 业界最佳文档之一 |
| 测试 | 完善的测试工具链 |
| 标准化 | PHP-FIG 规范的主要推动者 |
版本对应关系
| Symfony | PHP 最低版本 | 支持状态 |
|---|---|---|
| Symfony 7 | PHP 8.2 | 当前版本 |
| Symfony 6.4 | PHP 8.1 | LTS(长期支持) |
| Symfony 5.4 | PHP 8.0 | 维护中 |
详细说明
项目创建
bash
# 方式一:创建完整 Web 应用
composer create-project symfony/website-skeleton myapp
# 方式二:创建微服务(推荐 API 项目)
composer create-project symfony/skeleton myapp
# 方式三:使用 Symfony CLI
symfony new myapp --full # 完整版
symfony new myapp --webapp # Web 应用
symfony new myapp # 微服务目录结构
symfony-project/
├── config/ # 配置文件(YAML)
│ ├── packages/
│ ├── routes/
│ └── services.yaml
├── src/ # PHP 源代码
│ ├── Controller/
│ ├── Entity/
│ ├── Repository/
│ ├── Service/
│ └── Kernel.php
├── templates/ # Twig 模板
├── public/ # Web 根目录
│ └── index.php
├── bin/ # CLI 命令
│ └── console
├── migrations/ # Doctrine 迁移
├── tests/ # 测试文件
└── composer.json路由与控制器
php
<?php
// src/Controller/UserController.php
declare(strict_types=1);
namespace App\Controller;
use App\Entity\User;
use App\Repository\UserRepository;
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;
class UserController extends AbstractController
{
#[Route('/api/users', methods: ['GET'])]
public function index(UserRepository $repository): JsonResponse
{
$users = $repository->findAll();
return $this->json([
'data' => $users,
]);
}
#[Route('/api/users/{id}', methods: ['GET'])]
public function show(int $id, UserRepository $repository): JsonResponse
{
$user = $repository->find($id);
if ($user === null) {
throw $this->createNotFoundException('User not found');
}
return $this->json($user);
}
#[Route('/api/users', methods: ['POST'])]
public function store(
Request $request,
EntityManagerInterface $em
): JsonResponse {
$data = json_decode($request->getContent(), true);
$user = new User();
$user->setName($data['name'] ?? '');
$user->setEmail($data['email'] ?? '');
$em->persist($user);
$em->flush();
return $this->json($user, 201);
}
}服务容器与依赖注入
yaml
# config/services.yaml
services:
_defaults:
autowire: true
autoconfigure: true
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
App\Controller\:
resource: '../src/Controller/'
tags: ['controller.service_arguments']php
<?php
declare(strict_types=1);
namespace App\Service;
use Psr\Log\LoggerInterface;
use App\Repository\UserRepository;
class UserService
{
// 自动注入(通过 autowire)
public function __construct(
private readonly UserRepository $userRepository,
private readonly LoggerInterface $logger
) {}
public function findActiveUsers(): array
{
$this->logger->info('Finding active users');
return $this->userRepository->findBy(['isActive' => true]);
}
}Doctrine ORM
php
<?php
declare(strict_types=1);
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
#[ORM\Table(name: 'users')]
class User
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private ?int $id = null;
#[ORM\Column(length: 255)]
private string $name = '';
#[ORM\Column(length: 255, unique: true)]
private string $email = '';
#[ORM\Column]
private bool $isActive = true;
#[ORM\Column]
private ?\DateTimeImmutable $createdAt = null;
// Getter 和 Setter
public function getId(): ?int
{
return $this->id;
}
public function getName(): string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getEmail(): string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function isActive(): bool
{
return $this->isActive;
}
}Symfony 控制台命令
bash
# 常用 Symfony 命令
php bin/console server:run # 启动开发服务器
php bin/console make:controller # 创建控制器
php bin/console make:entity # 创建 Doctrine 实体
php bin/console make:migration # 创建迁移
php bin/console doctrine:migrations:migrate # 运行迁移
php bin/console debug:router # 调试路由
php bin/console cache:clear # 清除缓存
php bin/console lint:container # 检查服务容器Twig 模板引擎
html
{# templates/user/index.html.twig #}
{% extends 'base.html.twig' %}
{% block title %}User List{% endblock %}
{% block body %}
<h1>Users</h1>
<table>
{% for user in users %}
<tr>
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.email }}</td>
<td>{{ user.isActive ? 'Active' : 'Inactive' }}</td>
</tr>
{% else %}
<tr><td colspan="4">No users found.</td></tr>
{% endfor %}
</table>
{{ paginate(users) }}
{% endblock %}验证器
php
<?php
// src/Entity/User.php
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity]
class User
{
#[Assert\NotBlank]
#[Assert\Length(min: 2, max: 255)]
#[ORM\Column(length: 255)]
private string $name = '';
#[Assert\NotBlank]
#[Assert\Email]
#[Assert\Length(max: 255)]
#[ORM\Column(length: 255)]
private string $email = '';
#[Assert\NotBlank]
#[Assert\Length(min: 8)]
#[ORM\Column]
private string $password = '';
}php
<?php
// 在控制器中使用验证
use Symfony\Component\Validator\Validator\ValidatorInterface;
public function store(Request $request, ValidatorInterface $validator): JsonResponse
{
$user = new User();
$user->setName($request->get('name'));
$user->setEmail($request->get('email'));
$errors = $validator->validate($user);
if (count($errors) > 0) {
$errorMessages = [];
foreach ($errors as $error) {
$errorMessages[$error->getPropertyPath()] = $error->getMessage();
}
return $this->json(['errors' => $errorMessages], 422);
}
$em->persist($user);
$em->flush();
return $this->json($user, 201);
}表单组件
php
<?php
// src/Form/UserType.php
namespace App\Form;
use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', TextType::class, [
'label' => 'Name',
'constraints' => [
new Assert\NotBlank(),
new Assert\Length(['min' => 2, 'max' => 255]),
],
])
->add('email', EmailType::class)
->add('password', PasswordType::class);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
}实战示例
场景一:独立使用 Symfony 组件
bash
# 不使用框架,仅使用 Symfony 组件
composer require symfony/http-foundation
composer require symfony/routing
composer require symfony/console
composer require symfony/var-dumperphp
<?php
declare(strict_types=1);
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Matcher\UrlMatcher;
// 使用 HttpFoundation 组件
$request = Request::createFromGlobals();
$name = $request->query->get('name', 'World');
$response = new Response("Hello, {$name}!", 200, [
'Content-Type' => 'text/plain',
]);
$response->send();场景二:配置 Symfony 安全
yaml
# config/packages/security.yaml
security:
enable_authenticator_manager: true
providers:
app_users:
entity:
class: App\Entity\User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt))/
security: false
main:
lazy: true
provider: app_users
json_login:
check_path: /api/login
username_path: email
password_path: password
access_control:
- { path: ^/api/login, roles: PUBLIC_ACCESS }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }注意事项
1. 环境变量
bash
# .env 文件
APP_ENV=dev
APP_SECRET=your-secret-key
DATABASE_URL=mysql://root:password@127.0.0.1:3306/myapp2. 缓存管理
bash
# 开发环境:自动更新缓存
# 生产环境:手动管理缓存
php bin/console cache:clear # 清除所有缓存
php bin/console cache:warmup # 预热缓存
php bin/console cache:pool:clear # 清除指定缓存池最佳实践
1. 使用 Flex 管理依赖
bash
# Symfony Flex 自动配置包
composer require symfony/twig-bundle # 自动配置 Twig
composer require symfony/mailer # 自动配置 Mailer
composer require symfony/validator # 自动配置 ValidatorSymfony vs Laravel
- Symfony:更灵活、更底层、更适合大型企业项目
- Laravel:更易上手、更优雅的语法、更快的开发速度
- 两者可以互补:Laravel 使用了多个 Symfony 组件
下一节
继续学习:ThinkPHP 框架 — 了解国内最流行的 PHP 框架。