PHPプロジェクトでの未使用関数の見つけ方

開発者として、クリーンで効率的なコードベースを維持することは、プロジェクトの長期的な健康にとって重要です。一般的な問題の一つは、未使用関数の存在で、これがコードを膨張させ、技術的負債を助長します。このブログ記事では、PHPプロジェクト内で未使用関数を効果的に特定する方法を、組み込みのPHP機能とカスタムスクリプトの両方を使用して探ります。

未使用関数を特定する重要性

未使用関数は、以下の原因となります。

  • リソースの無駄:余分なコードがスペースを消費し、アプリケーションの動作を遅らせる可能性があります。
  • 複雑性:多くのコードは、プロジェクトをナビゲートしにくくし、維持が困難になります。
  • セキュリティリスク:未使用のコードが、発見されていない脆弱性を知らずに露呈させるかもしれません。

これらの関数を見つけて削除することは、最適なコード管理にとって不可欠です。

PHP機能を使用して未使用関数を探す

PHPには、コードベースを分析するために利用できるいくつかの組み込み機能があります。特に注目すべき機能は以下の通りです。

  • リフレクション:クラス、メソッド、関数についての情報を反映し、使用法を理解するための能力を提供します。
  • token_get_all()を使ったトークン化:この関数は、PHPコードをトークンに解析し、コードの構造を特定しやすくします。

ただし、これらの機能だけに頼ると完全な視点は得られない可能性があるため、カスタムスクリプティングが役立ちます。

手軽で迅速な解決策:カスタムPHPスクリプト

最近の調査とコミュニティのフィードバックに基づいて、PHPプロジェクト内で未使用関数を見つけるためのカスタムスクリプトを提供します。このスクリプトは、プロジェクトディレクトリをスキャンし、関数の定義とその参照を特定し、結果を読みやすい形式で表示します。

ステップ1:環境の設定

  • PHP環境がセットアップされていることを確認してください。
  • プロジェクトディレクトリのパスが正確であることを確認してください。
  • 以下のスクリプトを新しい.phpファイルにコピーします。

ステップ2:PHPスクリプト

<?php
$functions = array();
$path = "/path/to/my/php/project"; // このパスをプロジェクトディレクトリに更新してください。
define_dir($path, $functions);
reference_dir($path, $functions);
echo "<table>";
echo "<tr><th>名前</th><th>定義済み</th><th>参照済み</th></tr>";
foreach ($functions as $name => $value) {
    echo "<tr><td>" . htmlentities($name) . "</td>";
    echo "<td>" . (isset($value[0]) ? count($value[0]) : "-") . "</td>";
    echo "<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) != ".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) && $token[0] == T_FUNCTION) {
            $i++;
            $token = $tokens[$i + 1]; // 次の関数名を取得
            if (is_array($token) && $token[0] == 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) != ".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) && $token[0] == T_STRING) {
            if ($tokens[$i + 1][0] == "(") { // 関数呼び出しを確認
                $functions[$token[1]][1][] = array($path, $token[2]); // 関数参照を保存
            }
        }
    }
}
?>

ステップ3:スクリプトの実行

  1. スクリプト内の$path変数をあなたのPHPプロジェクトディレクトリを指すように更新してください。
  2. コマンドラインまたはWebサーバーを通じてスクリプトを実行します。
  3. 出力は、すべての関数、定義されている回数、および参照されている回数を表示するHTMLテーブルになります。

結論

このカスタムスクリプトは、PHPプロジェクト内で未使用関数を追跡する効率的な方法を提供します。PHPの組み込み機能であるリフレクションやtoken_get_all()は強力ですが、特定のニーズに合わせたスクリプトを使用することで、未使用関数の特定および管理のプロセスがスムーズになります。ベストプラクティスとして、このスクリプトを定期的に実行して、コードベースをクリーンで効率的に保つことをお勧めします。

プロジェクトを整頓することで、そのパフォーマンスを向上させるだけでなく、長期的にはメンテナンスや協力を容易にします。