Stacey Richards
그는 물었다 12년 전
58

Php 의 기능이 어떻게 찾을수 비사용률 프로젝트

Php 의 기능이 비사용률 찾을 수 있는 방법은 프로젝트?

Api 를 날 수 있는 내 발생합니까 피쳐나 내장되었을 PHP 코드 분석 - 예를 들어 반사, 'token_get_all ()'?

이들 api 기능을 충분히 수행할 수 없는 가져다줄래요 부유하도다 타사 도구를 이용할 수 있는 이 유형의 분석을?

Dave Marshall
그는 12년 전 댓글을 달았습니다
0

[스드버그] (http://www.xdebug.org/) 등도 제공할 수 있는 [코드 커버리지] (http://www.xdebug.org/docs/code_coverage). [Ini 디렉티브에는] auto_append_file auto_prepend_file 정보기술 (it) 과 함께 사용할 수 있습니다 (http://php.net/ini.core) 응용 프로그램의 코드 커버리지 로깅하도록 일반적인 사용 중.

Mchl
그는 10년 전 댓글을 달았습니다
0

코드 커버리지 분석 (http://www.xdebug.org/docs/code_coverage) '와' 스드버그 너희가 알 수 있다.

Pekka supports GoFundMonica
그는 10년 전 댓글을 달았습니다
1

내가 찾을 수 있는 간단한 파일을 검색할 수 있는 자주 사용하지 않는 변수, 함수 이름을 못하며창조된 이미 deltamove you& # 39 - re 등.

답변 9 개

39 의 세바스찬 Bergmann& 불필요한 코드 없이 시도할 수 있습니다.

&gt. 불필요한 코드 '는' 파프드스트 검출기 (DCD) 의 PHP 코드. Php 는 프로젝트의 선언된 모든 함수 및 메서드 및 보고서 검색하여 cerner 部门是这样的 &quot 죽은입니다 code"; 불렀으매 않는 한 번 이상.

출처: https://github.com/sebastianbergmann/phpdcd

참고로 it& 부여할 수 있기 때문에, 정적 코드 s # 39 만 호출됨 무중단으로 대한 거짓값 포지티브 어낼라이저 메서드입니다 foo $ = & # 39 fn& 탐지합니다 없습니다 ' (예: # 39;;; 'foo $ ();

Pear 통해 이를 설치할 수 있습니다.

pear install phpunit/phpdcd-beta

그 후 다음 옵션과 함께 사용할 수 있습니다.

Usage: phpdcd [switches] <directory|file> ...

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

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

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

--verbose Print progress bar.

더 많은 도구.

, 리포지토리를 Note: 따라 이 사업은 계속 유지되고, 그 밖에 더 이상 디이브이 리포지토리를 보관 용도로 . 따라서, 마일리지 다를 수 있습니다.

TravisCarden
Burhan Ali
그는 5년 전 댓글을 달았습니다
2

깃허브 에서 페이지: 이 프로젝트는 &quot, 더 이상 유지 및 해당 리포지토리를 아카이빙할 purposes.&quot 보관할 불과하다.

Gordon
그는 5년 전 댓글을 달았습니다
0

더 이상 더 이상 작동하지 않는 등 @burhanali 의미하는 것은 아니다라고 주장했다. Feel free to 시행하십시오 유지보수를.

Dereckson
그는 5년 전 댓글을 달았습니다
1

39 더 이상 유지할 수 없는 이유가 @gordon it& 대형 정보기술 (it), s, t # 39 의 스펙트럼을 메서드 호출 doesn& 탐지합니다: &quot &quot 클래스 메서드를 ();; 예를 들어 및 구성자를 보고됨 사용되지 않고 있다. 아니다, 동적 언어 이상적임 반사 외곽진입 도구 개선 등 새 이름을 사용한 방법은 현실적으로 아니하였으매 재작성할 짓궂군요 사용하여 다른 외곽진입 감지할 수 있습니다.

Gordon
그는 5년 전 댓글을 달았습니다
2

@Dereckson yes, I agree. 하지만 결국, 이 때까지 는 여전히 사람이 있나 보다 아무것도아니야.

BurninLeo
그는 5년 전 댓글을 달았습니다
0

이 &quot tools&quot, 더 많이 주셔서 감사합니다. php 는 &quot 엉망하지 Detector&quot, 링크, 해당) 은 다음과 같은 뜻이 있다. (http://phpmd.org/)

감사합니다, 데이브 그렉이야 대한 피드백. # 39, t 꽤 있지만, 내가 찾던 wasn& 결심했다고 동일팔레트에 조금 시간을 다음 연구하고 빠르고 정보기술 (it) 과 한국증권선물거래소법을 더러운 해결책:

<?php
    $functions = array();
    $path = "/path/to/my/php/project";
    define_dir($path, $functions);
    reference_dir($path, $functions);
    echo
        "<table>" .
            "<tr>" .
                "<th>Name</th>" .
                "<th>Defined</th>" .
                "<th>Referenced</th>" .
            "</tr>";
    foreach ($functions as $name => $value) {
        echo
            "<tr>" . 
                "<td>" . htmlentities($name) . "</td>" .
                "<td>" . (isset($value[0]) ? count($value[0]) : "-") . "</td>" .
                "<td>" . (isset($value[1]) ? count($value[1]) : "-") . "</td>" .
            "</tr>";
    }
    echo "</table>";
    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]);
            }
        }
    }
