【问题标题】:Symfony - How to validate configuration node against another node value?Symfony - 如何根据另一个节点值验证配置节点?
【发布时间】:2015-10-01 19:43:30
【问题描述】:

在我的 Configuration.php 中,我的结构如下:

public function getConfigTreeBuilder()
{
  $treeBuilder = new TreeBuilder();
  $rootNode = $treeBuilder->root('my_bundle');

  $rootNode
    ->children()
      ->scalarNode('class')->cannotBeEmpty()->end()
      ->arrayNode('social_network')
        ->children()
          ->arrayNode('facebook')
            ->validate()
              ->ifTrue(function($node) {

                // my logic to validate if the 'class' specified implements my trait

              })
              ->thenInvalid('You must use XXXXXX trait in your class.')
            ->end()
            ->children()
              ->scalarNode('app_id')->isRequired()->cannotBeEmpty()->end()
              ->scalarNode('secret')->isRequired()->cannotBeEmpty()->end()
            ->end()
          ->end()
        ->end()
      ->end()
    ->end();

    return $treeBuilder;
}

我需要检查指定的类是否实现了我的包的特定特征部分。

如何读取function($node)class 的值?

【问题讨论】:

    标签: validation symfony configuration traits


    【解决方案1】:

    这是一个有趣的问题,所以我决定尝试一下,看看如何完成。通常,只会进行更一般的验证,这就是为什么我猜您不能直接在 getConfigTreeBuilder 函数中进行验证。或者至少我找不到方法。您可以尝试执行function($node) use($rootNode),但无法获得node 的值。因此,即使您尝试在匿名函数范围内执行 $rootNode->getNode('class'),您也无法获得实际值。

    另一方面,您可以做的是转到您的Extension 课程(位于DependencyInjection 目录中)并在那里进行验证。像这样的东西应该可以完成工作:

    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $config = $this->processConfiguration($configuration, $configs);
    
        $class = $config['class'];
    
        // Apply your logic here...
        if(!$this->checkForTrait($class, 'myTrait')) {
            throw new \ErrorException("The class ".$class." should implement myTrait!");
        }
    
        $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
        $loader->load('services.yml');
    }
    
    private function checkForTrait($class, $trait)
    {
        $class = new \ReflectionClass($class);
        $traits = $class->getTraitNames(); // returns an array of all trait names being currently used in that class.
        return in_array($trait, $traits);
    }
    

    我不知道这是否被认为是“最佳实践”,所以如果有人有更好的解决方案,请指出:)

    【讨论】:

      【解决方案2】:

      您所要做的就是在scalarNode('class') 节点内调用validate() 方法。看看:

      public function getConfigTreeBuilder()
      {
          $treeBuilder = new TreeBuilder();
          $rootNode = $treeBuilder->root('my_bundle');
      
          $rootNode
              ->children()
                  ->scalarNode('class')
                      ->cannotBeEmpty()
                      ->validate()
                          ->ifTrue(function ($value) {
                              // my logic to validate if the 'class' specified implements my trait
      
                              $reflection = new \ReflectionClass($value);
                              $traitsNames = $reflection->getTraitNames();
      
                              return false === \in_array('myTrait', $traitsNames, true);
                          })
                          ->thenInvalid('You must use XXXXXX trait in your class.')
                      ->end()
                  ->end()
                  ->arrayNode('social_network')
                      ->children()
                          ->arrayNode('facebook')
                              ->children()
                                  ->scalarNode('app_id')->isRequired()->cannotBeEmpty()->end()
                                  ->scalarNode('secret')->isRequired()->cannotBeEmpty()->end()
                              ->end()
                          ->end()
                      ->end()
                  ->end()
              ->end()
          ;
      
          return $treeBuilder;
      }
      

      以这种方式验证每个标量class 节点。 $valueclass 节点的值,所以它是你的类的名称。

      剩下的:

      $reflection = new \ReflectionClass($value);
      $traitsNames = $reflection->getTraitNames();
      
      return false === \in_array('myTrait', $traitsNames, true);
      

      这只是一段验证 trait 是否被实现的 php 代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多