php - 使用反射查找某个方法所属的类

标签 php class magento reflection

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

例如,如果我深入 10 个类来扩展其他类,并且这 10 个类中有 4 个有一个名为 getHtml 的方法,我希望能够找出其中的哪一个当我调用 $this->getHtml() 时,方法实际上被调用了。我还想知道 getHtml 是否真的是一个神奇的方法。

我如何使用 PHP 反射类或任何其他编程方式来做到这一点?

最佳答案

(下面未经测试的代码——如果您发现任何错误,我将不胜感激在评论中进行更新)

您使用反射 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);

运行上面的代码,你会得到

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)

所以您知道 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);

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

array (size=2)
  0 => string 'Mage_Catalog_Model_Abstract' (length=27)
  1 => string 'Varien_Object' (length=13)

因为 setDataMage_Catalog_Model_Abstract 类和 Varien_Object 类中都有定义。您应该能够修改这些函数以满足您自己的需要。祝你好运!

关于php - 使用反射查找某个方法所属的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22873403/

相关文章:

php - jQuery PHP 在函数内传递值与实时点击?

php - 使用 php/mysql 系统显示错误消息

jquery - 帮助多图像jquery悬停

php - htaccess IfModule 条件失败

php - 具有完整规范 url 的 Magento 产品导出

php - 如何在不同浏览器的手机上自动修复网站的分辨率?

php - 为什么 var_dump(array) 在 Magento 中会导致 500 错误?

java - 运行外部java类(项目)

python - 使用 matplotlib 在 Tkinter 中绘制数据 - 在列表之间切换

javascript - 通过 JavaScript 访问 Magento SOAP API : What am i doing wrong?