当前位置:  开发笔记 > 编程语言 > 正文

如何在PHP项目中找到未使用的函数

如何解决《如何在PHP项目中找到未使用的函数》经验,为你挑选了4个好方法。

如何在PHP项目中找到任何未使用的函数?

是否有功能或API内置到PHP,让我分析我的代码库-例如反射,token_get_all()

这些API功能是否足够丰富,我不必依赖第三方工具来执行此类分析?



1> Gordon..:

你可以试试Sebastian Bergmann的死码探测器:

phpdcd是用于PHP代码的死代码检测器(DCD).它扫描PHP项目中所有已声明的函数和方法,并将其报告为"死代码",至少不会调用一次.

资料来源:https://github.com/sebastianbergmann/phpdcd

请注意,它是一个静态代码分析器,因此它可能会为仅动态调用的方法提供误报,例如它无法检测 $foo = 'fn'; $foo();

你可以通过PEAR安装它:

pear install phpunit/phpdcd-beta

之后,您可以使用以下选项:

Usage: phpdcd [switches]  ...

--recursive Report code as dead if it is only called by dead code.

--exclude  Exclude  from code analysis.
--suffixes  A comma-separated list of file suffixes to check.

--help Prints this usage information.
--version Prints the version and exits.

--verbose Print progress bar.

更多工具:

https://phpqa.io/


注意:根据存储库通知,此项目不再维护,其存储库仅用于存档目的.所以你的里程可能不一样.


从github页面:"此项目不再维护,其存储库仅用于存档目的."
@Dereckson是的,我同意.但是直到有人最终做到这一点,这个*仍然比没有好.

2> Stacey Richa..:

感谢Greg和Dave的反馈.不是我想要的,但我决定花一点时间研究它,并提出了这个快速而肮脏的解决方案:

" .
            "" .
                "Name" .
                "Defined" .
                "Referenced" .
            "";
    foreach ($functions as $name => $value) {
        echo
            "" . 
                "" . htmlentities($name) . "" .
                "" . (isset($value[0]) ? count($value[0]) : "-") . "" .
                "" . (isset($value[1]) ? count($value[1]) : "-") . "" .
            "";
    }
    echo "";
    function define_dir($path, &$functions) {
        if ($dir = opendir($path)) {
            while (($file = readdir($dir)) !== false) {
                if (substr($file, 0, 1) == ".") continue;
                if (is_dir($path . "/" . $file)) {
                    define_dir($path . "/" . $file, $functions);
                } else {
                    if (substr($file, - 4, 4) != ".php") continue;
                    define_file($path . "/" . $file, $functions);
                }
            }
        }       
    }
    function define_file($path, &$functions) {
        $tokens = token_get_all(file_get_contents($path));
        for ($i = 0; $i < count($tokens); $i++) {
            $token = $tokens[$i];
            if (is_array($token)) {
                if ($token[0] != T_FUNCTION) continue;
                $i++;
                $token = $tokens[$i];
                if ($token[0] != T_WHITESPACE) die("T_WHITESPACE");
                $i++;
                $token = $tokens[$i];
                if ($token[0] != T_STRING) die("T_STRING");
                $functions[$token[1]][0][] = array($path, $token[2]);
            }
        }
    }
    function reference_dir($path, &$functions) {
        if ($dir = opendir($path)) {
            while (($file = readdir($dir)) !== false) {
                if (substr($file, 0, 1) == ".") continue;
                if (is_dir($path . "/" . $file)) {
                    reference_dir($path . "/" . $file, $functions);
                } else {
                    if (substr($file, - 4, 4) != ".php") continue;
                    reference_file($path . "/" . $file, $functions);
                }
            }
        }       
    }
    function reference_file($path, &$functions) {
        $tokens = token_get_all(file_get_contents($path));
        for ($i = 0; $i < count($tokens); $i++) {
            $token = $tokens[$i];
            if (is_array($token)) {
                if ($token[0] != T_STRING) continue;
                if ($tokens[$i + 1] != "(") continue;
                $functions[$token[1]][1][] = array($path, $token[2]);
            }
        }
    }
?>

我可能会花更多的时间在上面,这样我就可以快速找到函数定义和引用的文件和行号; 这些信息正在收集,只是没有显示.



3> 小智..:

