覆盖 KNP DoctrineBehaviors "under-the-hood"

Override KNP DoctrineBehaviors "under-the-hood"

我正在写一个 SEO 包,主要由两部分组成:

最重要的是,我想使用 sluggable trait 站在 KNP DoctrineBehaviors 的肩膀上。

我的问题:在我的架构中,Sluggable 特性将被我的 Seoable 特性使用,而不是最终 class。在 DoctrineBehaviors 的内部,我发现特征检查是由 ClassAnalyzer class 完成的,方法是:

/**
     * Return TRUE if the given object use the given trait, FALSE if not
     * @param ReflectionClass $class
     * @param string $traitName
     * @param boolean $isRecursive
     */
    public function hasTrait(\ReflectionClass $class, $traitName, $isRecursive = false)
    {
        if (in_array($traitName, $class->getTraitNames())) {
            return true;
        }

        $parentClass = $class->getParentClass();

        if ((false === $isRecursive) || (false === $parentClass) || (null === $parentClass)) {
            return false;
        }

        return $this->hasTrait($parentClass, $traitName, $isRecursive);
    }

递归部分检查所有祖先class,但不检查特征中包含的特征。

2 个解决方案在我的脑海中:

DoctrineBehaviors 不是 "regular" 包,这意味着未在 AppKernel 中注册。我如何扩展这部分?

感谢您的回复,

尼古拉斯

多亏了对 this part of cookbook 的更细心的阅读,我检查了 DoctrineBehaviors 配置文件 (vendor/knplabs/doctrine-behaviors/config/orm-services.yml)。

KNP 在这里提供所有参数给侦听器和 类 在 DoctrineBehaviors 包中使用,例如:

parameters:
    knp.doctrine_behaviors.reflection.class_analyzer.class: Knp\DoctrineBehaviors\Reflection\ClassAnalyzer
    knp.doctrine_behaviors.reflection.is_recursive: true
    knp.doctrine_behaviors.translatable_subscriber.class: Knp\DoctrineBehaviors\ORM\Translatable\TranslatableSubscriber
# next...

所以,我只是覆盖了第一个参数,以在参数 config.yml 部分使用我自己的 ClassAnalyser 实例。 作为记录,具有祖先特征检查的递归循环:

     /**
     * Return TRUE if the given object use the given trait, FALSE if not
     * Extends from ClassAnalyzer::hasTrait to check in ancestors traits as well
     * @param \ReflectionClass $class
     * @param string $traitName
     * @param boolean $isRecursive
     */
    public function hasTrait(\ReflectionClass $class, $traitName, $isRecursive = false)
    {
        $classTraits = $class->getTraitNames();

        // Trait directly present in final class
        if (in_array($traitName, $classTraits)) {
            return true;
        }

        // Check in parents traits
        foreach($classTraits as $classTrait) {
            $traitObject = new \ReflectionClass($classTrait);

            if($this->hasTrait($traitObject, $traitName, $isRecursive)) {
                return true;
            }
        }

        // Check in parents classes
        $parentClass = $class->getParentClass();

        if ((false === $isRecursive) || (false === $parentClass) || (null === $parentClass)) {
            return false;
        }

        return $this->hasTrait($parentClass, $traitName, $isRecursive);
    }