web-dev-qa-db-ja.com

Phpデストラクタ

クラスで__destructを使用する必要があったときの実際の例をいくつか教えてください。

64
danidacar

わかりました。私の最後の答えは明らかに基準に達しなかったので、もう一度試してみましょう。このトピックに関するインターネット上のリソースと例はたくさんあります。他のフレームワークのコードを少し検索して閲覧すると、かなり良い例がいくつか表示されます...

PHPが終了時にリソースを閉じるからといって、リソースが不要になったときに明示的に閉じるのは悪いことではありません(または閉じない方がよい))ことを忘れないでください。 ..それはユースケースに依存します(それは最後まで使用されていますか、それとも早い段階で1つの呼び出しがあり、残りの実行では再び必要とされませんか)...

これで、__destructは、オブジェクトが破棄されるときに呼び出されます。論理的には、オブジェクトが破棄されるとどうなりますか?まあ、それはもはや利用できないことを意味します。それで、リソースが開いている場合、破棄されているときにそれらのリソースを閉じることは意味がないのですか?確かに、平均的なWebページでは、ページが間もなく終了するので、PHPそれらを閉じることは通常、ひどいことではありません。しかし、何らかの理由でスクリプトが長い場合はどうなりますか?次に、リソースリークが発生したので、不要になったときに(またはデストラクタのスコープを検討して、使用できなくなったときに)すべてを閉じてみませんか?

以下は、実際のフレームワークの例です。

  1. リチウムのリチウム\ネット\ソケットクラス
  2. KohanaのMemcachedドライバー
  3. JoomlaのFTP実装
  4. Zend FrameworksのSMTPメールトランスポートクラス
  5. CodeIgniterのTTemplateクラス
  6. ケーキのTidyフィルターヘルパー
  7. symfonyセッションクラスのデストラクタの使用に関するGoogleグループスレッド

興味深いのは、Kohanaがタグを追跡しているため、(単にキャッシュをクリアするのではなく)後で「名前空間」で削除できることです。したがって、デストラクタを使用して、これらの変更をハードストレージにフラッシュします。

CodeIgniterクラスは、デストラクタの出力ストリームにデバッグ出力を追加するという点でも興味深いことをします。これは良いことだとは言いませんが、これはまた別の使用例です...

マスターコントローラでプロセスを長時間実行しているときはいつでも、個人的にデストラクタを使用します。コンストラクターで、pidファイルを確認します。そのファイルが存在する(そしてそのプロセスがまだ実行されている)場合は、例外をスローします。そうでない場合は、現在のプロセスIDでファイルを作成します。次に、デストラクタでそのファイルを削除します。つまり、リソースを解放するだけではなく、それ自体をクリーンアップすることです...

42
ircmaxell

HTMLページを生成する別の便利な使用方法があります

class HTMLgenerator {
  function __construct() {
    echo "<html><body>";
  }
  function __destruct() {
    echo "</body></html>";
  }
}

このクラスを使用すると、

$html = new HTMLgenerator();
echo "Hello, world!";

そして結果は

<html><body>Hello, world!</body></html>
19
Jan Turoň

例えば:

<?php
class Session
{
    protected $data = array();

    public function __construct()
    {
        // load session data from database or file
    }

    // get and set functions

    public function __destruct()
    {
        // store session data in database or file
    }
};

これが、destructを使用する理由です。セッションソースへの読み取りと書き込みを常に防止し、これは最初と最後にのみ行います。

6
VDVLeon
<?php
class Database
{
    private $connection;
    private $cache = array();

    function __construct([$params])
    {
        //Connection here
    }

    //Query
    public function query(Query $Query)
    {
        if($this->is_cached($Query->checksum))
        {
            return $this->get_cache($Query->checksum);
        }
        //...
    }
    public function __destruct()
    {
        unset($this->connection);
        $this->WriteCache();
        unset($this->cache);
        shutdown_log($this,'Destruction Completed');
    }
}
?>

あなたが理解させるべき例があります。

4
RobertPitt

たとえば、ロギングにfopen()によって返されるハンドルを使用する場合、__destruct()を使用して、クラスが破棄されたときにfclose()がリソースで呼び出されるようにすることができます。

4
Jeremy DeGroot

