OptionsResolver组件

编辑本页

警告:您正在浏览的文档欧宝官网下载appob娱乐下载Symfony 5.1,现已不再维护。

本页的更新版本用于Syob娱乐下载mfony 6.2(当前稳定版本)。

OptionsResolver组件

的OptionsResolver组件是改进的array_replacePHP函数。它允许您创建一个包含必需选项、默认值、验证(类型、值)、规范化等的选项系统。

安装

1
作曲家需要symfony/选项解析ob娱乐下载器

请注意

如果在Symfony应用程序外部安装此组件,则必须要求ob娱乐下载供应商/ autoload.php文件,以启用Composer提供的类自动加载机制。读这篇文章欲知详情。

使用

想象一下你有一个梅勒类,它有四个选项:宿主用户名密码而且港口

1 2 3 4 5 6 7 8 9
梅勒受保护的选项公共函数__construct(数组选项= [])->选择=选项;}}

访问选择美元,你需要添加一些样板代码来检查设置了哪些选项:

12 3 4 5 6 7 8 9 10 11 12 13 14 15
梅勒/ /……公共函数sendMail邮件=……;邮件->setHost (->选项(“主机”) ? ?“smtp.example.org”);邮件->setUsername (->选项(“用户名”) ? ?“用户”);邮件->向setPassword (->选项(“密码”) ? ?“爸爸$ $词”);邮件->setPort (->选项(“端口”) ? ?25);/ /……}}

此外,选项的默认值隐藏在代码的业务逻辑中。使用array_replace要解决这个问题:

12 3 4 5 6 7 8 9 10 11 12 13 14
梅勒/ /……公共函数__construct(数组选项= [])->选项= array_replace([“主机”= >“smtp.example.org”“用户名”= >“用户”“密码”= >“爸爸$ $词”“端口”= >25),选项);}}

现在,保证所有四个选项都已设置,但在使用梅勒类:

1 2 3
梅勒梅勒([“usernme”= >“johndoe”// username被错误地拼写成usernme]);

不会显示错误。在最好的情况下,bug会在测试过程中出现,但开发人员会花时间寻找问题。在最坏的情况下,bug可能直到部署到活动系统中才会出现。

幸运的是,OptionsResolver类帮助您解决这个问题:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
使用ob娱乐下载组件OptionsResolverOptionsResolver梅勒/ /……公共函数__construct(数组选项= [])解析器OptionsResolver ();解析器->setDefaults ([“主机”= >“smtp.example.org”“用户名”= >“用户”“密码”= >“爸爸$ $词”“端口”= >25]);->选择=解析器->解决(选项);}}

像以前一样,所有选项都将被保证设置。此外,一个UndefinedOptionsException如果传递了未知选项,则引发:

1 2 3 4 5 6
梅勒梅勒([“usernme”= >“johndoe”]);// UndefinedOptionsException: The option "usernme"不存在。//定义的选项是:"host", "password", "port", "username"

其余的代码可以在没有样板代码的情况下访问选项的值:

12 3 4 5 6 7 8 9 10 11 12 13 14 15
/ /……梅勒/ /……公共函数sendMail邮件=……;邮件->setHost (->选项(“主机”]);邮件->setUsername (->选项(“用户名”]);邮件->向setPassword (->选项(“密码”]);邮件->setPort (->选项(“端口”]);/ /……}}

将选项配置拆分为一个单独的方法是一个很好的实践:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/ /……梅勒/ /……公共函数__construct(数组选项= [])解析器OptionsResolver ();->configureOptions (解析器);->选择=解析器->解决(选项);}公共函数configureOptions(OptionsResolver解析器解析器->setDefaults ([“主机”= >“smtp.example.org”“用户名”= >“用户”“密码”= >“爸爸$ $词”“端口”= >25“加密”= >]);}}

首先,您的代码变得更容易阅读,特别是如果构造函数不仅仅处理选项。其次,子类现在可以重写configureOptions ()调整选项配置的方法:

12 3 4 5 6 7 8 9 10 11 12 13
/ /……GoogleMailer扩展梅勒公共函数configureOptions(OptionsResolver解析器::configureOptions (解析器);解析器->setDefaults ([“主机”= >“smtp.google.com”“加密”= >“ssl”]);}}

需要选择

如果调用方必须设置一个选项,则将该选项传递给setRequired ().例如,使宿主您可以选择:

1 2 3 4 5 6 7 8 9 10 11
/ /……梅勒/ /……公共函数configureOptions(OptionsResolver解析器/ /……解析器->setRequired (“主机”);}}

如果省略了必选选项,则aMissingOptionsException将被抛出:

1 2 3
梅勒梅勒();// MissingOptionsException:缺少必需的选项“host”。

setRequired ()方法接受单个名称或选项名称数组(如果您有多个必选选项):

