web-dev-qa-db-fra.com

Destructeurs Php

Veuillez me donner des exemples concrets lorsque vous avez dû utiliser __destruct dans vos cours.

64
danidacar

Ok, puisque ma dernière réponse n'a apparemment pas atteint le but, permettez-moi de réessayer. Il existe de nombreuses ressources et exemples sur Internet pour ce sujet. Faire un peu de recherche et parcourir le code d'autres frameworks et vous verrez de très bons exemples ...

N'oubliez pas que le simple fait que PHP fermera les ressources à la fin pour vous ne signifie pas qu'il est mauvais de les fermer explicitement lorsque vous n'en avez plus besoin (ou bien de ne pas les fermer). .. Cela dépend du cas d'utilisation (est-il utilisé jusqu'à la fin, ou y a-t-il un appel tôt et qui n'est plus nécessaire pour le reste de l'exécution) ...

Maintenant, nous savons que __destruct est appelé lorsque l'objet est détruit. Logiquement, que se passe-t-il si l'objet est détruit? Eh bien, cela signifie qu'il n'est plus disponible. Donc, s'il a des ressources ouvertes, cela n'a-t-il pas de sens de fermer ces ressources pendant leur destruction? Bien sûr, dans la page Web moyenne, la page va se terminer peu de temps après, donc laisser PHP les fermer n'est généralement pas terrible. Cependant, que se passe-t-il si pour une raison quelconque le script est long- Alors vous avez une fuite de ressources. Alors pourquoi ne pas tout fermer quand vous n'en avez plus besoin (ou en considérant l'étendue du destructeur, quand il n'est plus disponible)?

Voici quelques exemples dans des cadres du monde réel:

  1. Lithium\net\Socket classe de lithium
  2. Pilote Memcached de Kohana
  3. Implémentation FTP de Joomla
  4. Classe de transport de messagerie SMTP de Zend Frameworks
  5. Classe TTemplate de CodeIgniter
  6. n assistant de filtre bien rangé pour le gâtea
  7. n fil Google-Groupes sur l'utilisation de destructeurs pour la classe de session Symfony

La chose intéressante est que Kohana garde une trace des balises, afin qu'il puisse les supprimer par "namespace" plus tard (au lieu de simplement vider le cache). Il utilise donc le destructeur pour vider ces modifications du stockage dur.

La classe CodeIgniter fait également quelque chose d'intéressant en ce qu'elle ajoute la sortie de débogage au flux de sortie dans le destructeur. Je ne dis pas que c'est bon, mais c'est un exemple d'une autre utilisation encore ...

J'utilise personnellement des destructeurs chaque fois que j'ai des processus longs sur mon contrôleur maître. Dans le constructeur, je recherche un fichier pid. Si ce fichier existe (et que son processus est toujours en cours d'exécution), je lève une exception. Sinon, je crée un fichier avec l'ID de processus actuel. Ensuite, dans le destructeur, je supprime ce fichier. Il s'agit donc davantage de nettoyer après lui-même que de simplement libérer des ressources ...

42
ircmaxell

Il existe une autre utilisation pratique pour générer une page HTML

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

Avec cette classe, vous pouvez écrire

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

Et le résultat est

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

Par exemple:

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

C'est un bon pourquoi utiliser destruct. Vous empêchez tout le temps de lire et d'écrire dans une source de session et cela uniquement au début et à la fin.

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

theres un exemple qui devrait vous faire comprendre.

4
RobertPitt

Si vous utilisez des poignées renvoyées par fopen() par exemple, la journalisation, vous pouvez utiliser __destruct() pour vous assurer que fclose() est appelé sur nos ressources lorsque votre classe est détruite.

4
Jeremy DeGroot

Je crée une page php qui va générer un fichier jpg d'informations sur le film. Cette page devra rassembler quelques informations et exécuter inkscape pour convertir le modèle (un fichier svg) en png avant de le convertir en jpg. Le svg contient des liens relatifs vers une autre image qui doit être un fichier. Donc, ma page télécharge les fichiers nécessaires dans un dossier temporaire, convertissez le fichier svg. À la fin, le dossier temporaire doit être supprimé.

J'ai mis la suppression de dossier temporaire dans le destructeur. Avant qu'il puisse y avoir plusieurs raisons, la page se termine de manière inattendue et la seule chose dont je peux être sûr est que le destructeur sera appelé lors de la sortie de la page.

J'espère que cela t'aides.

4
NawaMan

Vous avez raison, __destruct est principalement inutile pour les scripts PHP courts. Les connexions à la base de données, les descripteurs de fichiers, etc. se ferment à la sortie du script ou parfois même plus tôt si les variables sont hors de portée.

Un exemple auquel je peux penser est l'écriture de journaux dans la base de données. Puisque nous ne voulions pas déclencher une requête par entrée de journal qui est créée quelque part dans le script, nous avons écrit la partie "écrire dans la base de données" dans la __destruct de la classe de journalisation, donc lorsque le script se termine, tout est inséré dans la base de données en une seule.

Un autre exemple: si vous autorisez un utilisateur à télécharger des fichiers, le destructeur est parfois un bon endroit pour supprimer le fichier temporaire (au cas où quelque chose se passe mal dans le script, il serait au moins nettoyé)

Mais même pour les descripteurs de fichiers, cela peut être utile. J'ai travaillé sur une application qui utilisait les anciens appels fopen etc. enveloppés dans des objets et lorsque vous les utilisiez sur de grands filetrees, php manquerait de descripteurs de fichiers tôt ou tard, donc le nettoyage pendant que le script était en cours d'exécution était non seulement agréable mais nécessaire .

4
edorian

Un destructeur est extrêmement utile si vous utilisez un connecteur/wrapper de base de données personnalisé.

Dans le constructeur, vous pouvez transmettre les informations de connexion. Parce que vous pouvez utiliser un destructeur (plutôt qu'un finaliseur, etc.), vous pouvez compter sur cela pour fermer la connexion pour vous. C'est plus pratique, mais c'est certainement utile.

Par exemple, lorsque PHP décide de "libérer" explicitement l'objet (c'est-à-dire qu'il n'est plus utilisé), il appellera le destructeur à ce moment-là. Ceci est plus utile dans le scénario que je décris car vous n'attendez pas que le garbage collector s'exécute et appelle le finaliseur.

0,02 $

Ian

4
Ian P

J'utilise la mise en cache APC pour un grand nombre d'objets de "bas niveau", qui autrement utiliseraient une mémoire excessive; et j'ai un objet cacheCollection qui gère la lecture et l'écriture de ces objets "bas niveau" vers et depuis APC pendant l'exécution du script. Lorsque le script se termine, les objets doivent être effacés d'APC, donc j'utilise la méthode cacheCollection __destruct pour exécuter cette fonction.

3
Mark Baker

J'ai utilisé __destruct() dans une classe de journalisation qui a encapsulé une connexion à la base de données:

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

Le script se connecte aux appels de la base de données et enregistre les instructions de préparation, puis lorsque le script est terminé (je ne sais pas toujours quand), il enregistre enfin le nombre d'appels à la base de données dans le fichier. De cette façon, je peux voir combien de fois certaines fonctions ont été appelées dans la base de données et planifier mon optimisation en conséquence.

Si vous créez une vue à l'aide d'un script PHP dans une base de données MySQL, vous devez drop cette vue à la fin du script. Dans le cas contraire, la prochaine fois que ce script sera exécuté, la vue ne sera pas créée, car il existe déjà une vue de nom similaire dans la base de données. Pour cela, vous pouvez utiliser le destructeur.

1