映画情報のjpgファイルを生成するPHPページを作成します。このページでは、jpgに変換する前に、いくつかの情報を収集し、inkscapeを実行してテンプレート(svgファイル)をpngに変換する必要があります。 svgには、ファイルでなければならない他の画像への相対リンクが含まれています。私のページは必要なファイルを一時フォルダにダウンロードし、svgファイルを変換します。最後に、一時フォルダを削除する必要があります。

一時フォルダの削除をデストラクタに入れました。多くの理由が出る前に、ページが予期せず終了し、ページが終了したときにデストラクタが呼び出されることを確信できる唯一の考えです。

お役に立てれば。

4
NawaMan

あなたが正しいです、 __destructは、実行時間の短いphpスクリプトではほとんど不要です。データベース接続、ファイルハンドルなどは、スクリプトの終了時、または場合によっては変数がスコープ外に実行された場合にもっと早く終了します。

私が考えることができる1つの例は、データベースにログを書き込むことです。スクリプトのどこかに作成されるログエントリごとに1つのクエリを実行したくないので、スクリプトが終了するとすべてが1つにデータベースに挿入されるように、ログクラスの__destructに「dbへの書き込み」の部分を記述しました。

別の例:ユーザーにファイルのアップロードを許可する場合、デストラクターは一時ファイルを削除するのに最適な場所です(スクリプトで問題が発生した場合に備えて、少なくともクリーンアップされます)。

しかし、ファイルハンドルの場合でも、それは役に立ちます。オブジェクトにラップされた古いfopenなどの呼び出しを使用するアプリケーションで作業しましたが、大きなファイルツリーでそれらを使用すると、phpがファイルハンドルを使い果たしてしまうため、スクリプトの実行中にクリーンアップを実行するのはいいだけでなく、必要でした。

4
edorian

デストラクタは、カスタムデータベースコネクタ/ラッパーを使用する場合に非常に役立ちます。

コンストラクターでは、接続情報を渡すことができます。 (ファイナライザなどではなく)デストラクタを使用できるので、デストラクタを使用して接続を閉じることができます。これはより便利ですが、確かに便利です。

たとえば、PHPがオブジェクトを明示的に "解放"することを決定した場合(つまり、使用されなくなった場合)、その時点でデストラクタが呼び出されます。これは、私が説明するシナリオでより便利ですガベージコレクターが実行されてファイナライザーを呼び出すのを待っているわけではないためです。

$ 0.02

イアン

4
Ian P

私は大量の「低レベル」オブジェクトにAPCキャッシングを使用します。そして、スクリプトの実行中にAPCとの間の「低レベル」オブジェクトの読み取りと書き込みを処理するcacheCollectionオブジェクトがあります。スクリプトが終了したら、オブジェクトをAPCから削除する必要があるため、cacheCollection __destructメソッドを使用してその機能を実行します。

3
Mark Baker

データベース接続をラップするロギングクラスで__destruct()を使用しました。

<?php

class anyWrap
{
  private $obj,$calls,$log,$hooks;
  function anyWrap($obj, $logfile = NULL)
  {
       if(is_null($logfile))
       {
         $this->log = dirname(__FILE__) . "/../logs/wrapLog.txt";
       }
       $this->hooks = array();
       $this->dbCalls = 0;
       $this->obj = $obj;
  }

   public function __set($attri, $val) {
       $this->obj->$attri = $val;
   }

   public function __get($attri) {      
       return $this->obj->$attri;
   }
  public function __hook($method)
  {
   $this->hooks[] = $method;
  }


   public function __call($name,$args)
   {
       $this->calls++;
       if(in_array($name,$this->hooks))
       {
           file_put_contents($this->log,var_export($args,TRUE)."\r\n",FILE_APPEND);
       }
       return call_user_func_array(array($this->obj,$name),$args);
   }
   //On destruction log diagnostics
   public function __destruct()
   {
        unset($this->dbReal);
        file_put_contents($this->log,$this->calls."\r\n",FILE_APPEND);
   }
}

スクリプトはデータベース呼び出しをフックして準備ステートメントをログに記録し、スクリプトが最後まで実行されると(いつだかわかりません)、データベースへの呼び出しの数を最終的にファイルに記録します。このようにして、特定の関数がデータベースで呼び出された回数を確認し、それに応じて最適化を計画できます。

MySQLデータベースでPHPスクリプトを使用してviewを作成する場合は、dropそのビューを使用する必要がありますスクリプトの最後にあります。そうでない場合は、次回そのスクリプトを実行したときに、データベースに同じような名前のビューが既に存在するため、ビューは作成されません。このために、デストラクタを使用できます。