Инициализатор статического класса в PHP


у меня есть вспомогательный класс с некоторыми статическими функциями. Все функции в классе требуется "тяжелая" функция инициализации один раз (как если бы это был конструктор).

есть хорошая практика для достижения этого?

единственное, о чем я подумал, это позвонить init функция и прерывание ее потока, если он уже запущен один раз (используя статический $initialized var). Проблема в том, что мне нужно вызвать его на каждую из функций класса.

6 73

6 ответов:

похоже, что вам будет лучше служить синглтон, а не куча статических методов

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

и затем, в использовании

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

// You'd do this
Singleton::getInstance()->someMethod1();
// file Foo.php
class Foo
{
  static function init() { /* ... */ }
}

Foo::init();

таким образом, инициализация происходит, когда файл класса входит. Вы можете убедиться, что это происходит только при необходимости (и только один раз) с помощью автоматической загрузки.

на самом деле, я использую публичный статический метод __init__() на моих статических классах, которые требуют инициализации (или, по крайней мере, нужно выполнить некоторый код). Затем, в моем автозагрузчике, когда он загружает класс, он проверяет is_callable($class, '__init__'). Если это так, он вызывает этот метод. Быстро, просто и эффективно...

Если вам не нравится public статический инициализатор, отражение может быть обходной путь.

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

?>

есть способ вызвать init() метод один раз и запретить его использование, вы можете превратить функцию в частный инициализатор и ivoke его после объявления класса следующим образом:

class Example {
    private function init() {
        // do whatever needed for class initialization
    }
}
(function () {
    static::init();
})->bindTo(null, Example::class)();

Примечание - RFC, предлагающий это, все еще находится в состоянии проекта.


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

предлагается для PHP 7.x (см. https://wiki.php.net/rfc/static_class_constructor)