2010-07-22 12 views
70

J'ai une classe d'aide avec quelques fonctions statiques. Toutes les fonctions de la classe nécessitent une fonction d'initialisation «lourde» pour s'exécuter une fois (comme s'il s'agissait d'un constructeur).Initialiseur de classe statique en PHP

Existe-t-il une bonne pratique pour y parvenir?

La seule chose que je pensais était d'appeler une fonction init, et briser son flux si elle a déjà exécuté une fois (en utilisant un $initialized var statique). Le problème est que je dois l'appeler sur chacune des fonctions de la classe.

+2

En discussion est le [Constructor classe statique] (https://wiki.php.net/rfc/static_class_constructor) RFC, qui offrirait une approche alternative. – bishop

Répondre

91

On dirait que vous seriez mieux servis par un singleton plutôt qu'un tas de méthodes statiques

class Singleton 
{ 
    /** 
    * 
    * @var Singleton 
    */ 
    private static $instance; 

    private function __construct() 
    { 
    // Your "heavy" initialization stuff here 
    } 

    public static function getInstance() 
    { 
    if (is_null(self::$instance)) 
    { 
     self::$instance = new self(); 
    } 
    return self::$instance; 
    } 

    public function someMethod1() 
    { 
    // whatever 
    } 

    public function someMethod2() 
    { 
    // whatever 
    } 
} 

Et puis, dans l'usage

// As opposed to this 
Singleton::someMethod1(); 

// You'd do this 
Singleton::getInstance()->someMethod1(); 
+0

Merci beaucoup. Je vais probablement faire de cette façon – user258626

+3

Je veux -1 (mais je ne le ferai pas) pour le constructeur privé et 'getInstance()' ... Vous allez le rendre TRÈS difficile à tester efficacement ... Au moins le faire protégé de sorte que vous avez des options ... – ircmaxell

+11

@ircmaxell - vous parlez juste des problèmes avec le modèle de singleton lui-même, vraiment. Et le code affiché par n'importe qui sur le SO ne devrait pas être considéré comme faisant autorité - en particulier des exemples simples qui sont seulement destinés à être illustratifs. Les scénarios et situations de chacun sont différents –

80
// file Foo.php 
class Foo 
{ 
    static function init() { /* ... */ } 
} 

Foo::init(); 

De cette façon, l'initialisation se produit lorsque le fichier de classe est inclus. Vous pouvez vous assurer que cela ne se produit que si nécessaire (et une seule fois) en utilisant le chargement automatique.

+0

Merci, c'est une bonne solution. mais mon cadre comprend tous les assistants. est-il un moyen de le faire à l'intérieur du fichier inclus? – user258626

+3

Je ne comprends pas votre question. Tout ce qui précède arrive dans le fichier inclus. –

+1

@VictorNicollet, c'est moche. Votre code fait 'init' une méthode publique, et cela ne fonctionnerait pas si c'était privé. N'y a-t-il pas une manière plus propre comme l'initialiseur de classe statique java? – Pacerier

51

En fait, j'utiliser une méthode statique publique __init__() sur mes classes statiques qui nécessitent l'initialisation (ou au moins besoin d'exécuter du code). Ensuite, dans mon autochargeur, lorsqu'il charge une classe, il vérifie is_callable($class, '__init__'). Si c'est le cas, il appelle cette méthode. Rapide, simple et efficace ...

+1

Ce serait aussi ma suggestion. J'ai fait de même par le passé mais je l'ai appelé '__initStatic()'. Cela ressemble à une chose dont PHP a besoin, sachant Java. – drealecs

+3

Pour ceux d'entre nous qui utilisent composer: J'ai trouvé ceci: https://packagist.org/packages/vladimmi/construct-static – iautomation

+0

@iautomation Je n'ai pas essayé mais cela vaut la peine d'être placé dans une réponse! C'est une approche simple et moderne. – robsch

-6

Remarque - la RFC proposant cette option est toujours à l'état de brouillon.


class Singleton 
{ 
    private static function __static() 
    { 
     //... 
    } 
    //... 
} 

proposé pour 7.x PHP (voir https://wiki.php.net/rfc/static_class_constructor)

+3

Cette RFC n'est pas en dehors de l'étape Draft. Veuillez ne pas lier ou donner des exemples à des choses qui n'ont pas été approuvées par un vote. Il va confondre les nouveaux utilisateurs qui ne réalisent pas que ce n'est pas encore utilisable – Machavity

0

Si vous ne l'aimez pas public statique initialiseur, la réflexion peut être une solution de contournement.

<?php 

class LanguageUtility 
{ 
    public static function initializeClass($class) 
    { 
     try 
     { 
      // Get a static method named 'initialize'. If not found, 
      // ReflectionMethod() will throw a ReflectionException. 
      $ref = new \ReflectionMethod($class, 'initialize'); 

      // The 'initialize' method is probably 'private'. 
      // Make it accessible before calling 'invoke'. 
      // Note that 'setAccessible' is not available 
      // before PHP version 5.3.2. 
      $ref->setAccessible(true); 

      // Execute the 'initialize' method. 
      $ref->invoke(null); 
     } 
     catch (Exception $e) 
     { 
     } 
    } 
} 

class MyClass 
{ 
    private static function initialize() 
    { 
    } 
} 

LanguageUtility::initializeClass('MyClass'); 

?> 
Questions connexes