kzen.dev
  • Вопросы
  • Метки
  • Пользователи
Оповещения
Вознаграждения
Регистрация
После регистрации, сможете получать уведомления об ответах и комментариях на Ваши вопросы.
Вход
Если у Вас уже есть аккаунт, войдите чтобы проверить новые уведомления.
Тут будут вознаграждения за добавленные вопросы, ответы и комментарий.
Дополнительно
Источник
Редактировать
Stacey Richards
Stacey Richards
Вопрос

Как найти неиспользуемые функции в проекте PHP

Как найти неиспользуемые функции в проекте PHP?

Существуют ли функции или API, встроенные в PHP, которые позволят мне проанализировать мою кодовую базу - например, Reflection, token_get_all()?

Достаточно ли функциональны эти API, чтобы мне не пришлось прибегать к помощи сторонних инструментов для проведения такого рода анализа?

58 2008-08-14T19:08:21+00:00 9
 Timothy
Timothy
Редактировал вопрос 24-го июля 2017 в 2:37
Программирование
php
 Gordon
Gordon
25-го января 2011 в 9:50
2011-01-25T09:50:51+00:00
Дополнительно
Источник
Редактировать
#8415286

Вы можете попробовать Себастьян Бергманн'ы мертвый код детектора:

&ГТ; phpdcd - это мертвый детектор код (ДКД) для PHP-кода. Она сканирует проекта PHP для всех заявленных функций и методов и сообщает, что как-то "мертвый код", что не позвонил хотя бы раз.

Источник: https://github.com/sebastianbergmann/phpdcd

Обратите внимание, что это'ы статический анализатор кода, поэтому он может давать ложные срабатывания для методов, которые только называются динамически, например, он не может обнаружить не$Foo = 'ФН'; $и Foo();

Вы можете установить его с помощью груши:

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.

Дополнительные инструменты:

  • https://phpqa.io/

Примечание: согласно репозитория обратите внимание, этот проект больше не поддерживается и его репозиторий только для архивных целей. Так что ваш пробег может варьироваться.

 TravisCarden
TravisCarden
Редактировал ответ 9-го октября 2018 в 11:43
GitHub - sebastianbergmann/phpdcd: Dead Code Detector (DCD) for PHP code.
Dead Code Detector (DCD) for PHP code. Contribute to sebastianbergmann/phpdcd development by creating an account on GitHub.
github.com
33
0
Решение / Ответ
Stacey Richards
Stacey Richards
18-го августа 2008 в 1:47
2008-08-18T13:47:41+00:00
Дополнительно
Источник
Редактировать
#8415280

Спасибо Грегу и Дэйву за отзывы. Это было не совсем то, что я искал, но я решил потратить немного времени на исследование и пришел к этому быстрому и грязному решению:

<?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]);
            }
        }
    }
?>

Возможно, я потрачу еще немного времени на это, чтобы быстро найти файлы и номера строк определений функций и ссылок; эта информация собирается, просто не отображается.

Stacey Richards
Stacey Richards
Редактировал ответ 6-го января 2009 в 3:33
24
0
Tim Cullen
Tim Cullen
2-го апреля 2012 в 3:43
2012-04-02T15:43:35+00:00
Дополнительно
Источник
Редактировать
#8415289

Этот бит Баш скриптов может помочь:

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

В основном это рекурсивно Грэпс текущего каталога для определения функций, передает просмотров в awk, который формирует команду выполнить следующие действия:

  • печатать имя функции
  • рекурсивный grep для этого снова
  • трубопроводы, что вывод команды grep -v, чтобы отфильтровать функции определения, так как для удержания вызова функции
  • трубы это выход в туалет -л, который печатает число строк

Эта команда отправляется на исполнение в bash и выход grepped на 0, что будет указывать на 0 вызовы функции.

Обратите внимание, что это не решить проблему выше calebbrown СИТЕС, поэтому там могут быть некоторые ложные срабатывания на выходе.

18
0
Andrey Butov
Andrey Butov
20-го августа 2011 в 4:57
2011-08-20T16:57:40+00:00
Дополнительно
Источник
Редактировать
#8415288

Использование: find_unused_functions.php &амп;ЛТ;корень&амп;ГТ;

Примечание: это подход быстрый-N-грязные к проблеме. Этот скрипт выполняет только лексический передавать файлы, и не уважает ситуациях, где различные модули определяют идентично именованных функций или методов. Если вы используете IDE для разработки PHP, она может предложить более комплексные решения.

Требует 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 */
7
0
 Till
Till
29-го марта 2009 в 2:12
2009-03-29T02:12:51+00:00
Дополнительно
Источник
Редактировать
#8415282

Если я правильно помню, для этого можно использовать phpCallGraph. Он сгенерирует для вас красивый график (изображение) со всеми задействованными методами. Если метод не связан ни с одним другим, это хороший признак того, что метод осиротел.

Вот пример: classGallerySystem.png

Метод getKeywordSetOfCategories() осиротел.

Кстати, необязательно брать изображение - phpCallGraph может также генерировать текстовый файл, или PHP массив, и т.д..

3
0
 webbiedave
webbiedave
1-го июня 2010 в 12:38
2010-06-01T00:38:22+00:00
Дополнительно
Источник
Редактировать
#8415283

