42. 配置系统Configuration(四):配置schema与类型化
在上篇中讲了配置schema和配置对象类型化,那么如何得到配置对象的类型化数据对象呢?该对象是类型化配置管理器通过schema定义实例化完成的,在配置对象Drupal\Core\Config\Config中已经展示了得到它的方法, 如下:
Drupal\Core\Config\Config::getSchemaWrapper()
配置对象中的schemaWrapper属性就是该配置对象的类型化数据对象,但getSchemaWrapper()方法仅内部使用,其可见性为:protected,在配置对象的实现中仅用该方法进行配置数据的类型校正,在控制器中执行以下方法我们可以在外部得到配置对象的类型化数据对象:
$typedConfigManager = \Drupal::service("config.typed");
//获取类型化配置管理器
$name = "system.site";
//示例一个配置对象
$data = \Drupal::configFactory()->getEditable($name)->getRawData();
//实时获取配置对象中储存的数据,配置对象如果被修改,得到的是修改后的值
$definition = $typedConfigManager->getDefinition($name);
//得到配置类型的插件定义,也就是schema配置文件中的内容,但经过递归合并,暂未处理动态类型
$data_definition = $typedConfigManager->buildDataDefinition($definition, $data);
//构建返回类型化数据对象的定义对象,因为schema定义中type属性允许动态内容
//(如[%parent.%parent.%type].third_party.[%key]),所以需要传递配置对象的数据参数
$typed_data = $typedConfigManager->create($data_definition, $data);
//创建类型化对象,最终我们得到了一个类型化配置数据对象
如果不考虑修改配置的情况也可以用以下快捷方法:
$typedConfigManager = \Drupal::service("config.typed");
//获取类型化配置管理器
$name = "system.site";
//示例一个配置对象
$typed_data = $typedConfigManager->get($name);
//从类型化配置管理器中直接获取配置对象的类型化数据对象,但配置值是来自配置储存服务的
为更加清楚,以下以配置实体类型来说明:
$typedConfigManager=\Drupal::service("config.typed");
$definition=$typedConfigManager->getDefinition("config_entity");
print_r($definition);
exit();
得到的定义将是:
Array
(
[label] => Mapping
[class] => Drupal\Core\Config\Schema\Mapping
[definition_class] => \Drupal\Core\TypedData\MapDataDefinition
[mapping] => Array
(
[uuid] => Array
(
[type] => string
[label] => UUID
)
[langcode] => Array
(
[type] => string
[label] => Language code
)
[status] => Array
(
[type] => boolean
[label] => Status
)
[dependencies] => Array
(
[type] => config_dependencies
[label] => Dependencies
)
[third_party_settings] => Array
(
[type] => sequence
[label] => Third party settings
[sequence] => Array
(
[type] => [%parent.%parent.%type].third_party.[%key]
)
)
[_core] => Array
(
[type] => _core_config_info
)
)
[type] => config_entity
)
注意:从类型化配置管理器中得到定义时third_party_settings项中的序列类型的动态变量并没有被替换,依然保持原来定义中的:
[type] => [%parent.%parent.%type].third_party.[%key]
该步骤的替换操作是在类型化对象获取该子项的类型化数据对象时进行的,也就是$typed_data->get($name),其中参数name可以是用点分隔的表示数组层级的字符串,那将在类型化配置管理器的buildDataDefinition方法中进行替换处理,传入的第二个参数$data是对应的配置值
mapping和sequence:
在配置系统中这两种数据类型,并不是使用类型化组件提供的:
Drupal\Core\TypedData\Plugin\DataType\Map
Drupal\Core\TypedData\Plugin\DataType\ItemList
注意不要将他们混淆,mapping和sequence只在配置系统中使用,他们是:
\Drupal\Core\Config\Schema\Mapping
\Drupal\Core\Config\Schema\Sequence
他们都是类型化数据对象:映射和序列的类实现,但mapping和sequence是针对配置系统的特殊实现,继承了不同类,实现了接口:Drupal\Core\Config\Schema\TypedConfigInterface
Schema无定义:
配置对象的schema定义是可选的,如果配置对象没有对应定义schema,那么缺省情况下获取类型对象时当做undefined类型处理,通过上文获取到的类型对象是Drupal\Core\Config\Schema\Undefined类的实例,该类型化配置对象可以使用如下方法得到保存的值:
$typed_data->getValue();
但是在模块安装时,没有定义配置schema的配置对象是以config_object类型进行处理,因此保存的配置内容含有langcode和_core属性
判断某配置对象时候定义了schema可以使用如下方法:
$typedConfigManager=\Drupal::service("config.typed");
$typedConfigManager –>hasConfigSchema($name); //将返回布尔值
Undefined和ignore类型的区别:
他们只是代表的意义不同,如字面意思,一个代表未定义,一个代表忽略不考虑类型,但是实现上完全相同,因此使用方法均相同;设置ignore类型在有些情况下很有用,比如在验证schema定义有效性时,如果是未定义,表示schema定义不通过,需要更正,如果明确指出是ignore类型那么验证将通过
本篇就介绍到这里,以后的主题中还将陆续介绍配置安装、导入、比较等,配置系统很大,和其他组件有机结合,之后介绍的主题涉及配置内容时标题不再专门用配置系统编号,如是专门介绍配置系统某块内容仍然以本篇标题的形式递增序号,目前已介绍的内容足够理解实体配置,下篇将结合实体系统,介绍配置实体方面的内容。
为了阅读内容时已经具备前备知识,请按本系列主题的发布顺序跟随阅读