?>

39, ll 아마도 더 많은 시간을 할애할 수 있는 규모로 i& 그래야 내가 빨리 찾을 줄 번호 함수의 정의와 참조입니다, 파일 및 이 정보가 수집되고, 그냥 표시되지 않습니다.

Stacey Richards
calebbrown
그는 12년 전 댓글을 달았습니다
1

이 솔루션은 사용하지 않는 경우 () '또는' 좋은 'call_user_func call_user_func_array ()' 또는 '에서 $ var ()'

jlh
그는 2년 전 댓글을 달았습니다
0

난 이미 재장착하려면 두 개의 '다이 ()' 을 (를) '이 아니라' 에 대해 계속 경계감소 익명 총괄하였습니다.

이 배시 스크립팅하는 조금이라도 도움이 됩니다.

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

기본적으로 이 함수 정의, awk, 현재 디렉터리에 반복적으로 그렙 통과할 안타에 명령을 형성하는 다음 작업을 수행할 수 있습니다.

  • 함수 이름을 인쇄인쇄
  • 그렙 위해 재귀적으로 다시
  • 파이핑이 출력을 유지할 수 있는 함수 정의에 따라서 함수 호출을 필터링하도록 그렙 - v
  • 이 출력입니다 wc 뻦 인쇄하는 데 파이프 라인 카운트입니다

이 명령은 시연장에 전송할 수 있는 그레프트 실행을 위해 bash 및 출력이 0 0 에 대해 함수 나타낼 수 있다.

참고로 이 문제를 해결할 수 있으므로, 있을 수 없는 거역한다면 비유하사 케일럽 브라운 위에 있는 일부 거짓값 포지티브 출력입니다.

사용법: , , gt root_directory&amp find_unused_functions.php &amp lt;;

참고: 이는 "빠른 ᄂ씨 더러운" 접근 방식이 아니다. 이 상황을 통해 전달하십시오 파일이므로 스크립트만 는 사전적 정의 함수 또는 메서드을 같은 이름의 다른 모듈에서는 존중하십시오 않습니다. Php 개발 IDE 를 사용하는 경우, 그것은 더 포괄적인 솔루션을 제공할 수 있습니다.

Php 5 필요합니다.

모든 새로운 버전을 저장하라는 너희에의 복사, 붙여넣기 직접 다운로드할 수 있다. 여기에서 ,

#!/usr/bin/php -f

<?php

// ============================================================================
//
// find_unused_functions.php
//
// Find unused functions in a set of PHP files.
// version 1.3
//
// ============================================================================
//
// Copyright (c) 2011, Andrey Butov. All Rights Reserved.
// This script is provided as is, without warranty of any kind.
//
// http://www.andreybutov.com
//
// ============================================================================

// This may take a bit of memory...
ini_set('memory_limit', '2048M');

if ( !isset($argv[1]) ) 
{
    usage();
}

$root_dir = $argv[1];

if ( !is_dir($root_dir) || !is_readable($root_dir) )
{
    echo "ERROR: '$root_dir' is not a readable directory.\n";
    usage();
}

$files = php_files($root_dir);
$tokenized = array();

if ( count($files) == 0 )
{
    echo "No PHP files found.\n";
    exit;
}

$defined_functions = array();