Поскольку функции/методы PHP могут вызываться динамически, не существует программного способа узнать с уверенностью, что функция никогда не будет вызвана.

Единственный надежный способ - это ручной анализ.

3
0
Tom&#225;š Votruba
Tomáš Votruba
16-го марта 2019 в 11:55
2019-03-16T11:55:43+00:00
Дополнительно
Источник
Редактировать
#8415290

2019+ обновление

Я inspied по Андрей'ы answer и превратили это в стандарт кодирования нюхать.

Обнаружение очень простой, но мощный:

  • поиск всех методов государственной функции метода someMethod()`
  • значит, найти все вызовы метода ${ничего}-&ГТ;метода someMethod()
  • и просто отчеты о тех общественных функций, которые никогда не называли

Он помог мне снять за 20+ методы я бы для поддержания и тест.

&ЛТ;БР&ГТ;

3 шага, чтобы найти их

Установите ФОВ:

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

Настройка ФОВ.в YAML конфигурации:

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

Выполните команду:

vendor/bin/ecs check src

Увидеть сообщили методов и удалить те, которые вы не'т хорошо полезные 👍


Вы можете прочитать больше об этом здесь: &ЛТ;а href="https://www.tomasvotruba.cz/blog/2019/03/14/remove-dead-public-methdos-from-your-code/">удалить мертвые публичных методов из кода&ЛТ;/а&ГТ;

1
0
manuel aldana
manuel aldana
1-го июня 2010 в 9:19
2010-06-01T21:19:14+00:00
Дополнительно
Источник
Редактировать
#8415285

насколько мне известно, нет никакой возможности. Знать, какие функции "не относятся к кому" Вы должны выполнить систему (выполнения позднего связывания подстановки функция).

Но инструменты рефакторинга на основе статического анализа кода. Мне очень нравится динамически типизированные языки, но на мой взгляд их трудно масштабировать. Отсутствие безопасного рефакторинга в больших кодовых баз и динамически типизированных языков, является основным препятствием для ремонтопригодность и управляемость эволюции программного обеспечения.

-1
0
 symcbean
symcbean
1-го июня 2010 в 8:59
2010-06-01T08:59:49+00:00
Дополнительно
Источник
Редактировать
#8415284

phpxref будет определить, где функции вызываются из которых облегчило бы анализ - но там's по-прежнему определенное количество ручной работы.

 m.s.
m.s.
Редактировал ответ 19-го октября 2015 в 12:12
-1
0
Похожие сообщества 22
phpGeeks
phpGeeks
4 757 пользователей
Best PHP chat @phpGeeksJunior - новичкам @golangGeeks - гошка @jobGeeks - вакансии(250000 р/мес) @dbGeeks - базы данных @ebanoePhp - канал о PHP @laravel_pro - Laravel @jsChat - JS @moscowProgers - Москва Реклама: https://vk.cc/cbJtVV ДР - 28.03.2016
Открыть telegram
PHP — вакансии, поиск работы и аналитика
PHP — вакансии, поиск работы и аналитика
4 157 пользователей
Публикуем вакансии и запросы на поиск работы по направлению PHP, Laravel, Symfony, Yii etc. Full/par-time, remote и т.д. ПРАВИЛА: https://t.me/php_jobs/45345 Флудильня: @phpimhorus More: @javascript_jobs, @nodejs_jobs, @devops_jobs, @sql_jobs
Открыть telegram
phpGeeksJunior
phpGeeksJunior
2 980 пользователей
Группа для новичков. Не стесняйтесь задавать вопросы по php. Не флудить!!!! Реклама: https://vk.cc/cbJtVV Правила и полезные ссылки https://github.com/phpgeeks-club/faq Бест от пхпгикс https://t.me/best_of_phpgeeks
Открыть telegram
#php chat
#php chat
2 827 пользователей
Группа для новичков и бывалых. Не стесняйтесь задавать вопросы по php. Уважаем друг друга Администрация: @faramanx Сотрудничество: @adskiy_tony
Открыть telegram
PHP
PHP
2 761 пользователей
Группа про современный PHP. Обсуждаем ООП, TDD, BDD, DDD, SOLID, GRASP и прочие крутые базворды правила чата: https://gist.github.com/fesor/6c8b162ac1e2fe4d6f227341ec8eaadf Группа PHP для новичков @phpGeeksJunior Вакансии: https://t.me/fordev
Открыть telegram
PHP.Zone Chat - Сообщество PHP-разработчиков
PHP.Zone Chat - Сообщество PHP-разработчиков
1 688 пользователей
Чат PHP разработчиков от проекта https://php.zone Общаемся по делу. Для оффтопика отдельный чат @php_zone_offtop
Открыть telegram
Добавить вопрос
Категории
Все
Технологий
Культура / Отдых
Жизнь / Искусство
Наука
Профессии
Бизнес
Пользователи
Все
Новые
Популярные
1
Денис Васьков
Зарегистрирован 15 часов назад
2
Dima Patrushev
Зарегистрирован 2 дня назад
3
sirojidddin otaboyev
Зарегистрирован 1 неделю назад
4
Елена Гайдамамакинат
Зарегистрирован 1 неделю назад
5
Иван Степанюк
Зарегистрирован 1 неделю назад
ID
KO
RU
© kzen.dev 2023
Источник
stackoverflow.com
под лицензией cc by-sa 3.0 с атрибуцией