跳到内容

Flex: 组合你的应用

编辑此页

在阅读了本教程的第一部分之后,您已经决定 Symfony 值得再花 10 分钟了解。非常棒的选择!在第二部分中,您将学习 Symfony Flex:这个神奇的工具让添加新功能就像运行一个命令一样简单。这也是 Symfony 成为小型微服务或大型应用的理想选择的原因。好奇吗?太好了!

Symfony: 启动微型应用!

除非您正在构建纯 API(稍后会详细介绍!),否则您可能需要渲染 HTML。为此,您将使用 Twig。Twig 是一个灵活、快速且安全的 PHP 模板引擎。它使您的模板更具可读性和简洁性;它也使它们对网页设计师更加友好。

我们的应用中是否已经安装了 Twig?实际上,还没有!这太棒了!当您启动一个新的 Symfony 项目时,它是小巧的:只有最关键的依赖项包含在您的 composer.json 文件中

1
2
3
4
5
6
7
"require": {
    "...",
    "symfony/console": "^6.1",
    "symfony/flex": "^2.0",
    "symfony/framework-bundle": "^6.1",
    "symfony/yaml": "^6.1"
}

这使得 Symfony 与任何其他 PHP 框架都不同!Symfony 应用不是从一个臃肿的应用开始,其中包含您可能永远需要的所有可能的功能,而是小巧、简单且快速。您可以完全控制要添加的内容。

Flex Recipes 和别名

那么我们如何安装和配置 Twig 呢?只需运行一个命令

1
$ composer require twig

由于 Symfony Flex,在我们项目的 Composer 插件中,幕后发生了两个非常有趣的事情。

首先,twig 不是 Composer 包的名称:它是一个 Flex 别名,指向 symfony/twig-bundle。Flex 为 Composer 解析该别名。

其次,Flex 为 symfony/twig-bundle 安装了一个 recipe。什么是 recipe?它是一种库通过添加和修改文件来自动配置自身的方式。借助 recipes,添加功能变得无缝且自动化:安装一个包就完成了!

您可以在 recipes 仓库中的 RECIPES.md 中找到 recipes 和别名的完整列表。

这个 recipe 做了什么?除了在 config/bundles.php 中自动启用该功能外,它还添加了 3 个内容

config/packages/twig.yaml
一个配置文件,使用合理的默认值设置 Twig。
config/packages/test/twig.yaml
一个配置文件,在运行测试时更改一些 Twig 选项。
templates/
这是模板文件将存放的目录。该 recipe 还添加了一个 base.html.twig 布局文件。

Twig: 渲染模板

借助 Flex,只需一个命令,您就可以立即开始使用 Twig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
  // src/Controller/DefaultController.php
  namespace App\Controller;

  use Symfony\Component\Routing\Attribute\Route;
  use Symfony\Component\HttpFoundation\Response;
+ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

- class DefaultController
+ class DefaultController extends AbstractController
  {
       #[Route('/hello/{name}', methods: ['GET'])]
       public function index(string $name): Response
       {
-        return new Response("Hello $name!");
+        return $this->render('default/index.html.twig', [
+            'name' => $name,
+        ]);
       }
  }

通过扩展 AbstractController,您现在可以访问许多快捷方法和工具,例如 render()。创建新模板

1
2
{# templates/default/index.html.twig #}
<h1>Hello {{ name }}</h1>

就是这样!{{ name }} 语法将打印从控制器传入的 name 变量。如果您是 Twig 新手,欢迎!您将在稍后了解更多关于其语法和功能的信息。

但是,现在页面包含 h1 标签。为了给它一个 HTML 布局,扩展 base.html.twig

1
2
3
4
5
6
{# templates/default/index.html.twig #}
{% extends 'base.html.twig' %}

{% block body %}
    <h1>Hello {{ name }}</h1>
{% endblock %}

这称为模板继承:我们的页面现在从 base.html.twig 继承 HTML 结构。

Profiler: 调试天堂

Symfony 最的功能之一甚至尚未安装!让我们修复它

1
$ composer require profiler

是的!这是另一个别名!Flex 安装了另一个 recipe,它自动化了 Symfony Profiler 的配置。结果是什么?刷新!

看到底部的黑色工具栏了吗?那是 Web 调试工具栏,它是您新的最佳朋友。通过悬停在每个图标上,您可以获得有关执行了哪些控制器、性能信息、缓存命中和未命中以及更多信息。单击任何图标进入 profiler,您可以在其中获得更详细的调试和性能数据!

哦,当您安装更多库时,您将获得更多工具(例如,显示数据库查询的 Web 调试工具栏图标)。

您现在可以直接使用 profiler,因为它通过 recipe 配置了自身。我们还能安装什么?

丰富的 API 支持

您正在构建 API 吗?您已经可以从任何控制器返回 JSON

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// src/Controller/DefaultController.php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Attribute\Route;

class DefaultController extends AbstractController
{
    // ...

    #[Route('/api/hello/{name}', methods: ['GET'])]
    public function apiHello(string $name): JsonResponse
    {
        return $this->json([
            'name' => $name,
            'symfony' => 'rocks',
        ]);
    }
}

但是为了获得真正丰富的 API,请尝试安装 API Platform

1
$ composer require api

这是 api-platform/api-pack Symfony pack 的别名,它依赖于其他几个包,例如 Symfony 的 Validator 和 Security 组件,以及 Doctrine ORM。实际上,Flex 安装了 5 个 recipes!

但像往常一样,我们可以立即开始使用新库。想要为 product 表创建一个丰富的 API 吗?创建一个 Product 实体并为其赋予 #[ApiResource] 属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// src/Entity/Product.php
namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
#[ApiResource]
class Product
{
    #[ORM\Id]
    #[ORM\GeneratedValue(strategy: 'AUTO')]
    #[ORM\Column(type: 'integer')]
    private int $id;

    #[ORM\Column(type: 'string')]
    private string $name;

    #[ORM\Column(type: 'integer')]
    private int $price;

    // ...
}

完成!您现在拥有列出、添加、更新和删除产品的端点!不相信我?运行以下命令列出您的路由

1
2
3
4
5
6
7
8
9
10
11
12
$ php bin/console debug:router

------------------------------ -------- -------------------------------------
 Name                           Method   Path
------------------------------ -------- -------------------------------------
 api_products_get_collection    GET      /api/products.{_format}
 api_products_post_collection   POST     /api/products.{_format}
 api_products_get_item          GET      /api/products/{id}.{_format}
 api_products_put_item          PUT      /api/products/{id}.{_format}
 api_products_delete_item       DELETE   /api/products/{id}.{_format}
 ...
------------------------------ -------- -------------------------------------

移除 Recipes

还不相信?没问题:移除该库

1
$ composer remove api

Flex 将卸载 recipes:移除文件并撤消更改,使您的应用恢复到原始状态。放心地进行实验。

更多特性、架构和速度

我希望您和我一样对 Flex 感到兴奋!但我们还有一个章节,而且是最重要的章节。我想向您展示 Symfony 如何使您能够快速构建功能,而不会牺牲代码质量或性能。这一切都与服务容器有关,它是 Symfony 的超级力量。继续阅读:关于 架构

这项工作,包括代码示例,根据 Creative Commons BY-SA 3.0 许可协议获得许可。
目录
    版本