使用Reflection查找方法所属的类

Tyl*_* V. 4 php reflection class magento

我在Magento工作,但这更像是一个普通的PHP问题.情况是在Magento中,有些类扩展了扩展类的类的类.我希望能够快速找到哪个类实际包含方法的定义和/或该方法实际上是魔术.

因此,例如,如果我在扩展其他类的类中有10个级别,并且这10个类中的4个有一个调用的方法getHtml,我希望能够找到在调用时实际调用这些方法中的哪一个$this->getHtml().我还想知道它getHtml是否真的是一种神奇的方法.

如何使用PHP Reflection Class或任何其他编程方法执行此操作?

Ala*_*orm 10

(下面未经测试的代码 - 如果您发现任何错误,我会感谢评论中的更新)

你就可以与反射API做的最好的是发现在其中的方法的分级中的类没有定义.该ReflectionClasshasMethod功能将父类考虑-它一个更好的名字可能aClassInTheHierarchyHasThisMethod.考虑这个(快速的我的头部)内联函数

    $getClassesWithMethod = function($classOrObject, $method, $return=false) use(&$getClassesWithMethod)
    {
        $return = $return ? $return : new ArrayObject;
        $r = new ReflectionClass($classOrObject);
        if($r->hasMethod($method))
        {
            $return['has ' . $method . ' method'][] = $r->getName();
        }
        else
        {
            $return['no '. $method . ' method'][] = $r->getName();
        }

        $parent = $r->getParentClass();
        if($parent)
        {
            $getClassesWithMethod($parent->getName(), $method, $return);
        }
        return $return;
    };

    $product = Mage::getModel('catalog/product'); 

    $classesWithMethod = $getClassesWithMethod($product, 'load');
    var_dump((array)$classesWithMethod);
Run Code Online (Sandbox Code Playgroud)

运行上面,你会得到

array (size=2)
  'has load method' => 
    array (size=4)
      0 => string 'Mage_Catalog_Model_Product' (length=26)
      1 => string 'Mage_Catalog_Model_Abstract' (length=27)
      2 => string 'Mage_Core_Model_Abstract' (length=24)
  'no load method' => 
    array (size=1)
      0 => string 'Varien_Object' (length=13)
Run Code Online (Sandbox Code Playgroud)

所以你知道Varien_Object没有load定义方法,这意味着它首先显示出来Mage_Core_Model_Abstract.然而,你不会知道是否也有一个定义Mage_Catalog_Model_AbstractMage_Catalog_Model_Product.Reflection API不会让你这么做.

什么可以使用该token_get_all方法得到你.这个方法可以将PHP文件分解为它的组件PHP/Zend标记.完成后,您可以在PHP中编写一个小解析器,用于标识特定类文件中的方法/函数定义.您可以使用它来递归检查层次结构.同样,内联函数.

    $getClassesWithConcreteDefinition = function($classOrObject,$method,$return=false) use(&$getClassesWithConcreteDefinition)
    {
        $return = $return ? $return : new ArrayObject;
        $r = new ReflectionClass($classOrObject);
        $tokens = token_get_all(file_get_contents($r->getFilename()));

        $is_function_context = false;
        foreach($tokens as $token)
        {
            if(!is_array($token)){continue;}                
            $token['name'] = token_name($token[0]);
            if($token['name'] == 'T_WHITESPACE'){ continue; }

            if($token['name'] == 'T_FUNCTION')
            { 
                $is_function_context = true;
                continue;
            }

            if($is_function_context)
            {
                if($token[1] == $method)
                {
                    $return[] = $r->getName();
                }
                $is_function_context = false;
                continue;
            }
        }

        $parent = $r->getParentClass();
        if($parent)
        {
            $getClassesWithConcreteDefinition($parent->getName(),$method,$return);
        }

        return $return;
    };

    $product = Mage::getModel('catalog/product');        

    $hasActualDefinition = $getClassesWithConcreteDefinition($product, 'setData');
    var_dump((array)$hasActualDefinition);
Run Code Online (Sandbox Code Playgroud)

我们在这里检查setData方法.以上将返回

array (size=2)
  0 => string 'Mage_Catalog_Model_Abstract' (length=27)
  1 => string 'Varien_Object' (length=13)
Run Code Online (Sandbox Code Playgroud)

因为setDataMage_Catalog_Model_Abstract类和Varien_Object类中都定义了.您应该能够修改这些功能以满足您自己的需要.祝好运!