foreach ( $files as $file )
{
    $tokens = tokenize($file);

    if ( $tokens )
    {
        // We retain the tokenized versions of each file,
        // because we'll be using the tokens later to search
        // for function 'uses', and we don't want to 
        // re-tokenize the same files again.

        $tokenized[$file] = $tokens;

        for ( $i = 0 ; $i < count($tokens) ; ++$i )
        {
            $current_token = $tokens[$i];
            $next_token = safe_arr($tokens, $i + 2, false);

            if ( is_array($current_token) && $next_token && is_array($next_token) )
            {
                if ( safe_arr($current_token, 0) == T_FUNCTION )
                {
                    // Find the 'function' token, then try to grab the 
                    // token that is the name of the function being defined.
                    // 
                    // For every defined function, retain the file and line
                    // location where that function is defined. Since different
                    // modules can define a functions with the same name,
                    // we retain multiple definition locations for each function name.

                    $function_name = safe_arr($next_token, 1, false);
                    $line = safe_arr($next_token, 2, false);

                    if ( $function_name && $line )
                    {
                        $function_name = trim($function_name);
                        if ( $function_name != "" )
                        {
                            $defined_functions[$function_name][] = array('file' => $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 <root_directory>\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 */

Tomáš Votruba
그는 3년 전 댓글을 달았습니다
0

그냥 뛰어난 점, 안드레이! # 39, m 에 있는 코딩 표준 검사기에서 i& 선반가공 이 많은 도움이. https://github.com/Symplify/Symplify/pull/466

Php 프로그래밍 방식 때문에 기능 / 방법은 호출되었을 무중단으로 확실하게 알 수 없다 '는 식으로 함수를 호출할 경우 결코.

유일한 방법은 특정 수작업식 분석.

파프칼그래프 이렇게 할 경우 제대로 기억이 사용할 수 있습니다. # 39, ll 발령합니다 그래프 (이미지) 을 모두 갖춘 it& 좋은 방법 중 한 명이였다. # 39 의 that& 메서드입니다 연결되어 있지 않은 경우, 이 방식은 다른 좋은 예중이 않습니다.

39 의 here& 예: 클로스갈리시스템.프영

이 방법 () '가' 제키워드스토프카테고리스 않습니다.

그나저나 너 그냥 don& 불러키지 할 수도 있습니다 t # 39, 텍스트 파일, 이미지, 즉 파프칼그래프 generate PHP 어레이이며 상술합니다.

2019년 업데이트 +

나는 attaboy 제프리드 에서 [Andrey& # 39 의 오토메이티드] (https://stackoverflow.com/questions/11532/how-can-i-find-unused-functions-in-a-php-project/7133253 # 7133253) 이 붙여넣습니다 코딩 표준 및 켜졌음 sniff.

탐지 매우 간단하면서도 강력한:

모든 방법을 aspt 공적인 기능은 섬메트로트 () '-'

  • $ {} - 모든 방법을 찾아야만 페이징됩니다 아무것도 &gt 섬메트로트 () ',' 단순히 그 함수를 정의하는 보고서 공개 단 한번도 호출됨 -

이 날 수 있도록 지루려면 [끝날거요] (https://github.com/Symplify/Symplify/commit/fa21855694d933716117b2a2db13acac55b86d69) [20+ 방법] (https://github.com/Symplify/Symplify/commit/3f08ed1fb2f22dd6c4a7b46d680adf4ab5a0907d) 나 유지 및 테스트 할 것입니다.

&lt br>;

3 단계를 것들이었다고요

설치처 ECS:

composer require symplify/easy-coding-standard --dev

'설정' 에치오야마라 구성:

# ecs.yaml
services:
    Symplify\CodingStandard\Sniffs\DeadCode\UnusedPublicMethodSniff: ~

명령을 실행합니다.

vendor/bin/ecs check src

39, & # t 좋은 유용한 방법 및 그 제거하시겠습니까 com/go/lrvid4005_ps_kr 보고됨 128077 don& 있습니다.

-

여기에 대한 자세한 내용을 확인할 수 있습니다. &lt ";;; a href = &quot (https://www.tomasvotruba.cz/blog/2019/03/14/remove-dead-public-methdos-from-your-code/) 에서 공개 메서드을 죽은입니다 제거하시겠습니까 &gt code&lt /a>;

k00ni
그는 일 년 전 댓글을 달았습니다
1
  • It 를 통해 간단한 검색하겠습니다 works.* 검증됨 그 출력입니다 설명하는 비사용률 총괄하였습니다. 일부 비고: 'Like' 테스트 '를 추가해야 합니다 / bin / src 폴더 명령을 공급업체별로 ecs 확인란 테스트'. 가짜 포지티브 그것 없이는 얻을 수 있습니다. # 흥분됐나요 Tom& 225, š 보트루바 엔드입니다.
Tomáš Votruba
그는 일 년 전 댓글을 달았습니다
0

39 m, I& 피드백 주셔서 감사합니다, 오히려 작동하잖아 잘!

그 때문에 얻을 수 있는 것처럼 포함하면 거짓값 포지티브, 검사를 위해 국민 메서드을 약간만이라도 호출됨 에서만 테스트 . 실제로 이 문제가 해결된 새로운 버전의 sniff.

아파이크 길이 없다. 알 수 있는 기능, whom&quot 속하는 &quot 있다. 실행하십시오 시스템 (런타임용으로 개발하십시오 바인딩하면 말 함수은 조회) 을 사용해야 합니다.

그러나 리팩토링 도구를 기준으로 그룹화됩니다 정적 프로그램 분석. 하지만 제가 보기에 이들은 어려운 언어, i really like 동적임 입력되었는지 배율입니다. 안전 및 동적 언어가 부족하다는 단점이 유지 관리에 대한 대규모 코드 리팩토링 입력되었는지 주요 소프트웨어, 취급료 진화.

파프 1세 에서 쉽게 파악할 수 있는 기능은 되는 것도 여전히 there& # 39 이라는 분석 - 하지만, 어느 정도의 수작업 있었다.