OptionsResolver组件
编辑该页面警告:你浏览的文档欧宝官网下载appob娱乐下载Symfony 3.4,不再维护。
读这个页面的更新版本Symfob娱乐下载ony 6.3(当前的稳定版本)。
OptionsResolver组件
OptionsResolver组件是一种改进的替代array_replacePHP函数。它允许您创建一个选项系统所需的选项,默认值,验证(类型、价值)、标准化和更多。
安装
1
美元作曲家需要symfony / opob娱乐下载tions-resolver: ^ 3.4
请注意
如果你安装这个组件之外的Symfony应用程序,你必须要求ob娱乐下载供应商/ autoload.php
文件在你的代码,使作曲家提供的类加载机制。读这篇文章为更多的细节。
使用
想象你有一个梅勒
类有四个选项:主机
,用户名
,密码
和港口
:
1 2 3 4 5 6 7 8 9
类梅勒{受保护的美元选项;公共函数__construct(数组美元选项= []){美元这- >选择=美元选项;}}
当访问选择美元
,您需要添加许多样板代码检查哪些选项设置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21日22日23日24日25日26日
类梅勒{/ /……公共函数sendMail(美元从,美元来){美元邮件=……;美元邮件- >setHost (收取(美元这- >选项(“主机”])?美元这- >选项(“主机”]:“smtp.example.org”);美元邮件- >setUsername (收取(美元这- >选项(“用户名”])?美元这- >选项(“用户名”]:“用户”);美元邮件- >向setPassword (收取(美元这- >选项(“密码”])?美元这- >选项(“密码”]:“爸爸$ $词”);美元邮件- >setPort (收取(美元这- >选项(“端口”])?美元这- >选项(“端口”]:25);/ /……}}
这个样板是难以阅读和重复。选项的默认值也埋在代码的业务逻辑。使用array_replace修复:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
类梅勒{/ /……公共函数__construct(数组美元选项= []){美元这- >选择= array_replace ([“主机”= >“smtp.example.org”,“用户名”= >“用户”,“密码”= >“爸爸$ $词”,“端口”= >25),美元选项);}}
现在所有四个选项是有保证的,但是你仍然可以使一个错误当使用如下梅勒
类:
1 2 3
美元梅勒=新梅勒([“usernme”= >“johndoe”,/ /用户名是错误的拼写是“usernme”]);
没有显示错误信息。在最好的情况下,错误在测试过程中会出现,但开发者会花时间找问题。在最坏的情况下,不可能出现错误直到部署到活动的系统。
幸运的是,OptionsResolver类可以帮助您解决这个问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
使用ob娱乐下载\组件\OptionsResolver\OptionsResolver;类梅勒{/ /……公共函数__construct(数组美元选项= []){美元解析器=新OptionsResolver ();美元解析器- >setDefaults ([“主机”= >“smtp.example.org”,“用户名”= >“用户”,“密码”= >“爸爸$ $词”,“端口”= >25]);美元这- >选择=美元解析器- >解决(美元选项);}}
像以前一样,所有选项都将保证集。此外,一个UndefinedOptionsException如果抛出一个未知的选择是通过:
1 2 3 4 5 6
美元梅勒=新梅勒([“usernme”= >“johndoe”]);/ / UndefinedOptionsException:选择“usernme”并不存在。/ /定义的选项:“主机”、“密码”、“港”、“用户名”
剩下的代码可以访问选项的值没有样板代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/ /……类梅勒{/ /……公共函数sendMail(美元从,美元来){美元邮件=……;美元邮件- >setHost (美元这- >选项(“主机”]);美元邮件- >setUsername (美元这- >选项(“用户名”]);美元邮件- >向setPassword (美元这- >选项(“密码”]);美元邮件- >setPort (美元这- >选项(“端口”]);/ /……}}
这是一个很好的实践将选择配置到一个单独的方法:
1 2 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 ()
调整方法的配置选项:
1 2 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 (“主机”);}}
如果您省略一个必需的选项,一个MissingOptionsException将被扔:
1 2 3
美元梅勒=新梅勒();/ / MissingOptionsException:所需的选项“主机”不见了。
的setRequired ()方法接受一个名称或一组选项名称,如果你有不止一个需要选择:
1 2 3 4 5 6 7 8 9 10 11
/ /……类梅勒{/ /……公共函数configureOptions(OptionsResolver美元解析器){/ /……美元解析器- >setRequired ([“主机”,“用户名”,“密码”]);}}
使用isRequired ()发现如果一个选项是必需的。您可以使用getRequiredOptions ()来检索所需的所有选项的名称:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/ /……类GoogleMailer扩展梅勒{公共函数configureOptions(OptionsResolver美元解析器){父::configureOptions (美元解析器);如果(美元解析器- >isRequired (“主机”)){/ /……}美元requiredOptions=美元解析器- >getRequiredOptions ();}}
如果你想要检查是否需要选择是失踪从默认选项,您可以使用isMissing ()。这之间的区别isRequired ()是,这个方法将返回false如果需要选择已经设置:
1 2 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 32 33 34
/ /……类梅勒{/ /……公共函数configureOptions(OptionsResolver美元解析器){/ /……美元解析器- >setRequired (“主机”);}}/ /……类GoogleMailer扩展梅勒{公共函数configureOptions(OptionsResolver美元解析器){父::configureOptions (美元解析器);美元解析器- >isRequired (“主机”);/ / = >正确的美元解析器- >isMissing (“主机”);/ / = >正确的美元解析器- >setDefault (“主机”,“smtp.google.com”);美元解析器- >isRequired (“主机”);/ / = >正确的美元解析器- >isMissing (“主机”);/ / = >假}}
的getMissingOptions ()方法允许您访问所有失踪的名称选项。
类型验证
选项您可以运行额外的检查,以确保他们正确传递。验证的类型选择,电话setAllowedTypes ():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/ /……类梅勒{/ /……公共函数configureOptions(OptionsResolver美元解析器){/ /……/ /允许指定一个类型美元解析器- >setAllowedTypes (“主机”,“字符串”);/ /允许指定多个类型美元解析器- >setAllowedTypes (“端口”,(“零”,“int”]);/ /检查所有物品在递归数组类型美元解析器- >setAllowedTypes (“日期”,“DateTime []”);美元解析器- >setAllowedTypes (“端口”,“int []”);}}
你可以传递任何类型的一个is_ <类型> ()
PHP函数中定义。你也可以通过完全限定的类或接口的名字(这是检查使用运算符
)。此外,您可以递归地验证数组中所有项目通过向与类型[]
。
3.4
验证类型的数组项递归地是在Symfony 3.4中引入的。ob娱乐下载Symfony 3ob娱乐下载.4之前,只有标量值可以验证。
如果你现在通过一个无效的选项,一个InvalidOptionsException抛出:
1 2 3 4 5 6
美元梅勒=新梅勒([“主机”= >25]);/ / InvalidOptionsException:选择“主机”与“25”是价值/ /将类型的“字符串”,但“int”类型的
在子类中,您可以使用addAllowedTypes ()添加额外的允许没有删除已经设置的类型。
值验证
一些选项只能取一个固定的预定义的值列表。例如,假设梅勒
类都有一个运输
选项之一sendmail
,邮件
和smtp
。使用这种方法setAllowedValues ()验证通过选择包含这些值之一:
1 2 3 4 5 6 7 8 9 10 11 12
/ /……类梅勒{/ /……公共函数configureOptions(OptionsResolver美元解析器){/ /……美元解析器- >setDefault (“交通”,“发送邮件”);美元解析器- >setAllowedValues (“交通”,(“发送邮件”,“邮件”,“smtp”]);}}
如果你通过一个无效的交通,一个InvalidOptionsException抛出:
1 2 3 4 5 6
美元梅勒=新梅勒([“交通”= >“发送邮件”]);/ / InvalidOptionsException:选择“运输”价值“发送邮件”/ /无效。接受值:“发送邮件”,“邮件”,“smtp”
对更复杂的验证方案,选择通过关闭它返回真正的
可接受的值和假
无效值:
1 2 3 4
/ /……美元解析器- >setAllowedValues (“交通”,函数(美元价值){/ /返回true或false});
在子类中,您可以使用addAllowedValues ()添加额外的允许没有删除已经设置的值。
选择归一化
有时,选项值需要归一化之前,您可以使用它们。例如,假设主机
应该开始http://
。要做到这一点,您可以编写标准化者。标准化者执行验证后一个选项。您可以配置一个标准化者通过调用setNormalizer ():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
使用ob娱乐下载\组件\OptionsResolver\选项;/ /……类梅勒{/ /……公共函数configureOptions(OptionsResolver美元解析器){/ /……美元解析器- >setNormalizer (“主机”,函数(选项美元选项,美元价值){如果(“http://”! = = substr (美元价值,0,7)){美元价值=“http://”。美元价值;}返回美元价值;});}}
标准化者接收到实际美元的价值
并返回标准化形式。你也看到,关闭以一个选择美元
参数。这是有用的,如果你需要使用其他选项在归一化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/ /……类梅勒{/ /……公共函数configureOptions(OptionsResolver美元解析器){/ /……美元解析器- >setNormalizer (“主机”,函数(选项美元选项,美元价值){如果(“http://”! = = substr (美元价值,0,7)& &“https://”! = = substr (美元价值,0,8)){如果(“ssl”= = =美元选项(“加密”){美元价值=“https://”。美元价值;}其他的{美元价值=“http://”。美元价值;}}返回美元价值;});}}
依赖于另一个选项的默认值
假设你想设置的默认值港口
选择基于加密的用户选择梅勒
类。更准确地说,你想设置端口465年
如果使用SSL和25
否则。
您可以实现此功能通过一个闭包的默认值港口
选择。关闭接收选项作为参数。根据这些选项,您可以返回所需的默认值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
使用ob娱乐下载\组件\OptionsResolver\选项;/ /……类梅勒{/ /……公共函数configureOptions(OptionsResolver美元解析器){/ /……美元解析器- >setDefault (“加密”,零);美元解析器- >setDefault (“端口”,函数(选项美元选项){如果(“ssl”= = =美元选项(“加密”){返回465年;}返回25;});}}
谨慎
可调用的参数必须类型暗示选项
。否则,可调用本身被认为是选项的默认值。
请注意
关闭只是如果执行港口
选择不设置由用户或覆盖在一个子类。
之前设置的默认值可以通过添加访问关闭第二个参数:
1 2 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;});}}
示例中可以看到,此功能主要是有用的,如果你想重复使用默认值设置在子类的父类。
选项没有默认值
在某些情况下,它是有用的定义一个选项没有设置一个默认值。这是有用的,如果你需要知道是否用户实际上设置一个选项。例如,如果您设置一个选项的默认值,这是不可能的知道用户通过这个值或如果它只是来自默认:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/ /……类梅勒{/ /……公共函数configureOptions(OptionsResolver美元解析器){/ /……美元解析器- >setDefault (“端口”,25);}/ /……公共函数sendMail(美元从,美元来){/ /这是默认值或类的调用者真的/ /设置端口25 ?如果(25= = =美元这- >选项(“端口”){/ /……}}}
您可以使用setDefined ()定义一个选项没有设置一个默认值。然后选择只会包含在选项如果它实际上是传递给解决解决():
1 2 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 ()让你找出哪些选项定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/ /……类GoogleMailer扩展梅勒{/ /……公共函数configureOptions(OptionsResolver美元解析器){父::configureOptions (美元解析器);如果(美元解析器- >isDefined (“主机”)){/ /以下被称为之一:/ /解析器- > setDefault(“主机”,…);/ /解析器- > setRequired('主机');/ /解析器- > setDefined('主机');}美元definedOptions=美元解析器- >getDefinedOptions ();}}
性能调整
与当前的实现configureOptions ()
方法将呼吁每一个的实例梅勒
类。根据选择的数量配置和创建实例的数量,这可能为应用程序添加显著的开销。如果开销成为一个问题,你可以改变你的每个类只配置一次代码:
1 2 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(数组美元选项= []){/ /这是什么类型的梅勒,梅勒,GoogleMailer,…吗?美元类= get_class (美元这);/ /是configureOptions()之前执行这个类?如果(!收取(自我::$resolversByClass [美元类))){自我::$resolversByClass [美元类]=新OptionsResolver ();美元这- >configureOptions (自我::$resolversByClass [美元类]);}美元这- >选择=自我::$resolversByClass [美元类]- >解决(美元选项);}公共函数configureOptions(OptionsResolver美元解析器){/ /……}}
现在,OptionsResolver每次创建类实例和重用的。请注意,这可能会导致长时间运行的应用程序中的内存泄漏,如果默认选项包含对象的引用或对象图。如果是这种情况,实现方法clearOptionsConfig ()
并定期称之为:
1 2 3 4 5 6 7 8 9 10 11 12
/ /……类梅勒{私人静态美元resolversByClass= [];公共静态函数clearOptionsConfig(){自我::$resolversByClass = [];}/ /……}
就是这样!你现在有了所需的所有工具和知识过程选项在您的代码中。