1 2 3 4 5 6 7 8 9 10 11
/ /……梅勒/ /……公共函数configureOptions(OptionsResolver解析器/ /……解析器->setRequired ([“主机”“用户名”“密码”]);}}

使用isRequired ()以确定是否需要某个选项。你可以使用getRequiredOptions ()检索所有必需选项的名称:

12 3 4 5 6 7 8 9 10 11 12 13 14
/ /……GoogleMailer扩展梅勒公共函数configureOptions(OptionsResolver解析器::configureOptions (解析器);如果解析器->isRequired (“主机”)) {/ /……requiredOptions解析器->getRequiredOptions ();}}

如果要检查默认选项中是否仍然缺少必需的选项,可以使用isMissing ().这和isRequired ()如果已经设置了必需的选项,该方法将返回false:

12 34 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
/ /……梅勒/ /……公共函数configureOptions(OptionsResolver解析器/ /……解析器->setRequired (“主机”);}}/ /……GoogleMailer扩展梅勒公共函数configureOptions(OptionsResolver解析器::configureOptions (解析器);解析器->isRequired (“主机”);// => true解析器->isMissing (“主机”);// => true解析器->setDefault (“主机”“smtp.google.com”);解析器->isRequired (“主机”);// => true解析器->isMissing (“主机”);// => false}}

getMissingOptions ()方法使您可以访问所有缺失选项的名称。

类型验证

您可以对选项运行额外的检查,以确保它们被正确地传递。要验证选项的类型,请调用setAllowedTypes ()

12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20
/ /……梅勒/ /……公共函数configureOptions(OptionsResolver解析器/ /……//指定允许的类型解析器->setAllowedTypes (“主机”“字符串”);//指定多个允许的类型解析器->setAllowedTypes (“端口”, (“零”“int”]);//递归检查数组中类型的所有项解析器->setAllowedTypes (“日期”“DateTime[]”);解析器->setAllowedTypes (“端口”“int[]”);}}

您可以传递任何类型is_类型< > ()函数是用PHP定义的。您还可以传递完全限定的类名或接口名(使用运算符).此外,可以通过为类型加上后缀来递归地验证数组中的所有项[]

如果你现在传递一个无效的选项,一个InvalidOptionsException抛出:

1 2 3 4 5 6
梅勒梅勒([“主机”= >25]);// InvalidOptionsException:值为25的选项“host”是//类型为string,但类型为int

在子类中,您可以使用addAllowedTypes ()添加其他允许的类型,而不删除已设置的类型。

值验证

有些选项只能接受固定的预定义值列表中的一个。例如,假设梅勒类有一个运输选项,可以是其中之一sendmail邮件而且smtp.使用方法setAllowedValues ()验证所传递的选项是否包含以下值之一:

12 3 4 5 6 7 8 9 10 11 12
/ /……梅勒/ /……公共函数configureOptions(OptionsResolver解析器/ /……解析器->setDefault (“交通”“发送邮件”);解析器->setAllowedValues (“交通”, (“发送邮件”“邮件”“smtp”]);}}

如果你通过了一个无效的传输,一个InvalidOptionsException抛出:

1 2 3 4 5 6
梅勒梅勒([“交通”= >“发送邮件”]);// InvalidOptionsException:选项"transport"的值是"send-mail"//无效。可接受的值为:sendmail, mail, smtp

对于具有更复杂验证方案的选项,传递一个返回的闭包真正的对于可接受的值和对于无效值:

1 2 3 4
/ /……解析器->setAllowedValues (“交通”函数价值//返回true或false});

在子类中,您可以使用addAllowedValues ()添加额外的允许值,而不删除已设置的值。

选择归一化

有时,在使用选项值之前,需要对它们进行规范化。例如,假设宿主应该总是以http://.为此,您可以编写规范化程序。标准化器在验证一个选项之后执行。可以通过调用来配置规范化器setNormalizer ()

12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20
使用ob娱乐下载组件OptionsResolver选项/ /……梅勒/ /……公共函数configureOptions(OptionsResolver解析器/ /……解析器->setNormalizer (“主机”函数(选项选项价值如果“http://”! = = substr (价值07)) {价值“http://”价值;}返回价值;});}}

规范化器接收实际值美元的价值并返回规范化的形式。你可以看到闭包也需要选择美元参数。如果你需要在规范化过程中使用其他选项,这是很有用的:

12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20
/ /……梅勒/ /……公共函数configureOptions(OptionsResolver解析器/ /……解析器->setNormalizer (“主机”函数(选项选项价值如果“http://”! = = substr (价值07) & &“https://”! = = substr (价值08)) {如果“ssl”= = =选项“加密”) {价值“https://”价值;}其他的价值“http://”价值;}}返回价值;});}}

要规范化父类中正在规范化的子类中的新允许值,请使用addNormalizer ().这条路,美元的价值参数将接收先前归一化的值,否则您可以在新的归一化器前面通过传入真正的作为第三个论点。

依赖于其他选项的默认值

属性的默认值港口方法的用户所选择的加密梅勒类。更准确地说,您希望将端口设置为465如果使用SSL和25否则。

类的默认值传递闭包来实现此特性港口选择。闭包接收选项作为参数。基于这些选项,您可以返回所需的默认值:

12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20
使用ob娱乐下载组件OptionsResolver选项/ /……梅勒/ /……公共函数configureOptions(OptionsResolver解析器/ /……解析器->setDefault (“加密”);解析器->setDefault (“端口”函数(选项选项如果“ssl”= = =选项“加密”) {返回465;}返回25;});}}

谨慎

可调用对象的实参必须是类型提示为选项.否则,可调用对象本身被视为该选项的默认值。

请注意

对象时才执行闭包港口选项不是由用户设置,也不是在子类中覆盖。

之前设置的默认值可以通过在闭包中添加第二个参数来访问:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/ /……梅勒/ /……公共函数configureOptions(OptionsResolver解析器/ /……解析器->setDefaults ([“加密”= >“主机”= >“example.org”]);}}GoogleMailer扩展梅勒公共函数configureOptions(OptionsResolver解析器::configureOptions (解析器);解析器->setDefault (“主机”函数(选项选项previousValue如果“ssl”= = =选项“加密”) {返回“secure.example.org”//获取基类中配置的默认值返回previousValue;});}}

如示例所示,如果您想在子类中重用父类中设置的默认值,则此特性非常有用。

没有默认值的选项

在某些情况下,定义一个选项而不设置默认值是有用的。如果您需要知道用户是否实际上是否设置一个选项。例如,如果你为一个选项设置了默认值,不可能知道用户是否传递了这个值,或者它是否来自默认值:

12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20
/ /……梅勒/ /……公共函数configureOptions(OptionsResolver解析器/ /……解析器->setDefault (“端口”25);}/ /……公共函数sendMail//这是默认值还是类的调用者真的//设置端口为25?如果25= = =->选项(“端口”) {/ /……}}}

你可以使用setDefined ()定义一个选项而不设置默认值。然后,只有在实际传递给时,该选项才会包含在已解析的选项中解决()

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/ /……梅勒/ /……公共函数configureOptions(OptionsResolver解析器/ /……解析器->setDefined (“端口”);}/ /……公共函数sendMail如果(array_key_exists (“端口”->选项)){回声“集合!”;}其他的回声“没有!”;}}}梅勒梅勒();梅勒->sendMail ();// =>未设置!梅勒梅勒([“端口”= >25]);梅勒->sendMail ();// =>设置!

如果你想一次性定义多个选项,你也可以传递一个选项名称数组:

1 2 3 4 5 6 7 8 9 10
/ /……梅勒/ /……公共函数configureOptions(OptionsResolver解析器/ /……解析器->setDefined ([“端口”“加密”]);}}

的方法isDefined ()而且getDefinedOptions ()让您了解定义了哪些选项:

12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20
/ /……GoogleMailer扩展梅勒/ /……公共函数configureOptions(OptionsResolver解析器::configureOptions (解析器);如果解析器->isDefined (“主机”)) {//下面的一个被调用:// $resolver->setDefault('host',…);/ /解析器- > setRequired('主机');/ /解析器- > setDefined('主机');definedOptions解析器->getDefinedOptions ();}}

嵌套的选择

假设您有一个名为线轴哪个有两个子选项类型而且路径.属性的默认值传递闭包,而不是将其定义为简单的值数组线轴选项。OptionsResolver论点。基于此实例,您可以定义下面的选项线轴及其期望的默认值:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
梅勒/ /……公共函数configureOptions(OptionsResolver解析器解析器->setDefault (“轴”函数(OptionsResolverspoolResolverspoolResolver->setDefaults ([“类型”= >“文件”“路径”= >“/ spool /道路/”]);spoolResolver->setAllowedValues (“类型”, (“文件”“记忆”]);spoolResolver->setAllowedTypes (“路径”“字符串”);});}公共函数sendMail如果“记忆”= = =->选项(“轴”] [“类型”) {/ /……}}}梅勒梅勒([“轴”= > [“类型”= >“记忆”,],]);

嵌套选项还支持所需的选项、验证(类型、值)和其值的规范化。如果嵌套选项的默认值依赖于父级中定义的另一个选项,请添加第二个选项参数来访问它们:

12 3 4 5 6 7 8 9 10 11 12 13 14 15
梅勒/ /……公共函数configureOptions(OptionsResolver解析器解析器->setDefault (“沙盒”);解析器->setDefault (“轴”函数(OptionsResolverspoolResolver、期权spoolResolver->setDefaults ([“类型”= >“沙盒”] ?“记忆”“文件”/ /……]);});}}

谨慎

闭包的参数必须是类型提示为OptionsResolver而且选项分别。否则,闭包本身被视为该选项的默认值。

以同样的方式,父选项可以像普通数组一样访问嵌套选项:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
梅勒/ /……公共函数configureOptions(OptionsResolver解析器解析器->setDefault (“轴”函数(OptionsResolverspoolResolverspoolResolver->setDefaults ([“类型”= >“文件”/ /……]);});解析器->setDefault (“分析”函数(选项选项返回“文件”= = =选项“轴”] [“类型”];});}}