这一点bash脚本可能会有所帮助:

grep -rhio ^function\ .*\(  .|awk -F'[( ]'  '{print "echo -n " $2 " && grep -rin " $2 " .|grep -v function|wc -l"}'|bash|grep 0

这基本上递归地抓取当前目录的函数定义,将命中传递给awk,这形成了执行以下操作的命令:

打印功能名称

递归grep再次

输出到grep -v的管道,用于过滤掉函数定义,以便保留对函数的调用

将此输出传递给wc -l,它打印行数

然后将此命令发送到bash执行,输出被grepped为0,这表示0调用该函数.

请注意,这不是解决问题calebbrown上述列举,所以有可能在输出一些误报.



4> Andrey Butov..:

用法:find_unused_functions.php

注意:这是解决问题的"快速肮脏"方法.此脚本仅对文件执行词法传递,并且不考虑不同模块定义具有相同名称的函数或方法的情况.如果您使用IDE进行PHP开发,它可能会提供更全面的解决方案.

需要PHP 5

为了节省您的复制和粘贴,可以在此处获得直接下载和任何新版本.

#!/usr/bin/php -f

 $file, 'line' => $line);
                        }
                    }
                }
            }
        }
    }
}

// We now have a collection of defined functions and
// their definition locations. Go through the tokens again, 
// and find 'uses' of the function names. 

foreach ( $tokenized as $file => $tokens )
{
    foreach ( $tokens as $token )
    {
        if ( is_array($token) && safe_arr($token, 0) == T_STRING )
        {
            $function_name = safe_arr($token, 1, false);
            $function_line = safe_arr($token, 2, false);;

            if ( $function_name && $function_line )
            {
                $locations_of_defined_function = safe_arr($defined_functions, $function_name, false);

                if ( $locations_of_defined_function )
                {
                    $found_function_definition = false;

                    foreach ( $locations_of_defined_function as $location_of_defined_function )
                    {
                        $function_defined_in_file = $location_of_defined_function['file'];
                        $function_defined_on_line = $location_of_defined_function['line'];

                        if ( $function_defined_in_file == $file && 
                             $function_defined_on_line == $function_line )
                        {
                            $found_function_definition = true;
                            break;
                        }
                    }

                    if ( !$found_function_definition )
                    {
                        // We found usage of the function name in a context
                        // that is not the definition of that function. 
                        // Consider the function as 'used'.

                        unset($defined_functions[$function_name]);
                    }
                }
            }
        }
    }
}


print_report($defined_functions);   
exit;


// ============================================================================

function php_files($path) 
{
    // Get a listing of all the .php files contained within the $path
    // directory and its subdirectories.

    $matches = array();
    $folders = array(rtrim($path, DIRECTORY_SEPARATOR));

    while( $folder = array_shift($folders) ) 
    {
        $matches = array_merge($matches, glob($folder.DIRECTORY_SEPARATOR."*.php", 0));
        $moreFolders = glob($folder.DIRECTORY_SEPARATOR.'*', GLOB_ONLYDIR);
        $folders = array_merge($folders, $moreFolders);
    }

    return $matches;
}

// ============================================================================

function safe_arr($arr, $i, $default = "")
{
    return isset($arr[$i]) ? $arr[$i] : $default;
}

// ============================================================================

function tokenize($file)
{
    $file_contents = file_get_contents($file);

    if ( !$file_contents )
    {
        return false;
    }

    $tokens = token_get_all($file_contents);
    return ($tokens && count($tokens) > 0) ? $tokens : false;
}

// ============================================================================

function usage()
{
    global $argv;
    $file = (isset($argv[0])) ? basename($argv[0]) : "find_unused_functions.php";
    die("USAGE: $file \n\n");
}

// ============================================================================

function print_report($unused_functions)
{
    if ( count($unused_functions) == 0 )
    {
        echo "No unused functions found.\n";
    }

    $count = 0;
    foreach ( $unused_functions as $function => $locations )
    {
        foreach ( $locations as $location )
        {
            echo "'$function' in {$location['file']} on line {$location['line']}\n";
            $count++;
        }
    }

    echo "=======================================\n";
    echo "Found $count unused function" . (($count == 1) ? '' : 's') . ".\n\n";
}

// ============================================================================

/* EOF */

推荐阅读
k78283381
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有