PHP の realpath の挙動

これにハマっていました。

PHP の realpath、相対パスから実際のパスに直してくれる関数です。Classic ASP では Server.MapPath というのがありましたが、realpath では実在するもののみ返す性質があります。

さて、今回、正体不明な現象があったので調査しました。以下のように数か所に realpath を置き、いったい「何」がおきているのか調査します。

<?php
echo 'Normal:'.realpath('').'<br>';
$cls = new stab();
$cls->main();

class stab {
  function __construct() {
    echo 'In constructor:'.realpath('').'<br>';
  }
  function main() {
    echo 'In class method:'.realpath('').'<br>';
  }
  function __destruct() {
    echo 'In destructor:'.realpath('').'<br>';
  }
}

realpath('') で現在の絶対パスを返してくれるわけですが、想定ではすべて同じものが返ってほしいです。ところが、上記のようにクラスインスタンス内では、ある場所だけ違うものが返されます。

その答えはデストラクタ。インスタンスが無くなって初期値がプログラムフォルダになっていることが考えられます。

Normal:C:\inetpub\sites\wwwroot
In constructor:C:\inetpub\sites\wwwroot
In class method:C:\inetpub\sites\wwwroot
In destructor:C:\Program Files (x86)\PHP\v7.1

デストラクタ内で使うときは、コンストラクタで予め親パスを変数に退避させておいて、realpath 使用時はくっつけてあげるのがよいでしょう。

Qiita で公開したら返信をいただきました。スクリプトの終了時かつクラス終了時の挙動ということで理解しました。インスタンス終了時に unset で明示したら正常な応答を示しました。変数は終了時に unset しましょう。