# Symfony 服务教程

> 原文： [http://zetcode.com/symfony/service/](http://zetcode.com/symfony/service/)

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

## Symfony

Symfony 是一组可重用的 PHP 组件和一个用于 Web 项目的 PHP 框架。 Symfony 于 2005 年发布为免费软件。Symfony 的原始作者是 Fabien Potencier。 Symfony 受到 Spring 框架的极大启发。

## Symfony 服务

Symfony 应用的功能分为称为服务的较小块。 服务是一个 PHP 对象。 服务位于 Symfony 服务容器中。 有许多内置服务。 可以通过使用类型提示在 Symfony 应用中自动连接服务。

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

```php
# 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 服务示例

在以下示例中，我们从 MySQL 数据库中获取数据。 数据检索委托给特定的应用组件：Symfony 服务。

```php
$ composer create-project symfony/skeleton simpleservice
$ cd simpleservice

```

使用`composer`，我们创建一个新的 Symfony 骨架项目。 然后我们找到新创建的项目目录。

```php
$ composer req annot orm-pack

```

我们安装了三个模块：`annotations`和`orm-pack`。

```php
$ composer req server maker --dev

```

我们安装了开发 Web 服务器和 Symfony `maker`。

`countries_mysql.sql`

```php
CREATE TABLE countries(id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, 
    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);

```

这是一些测试数据。 它在 MySQL 中创建一个小表。 我们可以使用 MySQL `source`命令执行文件。

`config/packages/doctrine.yaml`

```php
... 
doctrine:
    dbal:
        # configure these for your database server
        driver: 'pdo_mysql'
        server_version: '5.7'
        charset: utf8mb4
        default_table_options:
            charset: utf8mb4
            collate: utf8mb4_unicode_ci 
...

```

默认情况下，我们有一个为 Doctrine DBAL 配置的 MySQL 数据库。 教义数据库抽象层（DBAL）是位于 PDO 之上的抽象层，并提供了直观，灵活的 API，可用于与最流行的关系数据库进行通信。

`.env`

```php
...
DATABASE_URL=mysql://user12:s$cret@localhost:3306/mydb

```

在`.env`文件中，我们配置数据库 URL。

```php
$ php bin/console make:controller DataController

```

用`bin/console`创建一个`DataController`。

`src/Controller/DataController.php`

```php
<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use App\Service\DataService;

class DataController extends AbstractController
{
    /**
     * @Route("/data", name="data")
     */
    public function index(DataService $dserv)
    {
        $countries = $dserv->findAll();

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

```

`DataController`以 JSON 格式返回`countries`表中的所有行。 它使用`DataService`服务。

```php
public function index(DataService $dserv)
{

```

通过参数注入创建`DataService`。

> **注意**：为简单起见，我们已将数据库访问代码放置在服务类中。 生产应用中还有另一层：存储库。 数据库访问代码放置在存储库类中，该存储库类从服务类中调用。

`src/Service/DataService.php`

```php
<?php

namespace App\Service;

use Doctrine\DBAL\Driver\Connection;

class DataService 
{
    private $conn;

    public function __construct(Connection $conn) 
    {
        $this->conn = $conn;
    }

    /**
     * Finds all countries
     */
    public function findAll() {

        $queryBuilder = $this->conn->createQueryBuilder();
        $queryBuilder->select('*')->from('countries');

        $data = $queryBuilder->execute()->fetchAll();

        return $data;
    }
}

```

`DataService`包含一种从`countries`表中检索所有行的方法。 它使用 Symfony 的 DBAL 执行查询。

```php
public function __construct(Connection $conn) 
{
    $this->conn = $conn;
}

```

该服务还使用自动装配来创建`Connection`对象。

```php
/**
 * Finds all countries
 */
public function findAll() {

    $queryBuilder = $this->conn->createQueryBuilder();
    $queryBuilder->select('*')->from('countries');

    $data = $queryBuilder->execute()->fetchAll();

    return $data;
}

```

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

```php
$ php bin/console server:run

```

Web 服务器已启动。

```php
$ curl localhost:8000/data
{"data":[{"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 简介](/symfony/intro/)， [Doctrine DBAL `QueryBuilder`教程](/doctrine/querybuilder/)， [Symfony DBAL 教程](/symfony/dbal/)， [Symfony 上传文件教程](/symfony/uploadfile/) ， [Symfony 表单教程](/symfony/form/)， [PHP 教程](/lang/php/)或列出[所有 Symfony 教程](/all/#symfony/)。