服务基础 #

一、服务容器概述 #

1.1 什么是服务 #

服务是执行特定任务的PHP对象,例如发送邮件、处理数据库操作等。

text
┌─────────────────────────────────────────────────────┐
│                  服务容器作用                        │
├─────────────────────────────────────────────────────┤
│  • 管理服务生命周期                                  │
│  • 自动依赖注入                                      │
│  • 服务配置和参数化                                  │
│  • 延迟加载                                          │
│  • 服务标签                                          │
└─────────────────────────────────────────────────────┘

1.2 服务容器结构 #

text
服务容器
├── 服务定义
│   ├── 类名
│   ├── 参数
│   └── 标签
├── 参数
│   ├── 字符串
│   ├── 数字
│   └── 数组
└── 别名

二、创建服务 #

2.1 创建服务类 #

php
<?php

namespace App\Service;

use App\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;

class UserService
{
    public function __construct(
        private EntityManagerInterface $entityManager,
        private UserRepository $userRepository
    ) {}

    public function getAllUsers(): array
    {
        return $this->userRepository->findAll();
    }

    public function getUserById(int $id): ?User
    {
        return $this->userRepository->find($id);
    }

    public function createUser(array $data): User
    {
        $user = new User();
        $user->setName($data['name']);
        $user->setEmail($data['email']);

        $this->entityManager->persist($user);
        $this->entityManager->flush();

        return $user;
    }
}

2.2 自动装配 #

Symfony默认启用自动装配,服务会自动注册:

yaml
# config/services.yaml
services:
    _defaults:
        autowire: true
        autoconfigure: true

    App\:
        resource: '../src/'
        exclude:
            - '../src/DependencyInjection/'
            - '../src/Entity/'
            - '../src/Kernel.php'

2.3 使用服务 #

php
<?php

namespace App\Controller;

use App\Service\UserService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class UserController extends AbstractController
{
    public function list(UserService $userService)
    {
        $users = $userService->getAllUsers();
        
        return $this->render('user/list.html.twig', [
            'users' => $users,
        ]);
    }
}

三、服务配置 #

3.1 YAML配置 #

yaml
# config/services.yaml
services:
    App\Service\UserService:
        arguments:
            $userRepository: '@App\Repository\UserRepository'
        calls:
            - method: setLogger
              arguments:
                  - '@logger'
        tags:
            - { name: 'app.service' }

    App\Service\EmailService:
        arguments:
            $mailer: '@mailer.mailer'
            $fromEmail: '%env(MAILER_FROM_EMAIL)%'

3.2 PHP属性配置 #

php
<?php

namespace App\Service;

use Psr\Log\LoggerInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Contracts\Service\Attribute\Required;

class EmailService
{
    private MailerInterface $mailer;
    private LoggerInterface $logger;
    private string $fromEmail;

    public function __construct(
        MailerInterface $mailer,
        string $fromEmail
    ) {
        $this->mailer = $mailer;
        $this->fromEmail = $fromEmail;
    }

    #[Required]
    public function setLogger(LoggerInterface $logger): void
    {
        $this->logger = $logger;
    }
}

3.3 服务别名 #

yaml
# config/services.yaml
services:
    App\Service\UserServiceInterface: '@App\Service\UserService'
    
    app.user_service:
        alias: App\Service\UserService
        public: true

四、服务参数 #

4.1 定义参数 #

yaml
# config/services.yaml
parameters:
    app.site_name: 'My Symfony App'
    app.items_per_page: 20
    app.supported_locales: ['en', 'zh', 'ja']

services:
    App\Service\ConfigService:
        arguments:
            $siteName: '%app.site_name%'
            $itemsPerPage: '%app.items_per_page%'
            $supportedLocales: '%app.supported_locales%'

4.2 环境变量参数 #

yaml
# config/services.yaml
services:
    App\Service\ApiService:
        arguments:
            $apiKey: '%env(API_KEY)%'
            $apiUrl: '%env(API_URL)%'
            $debug: '%env(bool:APP_DEBUG)%'
            $timeout: '%env(int:API_TIMEOUT)%'

4.3 在服务中使用参数 #

php
<?php

namespace App\Service;

class ConfigService
{
    public function __construct(
        private string $siteName,
        private int $itemsPerPage,
        private array $supportedLocales
    ) {}

    public function getSiteName(): string
    {
        return $this->siteName;
    }

    public function getItemsPerPage(): int
    {
        return $this->itemsPerPage;
    }

    public function getSupportedLocales(): array
    {
        return $this->supportedLocales;
    }
}

五、服务作用域 #

