【PHP】 関数・クラスが定義されているソースファイル名を取得する

更新日:2024/02/27

個人的なプロジェクトでよくあることだが、機能を付け足していくうちにファイルが増えていき、関数が行方不明になることがあります。
IDEを使っているので探すのは簡単なはずだけど、なぜか見つからなかったりします。

そんなとき、関数の定義されているファイルをプログラムの実行中に特定できたら、場合によっては便利な気がするので調べてみました。

 

ReflectionFunctionAbstractクラスのgetFileNameメソッドを使用

関数が定義されているファイル名を取得するにはReflectionFunctionクラスのgetFileNameメソッドを使用します。

function testFunc(  )  { };

$fnames = ((new ReflectionFunction( 'testFunc' ))->getFileName();

とても簡単でした。

getStartLine()とgetEndLine()を使用すると、関数が何行目から始まって、何行目で終わるかを取得できます。

function testFunc(  )  { };

$rf = new ReflectionFunction( 'testFunc' );
echo $rf->getName() . 'は、' . $rf->getFileName() . 'の'
         . $rf->getStartLine() . '行目から' . $rf->getEndLine() . 'までです';

getName()は、関数名を取得しています。

 

クラスの場合

クラスの情報を得るときは、ReflectionClassクラスを使用します。


class extendsClass {
    public function extendsFunc(){

    }
}
class testClass  extends extendsClass{

    public function func(){

    }
};

$rf = new ReflectionClass( 'testClass' );

echo  $rf->getName() . 'は、' . $rf->getFileName() . 'の'
     . $rf->getStartLine() . '行目から' . $rf->getEndLine() . 'までです';

上のコードは、クラスを文字列で指定していますが、インスタンスでも大丈夫です。

$rf = new ReflectionClass( new testClass() );

メソッド内で$thisを使用することもできます。


class testClass  extends extendsClass{

    public function func(){
        $rf = new ReflectionClass( $this );
        echo $rf->getName() ;
    }
};

getParentClass()を使用すると、extendsされた親クラスのReflectionClassを取得できます。
次のコードは、親クラスの名前を出力しています。

$rf->getParentClass()->getName();

getMethods()を使用すると、親クラスを含めたメソッドの一覧を取得できます。

var_dump( $rf->getMethods() );

結果は次のようになります。

array(2) {
  [0]=>
  object(ReflectionMethod)#2 (2) {
    ["name"]=>string(4) "func"
    ["class"]=>string(9) "testClass"
  }
  [1]=>
  object(ReflectionMethod)#3 (2) {
    ["name"]=>string(11) "extendsFunc"
    ["class"]=>string(12) "extendsClass"
  }
}

getMethod()を使用すると、ReflectionMethodクラスを取得できます。

下のコードは、ReflectionMethodクラスを使用してメソッドの情報を出力しています。
getDeclaringClass()は、メソッドが所属するクラスのReflectionFunctionクラスを取得しています。


$funcRf = $rf->getMethod('func');
echo $funcRf->getName().'は、' . $funcRf->getDeclaringClass()->getName() . 'クラスの'
     .  $funcRf->getStartLine() . '行目から' . $funcRf->getEndLine() . 'までです';

$extendsFuncRf = $rf->getMethod('extendsFunc');
echo $extendsFuncRf->getName().'は、' . $extendsFuncRf->getDeclaringClass()->getName() . 'クラスの'
     .  $extendsFuncRf->getStartLine() . '行目から' . $extendsFuncRf->getEndLine() . 'までです';

 

クラス・関数のソースファイル名を取得するコード

クラスと関数それぞれのソースファイル名を取得する方法がわかったので、一つの関数にまとめてみます。

function getFunctionInfo( $functionName , $className = null ) {
    try{
        $is_class = $className !== null;
        $rf = $is_class
            ? (new ReflectionClass($className))->getMethod($functionName)
            : new ReflectionFunction($functionName);

        $name = $is_class
            ? $rf->getDeclaringClass()->getName() . '::'. $functionName
            : ($rf->getClosureScopeClass() === null ?  '' // ①
                        : $rf->getClosureScopeClass()->getName() . '::') . $rf->getName();

        $start_line =  $rf->getStartLine() ;
        $fname = $rf->getFileName();

        return $name  . ' [' . $fname .'(' . $start_line . ')]';
    }catch (Exception $e){
        return '例外エラー: '.  $e->getMessage();
    }
}

引数の$functionNameは、関数名だけでなく無名関数も受け付けます。
その処理がで、getClosureScopeClass()の結果がnullでなければ、クラス内で作成されたことになります。

この関数を、次のコードで実行してみます。

class extendsClass {
    public function extendsFunc(){}
}
class testClass  extends extendsClass{
    public function func(){
        return function (){};
    }
}
echo getFunctionInfo('func','testClass')."\n";
echo getFunctionInfo('extendsFunc','testClass')."\n";
echo getFunctionInfo('getFunctionInfo')."\n";

$a = new testClass();
echo getFunctionInfo($a->func())."\n";

ファイル名はC:\test.phpのとき、結果は次のようになります。

testClass::func [C:\test.php(8)]
extendsClass::extendsFunc [C:\test.php(5)]
getFunctionInfo [C:\test.php(9)]
testClass::{closure} [C:\test.php(33)]

 

リフレクションとは

ここで紹介しているReflectionClassクラスやReflectionFunctionクラスなどは、ReflectionFunctionAbstractクラスを親に持ちます。
ReflectionFunctionAbstractはリフレクション機能を実現させることを目的としたクラスです。

リフレクションとは、オブジェクトやプロパティについての情報(アクセス制限や名前・型など)の取得および変更、取得した情報からの関数実行などを動的におこなう機能を指します。

関数が定義されているファイル名の取得も、リフレクションの一つですね。

更新日:2024/02/27

書いた人(管理人):けーちゃん

スポンサーリンク

記事の内容について

null

こんにちはけーちゃんです。
説明するのって難しいですね。

「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php

 

このサイトは、リンクフリーです。大歓迎です。