ZetCode

Symfony 服务

最后修改于 2025 年 3 月 3 日

Symfony 服务教程展示了如何在 Symfony 中创建服务。该服务从数据库中获取数据。

Symfony

Symfony 是一套可重用的 PHP 组件,也是一个用于 Web 项目的 PHP 框架。Symfony 于 2005 年发布为自由软件。Symfony 的最初作者是 Fabien Potencier。Symfony 深受 Spring Framework 的启发。

Symfony 服务

Symfony 应用程序的功能被划分为称为服务的更小的块。服务是 PHP 对象。服务存在于 Symfony 服务容器中。有许多内置服务。可以使用类型提示在 Symfony 应用程序中自动注入服务。

可以使用 php bin/console debug:container 命令生成可用服务的列表。

# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
    resource: '../src/*'
    exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'

这是 services.yaml 配置文件的一部分。src 目录中的 PHP 类可以通过类型提示自动注入到我们的代码中。

Symfony 服务示例

在下面的示例中,我们从 PostgreSQL 数据库中获取数据。数据检索被委托给一个特定的应用程序组件:Symfony 服务。

$ symfony new symservice
$ cd symservice

我们创建一个新的 Symfony 骨架项目,并导航到新创建的项目目录。

$ composer req doctrine orm

我们安装 Doctrine ORM 模块。

$ composer req maker --dev

我们安装 Symfony maker 组件。

countries_postgres.sql
CREATE TABLE countries (id serial PRIMARY KEY, name VARCHAR(100), population INT);

INSERT INTO countries(name, population) VALUES('China', 1382050000);
INSERT INTO countries(name, population) VALUES('India', 1313210000);
INSERT INTO countries(name, population) VALUES('USA', 324666000);
INSERT INTO countries(name, population) VALUES('Indonesia', 260581000);
INSERT INTO countries(name, population) VALUES('Brazil', 207221000);
INSERT INTO countries(name, population) VALUES('Pakistan', 196626000);
INSERT INTO countries(name, population) VALUES('Nigeria', 186988000);
INSERT INTO countries(name, population) VALUES('Bangladesh', 162099000);
INSERT INTO countries(name, population) VALUES('Nigeria', 186988000);
INSERT INTO countries(name, population) VALUES('Russia', 146838000);
INSERT INTO countries(name, population) VALUES('Japan', 126830000);
INSERT INTO countries(name, population) VALUES('Mexico', 122273000);
INSERT INTO countries(name, population) VALUES('Philippines', 103738000);

这是一些测试数据。它在 PostgreSQL 中创建了一个小型表。

config/packages/doctrine.yaml
doctrine:
dbal:
    driver: 'pdo_pgsql'
    server_version: '13'
    charset: 'utf8'
    default_table_options:
        charset: 'utf8'
        collate: 'utf8_unicode_ci'
    url: '%env(resolve:DATABASE_URL)%'

默认情况下,我们为 Doctqrine DBAL 配置了 PostgreSQL 数据库。Doctrine Database Abstraction Layer (DBAL) 是一个建立在 PDO 之上的抽象层,它提供了一个直观且灵活的 API 来与最流行的关系型数据库进行通信。

.env
DATABASE_URL=postgresql://user12:s$cret@localhost:5432/testdb

.env 文件中,我们配置数据库 URL。

$ php bin/console make:controller MyController

使用 bin/console 创建一个 MyController

src/Controller/MyController.php
<?php

namespace App\Controller;

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

class MyController extends AbstractController
{
    #[Route('/countries', name: 'countries')]
    public function index(CountryService $countryService): JsonResponse
    {
        $countries = $countryService->findAll();

        return $this->json([
            'countries' => $countries
        ]);  
    }
}

MyController 以 JSON 格式返回 countries 表的所有行。它使用 CountryService 服务。

public function index(CountryService $countryService): JsonResponse

CountryService 是通过参数注入创建的。

src/Service/CountryService.php
<?php

namespace App\Service;

use App\Repository\CountryRepository;

class CountryService 
{
    public function __construct(
        private readonly CountryRepository $countryRepository
    ) {}

    /**
    * Finds all countries
    */
    public function findAll(): array
    {
        return $this->countryRepository->findAll();
    }
}

CountryService 使用 CountryRepository 来获取数据。

public function __construct(
    private readonly CountryRepository $countryRepository
) {}

我们自动注入 CountryRepository,并从中检索数据。

src/Repository/CountryRepository.php
<?php

namespace App\Repository;

use Doctrine\DBAL\Connection;

class CountryRepository
{
    public function __construct(
        private readonly Connection $conn
    ) {}

    /**
    * Finds all countries
    */
    public function findAll(): array
    {
        $queryBuilder = $this->conn->createQueryBuilder();
        $queryBuilder->select('*')->from('countries');

        return $queryBuilder->executeQuery()->fetchAllAssociative();
    }
}

CountryRepository 包含一个从 countries 表检索所有行的方法。它使用 Symfony 的 DBAL 执行查询。

public function findAll(): array
{
    $queryBuilder = $this->conn->createQueryBuilder();
    $queryBuilder->select('*')->from('countries');

    return $queryBuilder->executeQuery()->fetchAllAssociative();
}

我们使用 DBAL QueryBuilder 从表中获取所有行。Doctrine DBAL QueryBuilder 提供了一个方便、流畅的接口来创建和运行数据库查询。

$ symfony serve

Web 服务器已启动。

$ curl localhost:8000/countries
{"countries":[{"id":"1","name":"China","population":"1382050000"},
{"id":"2","name":"India","population":"1313210000"},
{"id":"3","name":"USA","population":"324666000"},
{"id":"4","name":"Indonesia","population":"260581000"},
{"id":"5","name":"Brazil","population":"207221000"},
{"id":"6","name":"Pakistan","population":"196626000"},
{"id":"7","name":"Nigeria","population":"186988000"},
{"id":"8","name":"Bangladesh","population":"162099000"},
{"id":"9","name":"Nigeria","population":"186988000"},
{"id":"10","name":"Russia","population":"146838000"},
{"id":"11","name":"Japan","population":"126830000"},
{"id":"12","name":"Mexico","population":"122273000"},
{"id":"13","name":"Philippines","population":"103738000"}]}

我们使用 curl 命令创建了一个请求。

在本教程中,我们在 Symfony 中创建了一个简单的服务。该服务从数据库获取数据,并在 Symfony 控制器中自动注入。

列出 所有 Symfony 教程