5.1 单例服务(默认) #

yaml
# config/services.yaml
services:
    App\Service\UserService:
        shared: true  # 默认值

5.2 非共享服务 #

yaml
# config/services.yaml
services:
    App\Service\TempService:
        shared: false

5.3 原型服务 #

yaml
# config/services.yaml
services:
    App\Service\PrototypeService:
        shared: false

六、服务标签 #

6.1 定义标签 #

yaml
# config/services.yaml
services:
    App\Handler\FirstHandler:
        tags:
            - { name: 'app.handler', priority: 10 }

    App\Handler\SecondHandler:
        tags:
            - { name: 'app.handler', priority: 5 }

6.2 收集标签服务 #

php
<?php

namespace App\Service;

use Symfony\Component\DependencyInjection\Attribute\TaggedIterator;

class HandlerService
{
    public function __construct(
        #[TaggedIterator('app.handler')]
        private iterable $handlers
    ) {}

    public function process(): void
    {
        foreach ($this->handlers as $handler) {
            $handler->handle();
        }
    }
}

6.3 常用标签 #

标签 说明
controller.service_arguments 控制器服务参数
twig.extension Twig扩展
form.type 表单类型
validator.constraint_validator 验证器
kernel.event_subscriber 事件订阅者

七、服务工厂 #

7.1 工厂服务 #

php
<?php

namespace App\Factory;

use App\Service\ApiClient;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class ApiClientFactory
{
    public static function create(HttpClientInterface $httpClient, string $baseUrl): ApiClient
    {
        return new ApiClient($httpClient, $baseUrl);
    }
}

7.2 配置工厂 #

yaml
# config/services.yaml
services:
    App\Service\ApiClient:
        factory: [App\Factory\ApiClientFactory, 'create']
        arguments:
            - '@http_client'
            - '%env(API_BASE_URL)%'

八、服务装饰 #

8.1 装饰器模式 #

php
<?php

namespace App\Decorator;

use App\Service\LoggerInterface;
use App\Service\FileLogger;

class JsonLoggerDecorator implements LoggerInterface
{
    public function __construct(
        private LoggerInterface $decorated
    ) {}

    public function log(string $message): void
    {
        $jsonMessage = json_encode([
            'message' => $message,
            'timestamp' => time(),
        ]);
        
        $this->decorated->log($jsonMessage);
    }
}

8.2 配置装饰器 #

yaml
# config/services.yaml
services:
    App\Service\LoggerInterface: '@App\Service\FileLogger'
    
    App\Service\FileLogger:
        class: App\Service\FileLogger
    
    App\Decorator\JsonLoggerDecorator:
        decorates: App\Service\FileLogger
        arguments: ['@App\Decorator\JsonLoggerDecorator.inner']

九、服务调试 #

9.1 查看服务 #

bash
# 查看所有服务
php bin/console debug:container

# 查看特定服务
php bin/console debug:container App\Service\UserService

# 查看自动装配
php bin/console debug:autowiring

# 查看服务标签
php bin/console debug:container --tag=twig.extension

9.2 服务信息 #

bash
php bin/console debug:container App\Service\UserService

# 输出示例
+---------------+---------------------------------------------------------+
| Option        | Value                                                   |
+---------------+---------------------------------------------------------+
| Service ID    | App\Service\UserService                                 |
| Class         | App\Service\UserService                                 |
| Tags          | app.service                                             |
| Public        | no                                                      |
| Synthetic     | no                                                      |
| Lazy          | no                                                      |
| Shared        | yes                                                     |
| Abstract      | no                                                      |
| Autowired     | yes                                                     |
| Autoconfigured| yes                                                     |
+---------------+---------------------------------------------------------+

十、最佳实践 #

10.1 服务设计原则 #

text
服务设计原则:
├── 单一职责:每个服务只做一件事
├── 接口编程:面向接口而非实现
├── 依赖注入:避免在服务中使用new
├── 避免服务定位器:使用依赖注入
├── 合理使用标签:组织相关服务
└── 配置外部化:使用参数和环境变量

10.2 命名规范 #

text
服务命名规范:
├── 类名:{Name}Service
├── 接口:{Name}Interface
├── 工厂:{Name}Factory
├── 装饰器:{Name}Decorator
└── 订阅者:{Name}Subscriber

十一、总结 #

本章学习了:

  • 服务容器概述
  • 创建和使用服务
  • 服务配置方式
  • 服务参数
  • 服务作用域
  • 服务标签
  • 服务工厂
  • 服务装饰器
  • 服务调试

下一章将学习 依赖注入

最后更新:2026-03-28