请注意

一个选项被定义为嵌套的事实意味着您必须在运行时传递一个值数组来解析它。

弃用选项

5.1

签署setDeprecated ()方法从setDeprecated(string $option, ?string $message)setDeprecated(字符串$option,字符串$package,字符串$version, $message)在Syob娱乐下载mfony 5.1。

选项过时或决定不再维护时,可以使用setDeprecated ()方法:

12 3 4 5 6 7 8 9 10 11 12 13 14 15
解析器->setDefined ([的主机名“主机”])//输出以下通用弃用消息://由于acme/package 1.2:选项“hostname”已弃用。->setDeprecated (的主机名“acme /包”“1.2”//你也可以传递一个自定义的弃用消息(%name%占位符可用)->setDeprecated (的主机名“acme /包”“1.2”“不推荐使用‘hostname’选项,改用‘host’。”);

请注意

只有在某个地方使用了该选项,或者该选项的值由用户提供,或者该选项在惰性选项和正常化器的闭包中计算时,才会触发弃用消息。

请注意

当您在自己的库中使用已弃用的选项时,可以通过的第二个参数offsetGet ()方法以不触发弃用警告。

除了传递消息,你还可以传递一个闭包,它返回一个字符串(弃用消息)或一个空字符串来忽略弃用。这个闭包只适用于弃用某些允许的类型或值:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
解析器->setDefault (“加密”->setDefault (“端口”->setAllowedTypes (“端口”, (“零”“int”])->setDeprecated (“端口”“acme /包”“1.2”函数(选项选项价值如果= = =价值) {返回“向选项“端口”传递“null”已弃用,而是传递一个整数。”;}// deprecation也可能依赖于另一个选项如果“ssl”= = =选项“加密”) & &456= = !价值) {返回“当“加密”选项设置为“ssl”时,不建议使用与“456”不同的端口。”;}返回;});

请注意

只有当用户提供该选项时,才会触发基于该值的弃用。

这个闭包在对选项进行验证之后,在解析选项时对其进行规范化之前,接收选项的值作为参数。

链接选项配置

在许多情况下,您可能需要为每个选项定义多个配置。例如,假设InvoiceMailer类有一个宿主选项运输选项,可以是其中之一sendmail邮件而且smtp.属性可以提高代码的可读性,避免重复每个配置的选项名称定义()方法:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/ /……InvoiceMailer/ /……公共函数configureOptions(OptionsResolver解析器/ /……解析器->定义(“主机”->要求()->默认的“smtp.example.org”->allowedTypes (“字符串”->信息(IP地址或主机名);解析器->定义(“交通”->要求()->默认的“交通”->allowedValues ([“发送邮件”“邮件”“smtp”]);}}

5.1

定义()而且信息()方法是在Symfony 5.1中引入的。ob娱乐下载

性能调整

对于当前的实现,configureOptions ()方法的每个实例都将调用梅勒类。根据选项配置的数量和创建实例的数量,这可能会给应用程序增加明显的开销。如果这个开销成为一个问题,你可以改变你的代码,每个类只做一次配置:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/ /……梅勒私人静态resolversByClass= [];受保护的选项公共函数__construct(数组选项= [])//这是什么类型的Mailer, Mailer, GoogleMailer,…吗?= get_class ();// configureOptions()在这个类之前执行了吗?如果(!收取自我:: $resolversByClass [))) {自我:: $resolversByClass [] =OptionsResolver ();->configureOptions (自我:: $resolversByClass []);}->选择=自我:: $resolversByClass [->解决(选项);}公共函数configureOptions(OptionsResolver解析器/ /……}}

现在,OptionsResolver实例将在每个类中创建一次,并从那时开始重用。注意,如果默认选项包含对对象或对象图的引用,这可能会导致长时间运行的应用程序发生内存泄漏。如果是这样的话,实现一个方法clearOptionsConfig ()并定期调用它:

12 3 4 5 6 7 8 9 10 11 12
/ /……梅勒私人静态resolversByClass= [];公共静态函数clearOptionsConfig()自我:: $resolversByClass = [];}/ /……

就是这样!现在您已经拥有了处理代码中的选项所需的所有工具和知识。

此工作,包括代码示例,是根据创作共用BY-SA 3.0许可证。