Symfony 服务配置 看这一篇就够了
对于刚接触 Symfony 的新手来说,如何配置服务是一件很困难的事情。虽然在 Symfony 的新版本的框架中加入了自动加载(autowire),基本上满足了一般的需求,但是如果你想深入了解“服务”这个概念,并且能够娴熟的使用,就需要能够手动配置完整的工程级别的服务配置。
可惜,对于服务的诸多配置官方文档上的介绍是分功能来描述的,并没有一个列表性质的总结。网上有一些但是也不够全面。
本文总结了大部分的服务配置以及语法,相信能够满足大规模项目中的99%配置需求。
本文没有对 tag,decorates 配置进行介绍,后续的文章会补上,感兴趣的同学可以关注我的博客。
如何阅读本文,
如何阅读本文,
如何阅读本文,
重要的事情说了三遍了,如果你有服务配置的基础,而只是对某个配置不太了解的话,大可以直接从下面的配置中查看(像手册一样)。如果你是新手小白,那么请注意阅读方法:文章分两部分,一部分是服务配置 yaml 格式的文件,后续会补上 xml 以及 PHP 的版本,xml 格式比较严谨(大部分的官方 bundle 采用的都是 xml),而 PHP 代码实现则可以对配置内部如何实现有比较直观清晰的认识。另一部分是服务对应的 PHP 代码,几个简单的类而已。
1 # config/service.yaml 2 3 parameters: 4 email_address: admin@email.com 5 6 services: 7 # 使用 FQCN 的形式定义一个服务名(推荐) 8 App\Services\Email: 9 # 服务实现的类 10 class: App\Services\Email 11 # true 则可以通过 get(\App\Services\Email::class) 方法获取到,false 不可以 12 public: true 13 # 当该服务在多个地方被注入或获取时,返回不同的实例,如果是 true 则返回同一个实例 14 shared: false 15 # 关闭 autowire 16 autowire: false 17 # 这个服务(类)的构造方法需要3个参数,第一个参数引用了一个 parameter,第二个参数是一个固定值,
# 第三个参数引用了一个服务,第四个 18 # 参数是一个可选的服务,存在就引用,不存在就使用服务(类)中的默认值(请查看 App\Services\Email 的构造方法) 19 # %xxx% 表示引用一个 parameters 中定义的变量,@xxx 表示引用一个服务 20 arguments: ["%email_address%", 10, "@app.logger", '@?app.not_exist'] # 等价于下面的设置 21 # arguments: 22 # - "%email_address%" 23 # - 10 24 # - "@app.logger" 25 # - '@?app.not_exist' 26 # 这里需要注意 "" 和 '' 的使用,如果引用的服务名是 FQCN 那么必须使用 '',
# 如果是普通的字符串服务名那么双引单引都可以 27 # 等价于上一行,因为在下面关联了这个接口和服务 28 # arguments: ["%email_address%", 10, '@App\Services\LoggerInterface'] 29 # 这个服务(类)有一个 server 属性,对这个属性进行赋值操作,赋值了一个数组 30 properties: 31 server: 32 smtp: smtp.email.com 33 imap: imap.email.com 34 # 这个服务(类)有一个 setTemplate 方法,该方法有两个参数,服务被注入或获取时,会自动调用该方法 35 calls: 36 - ['setTemplate', ['@app.template', 512]] #等价于下面的设置 37 # - method: setTemplate 38 # arguments: 39 # - '@app.template' 40 # - 512 41 42 App\Services\Logger: 43 class: App\Services\Logger 44 public: true 45 shared: false # 这里的设置没起作用,不知道为什么 46 # 给 App\Services\Logger 服务定义一个别名 47 # 但是不能够通过 get('app.logger') 获取服务,因为没有指定 public,
# 那么在 ResolvePrivatesPass 中就会将 public 设置为 false 48 app.logger: 49 alias: App\Services\Logger 50 51 # 关联接口和服务,任何一个服务如果注入的是参数类型是 App\Services\LoggerInterface,
# 那么都将获取到 App\Services\Logger 这个服务 52 App\Services\LoggerInterface: '@App\Services\Logger' 53 54 # 使用字符串的形式定义一个服务名(不推荐),app.template 中的 "." 没有任何意义,好看而已 55 app.template: 56 class: App\Services\Template 57 # 这个服务(类)的初始化是由 factory 中设置的方法来实现的,也就是说当这个服务被注入或获取时,会静态调用 App\Services\TemplateFactory 58 # 中的 createTemplate 这个方法 59 # 下面的语法只适用于静态方法的创建 60 factory: 61 ['App\Services\TemplateFactory', createTemplate] 62 # 这个静态方法需要一个参数 63 arguments: 64 - 512 65 66 # 如果工厂类需要实例化,那么就必须将其定义为一个服务 67 # App\Services\TemplateFactory: ~ 68 # app.template: 69 # class: App\Services\Template 70 # # 这个 createTemplate 是成员方法,下面的语法只适用于工厂类实例化后调用成员方法的创建 71 # factory: 72 # 'App\Services\TemplateFactory:createTemplate' 73 # arguments: 74 # - 512 75 76 ############################## 自动装载 autowire ############################################################ 77 # 如果当前的 services 下面没有定义 _default(或者 _default 下面定义的 autowire:false) 并且 App\Services\TestAutowire\TestAutowire 78 # 这个服务中也没有定义 autowire,那么默认 autowire 就是 false。autowire:false 意味着如果服务的构造方法中需要参数,则必须手动的在 79 # arguments 字段中明确的设置。 80 # 也就是说所谓的 autowire 就是自动注入构造方法中所需要的参数而无须手动声明。 81 App\Services\TestAutowire\TestAutowire: 82 class: App\Services\TestAutowire\TestAutowire 83 public: true 84 arguments: 85 - '@App\Services\TestAutowire\TestAutowireArg' 86 App\Services\TestAutowire\TestAutowireArg: 87 class: App\Services\TestAutowire\TestAutowireArg 88 89 # 设置了 autowire:true 则无需手动设置构造方法的参数了 90 # App\Services\TestAutowire\TestAutowire: 91 # class: App\Services\TestAutowire\TestAutowire 92 # public: true 93 # autowire: true 94 # App\Services\TestAutowire\TestAutowireArg: 95 # class: App\Services\TestAutowire\TestAutowireArg 96 97 ############################## 父服务与子服务 ############################################################ 98 App\Services\ParentAndChild\ParentService: 99 class: App\Services\ParentAndChild\ParentService 100 public: true 101 abstract: true 102 arguments: 103 $someService1: '@App\Services\ParentAndChild\SomeService1' 104 $someService2: '@App\Services\ParentAndChild\SomeService2' 105 App\Services\ParentAndChild\ChildService: 106 class: App\Services\ParentAndChild\ChildService 107 parent: App\Services\ParentAndChild\ParentService 108 public: true 109 # 波浪线表示 null,容器会使用默认的设置,不能通过 get() 获取,因为默认 public:false 110 App\Services\ParentAndChild\SomeService1: ~ 111 App\Services\ParentAndChild\SomeService2: ~