2010-07-22 15 views
70

Tengo una clase auxiliar con algunas funciones estáticas. Todas las funciones en la clase requieren una función de inicialización 'pesada' para ejecutarse una vez (como si fuera un constructor).Inicializador de clase estático en PHP

¿Existe una buena práctica para lograr esto?

Lo único que pensé fue llamar a una función init, y interrumpir su flujo si ya se ha ejecutado una vez (utilizando una var estática $initialized). El problema es que necesito llamarlo a cada una de las funciones de la clase.

+2

en discusión es el RFC [estática Clase Constructor] (https://wiki.php.net/rfc/static_class_constructor), lo que ofrecería un enfoque alternativo. – bishop

Respuesta

91

Suena como que estaría mejor servido por un producto único en lugar de un montón de métodos estáticos

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

Y luego, en el uso

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

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

Muchas gracias. Probablemente lo esté haciendo de esta manera – user258626

+3

Quiero -1 (pero no lo haré) para constructor privado y 'getInstance()' ... Lo vas a hacer MUY difícil de probar efectivamente ... Al menos hazlo protegido para que tenga opciones ... – ircmaxell

+11

@ircmaxell - usted solo está hablando de problemas con el patrón singleton en sí mismo, realmente. Y el código publicado por alguien en SO no debe considerarse autoritativo, especialmente ejemplos simples que solo tienen el objetivo de ser ilustrativos. Todos los escenarios y situaciones son diferentes –

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

Foo::init(); 

De esta manera, la inicialización sucede cuando el archivo de clase está incluido. Puede asegurarse de que esto solo suceda cuando sea necesario (y solo una vez) mediante la carga automática.

+0

Gracias, esa es una buena solución. pero mi marco incluye todos los ayudantes. ¿Hay alguna forma de hacerlo dentro del archivo incluido? – user258626

+3

No entiendo tu pregunta. Todo lo anterior ocurre en el archivo incluido. –

+1

@VictorNicollet, esto es feo. Su código hace 'init' un método público, y no funcionaría si es privado. ¿No hay una manera más limpia como el inicializador de clase estático java? – Pacerier

51

En realidad, utilizo un método público estático __init__() en mis clases estáticas que requieren inicialización (o al menos necesitan ejecutar algún código). Luego, en mi autocargador, cuando carga una clase, comprueba is_callable($class, '__init__'). Si lo es, llama a ese método. Rápido, simple y efectivo ...

+1

Esa sería mi sugerencia también. Hice lo mismo en el pasado pero lo llamé '__initStatic()'. Se siente como algo que PHP necesita, conociendo Java. – drealecs

+3

Para aquellos de nosotros que usamos el compositor: Encontré esto: https://packagist.org/packages/vladimmi/construct-static – iautomation

+0

@iautomation No lo probé, pero vale la pena colocarlo en una respuesta propia. Es un enfoque directo y moderno. – robsch

-6

Nota: el RFC que propone esto todavía está en el estado de borrador.


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

propuestos para 7.x PHP (ver https://wiki.php.net/rfc/static_class_constructor)

+3

Ese RFC no está fuera de la etapa Draft. No vincules ni proporciones ejemplos de cosas que no hayan sido aprobadas por votación. Confundirá a los nuevos usuarios que no se dan cuenta de que esto aún no se puede utilizar – Machavity

0

Si no te gusta public inicializador estático, la reflexión puede ser una solución.

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

?> 
Cuestiones relacionadas