Static class initializer in PHP

后端 未结 8 795
南方客
南方客 2020-12-02 05:12

I have an helper class with some static functions. All the functions in the class require a ‘heavy’ initialization function to run once (as if it were a constructor).

<
相关标签:
8条回答
  • 2020-12-02 05:47

    There is a way to call the init() method once and forbid it's usage, you can turn the function into private initializer and ivoke it after class declaration like this:

    class Example {
        private static function init() {
            // do whatever needed for class initialization
        }
    }
    (static function () {
        static::init();
    })->bindTo(null, Example::class)();
    
    0 讨论(0)
  • 2020-12-02 05:47

    NOTE: This is exactly what OP said they did. (But didn't show code for.) I show the details here, so that you can compare it to the accepted answer. My point is that OP's original instinct was, IMHO, better than the answer he accepted.


    Given how highly upvoted the accepted answer is, I'd like to point out the "naive" answer to one-time initialization of static methods, is hardly more code than that implementation of Singleton -- and has an essential advantage.

    final class MyClass  {
        public static function someMethod1() {
            MyClass::init();
            // whatever
        }
    
        public static function someMethod2() {
            MyClass::init();
            // whatever
        }
    
    
        private static $didInit = false;
    
        private static function init() {
            if (!self::$didInit) {
                self::$didInit = true;
                // one-time init code.
            }
        }
    
        // private, so can't create an instance.
        private function __construct() {
            // Nothing to do - there are no instances.
        }
    }
    

    The advantage of this approach, is that you get to call with the straightforward static function syntax:

    MyClass::someMethod1();
    

    Contrast it to the calls required by the accepted answer:

    MyClass::getInstance->someMethod1();
    

    As a general principle, it is best to pay the coding price once, when you code a class, to keep callers simpler.


    Of all the answers (including this one), I prefer Victor Nicollet's answer. Simple. No extra coding required. No "advanced" coding to understand. (I recommend including FrancescoMM's comment, to make sure "init" will never execute twice.)

    So I could have not bothered to write this answer. But so many people upvoted the accepted answer, that I conclude some people are simply not aware of the obvious, "naive", approach (that I show here). Understand this as a starting point.

    0 讨论(0)
  • 2020-12-02 05:53

    Sounds like you'd be better served by a singleton rather than a bunch of static methods

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

    And then, in usage

    // As opposed to this
    Singleton::someMethod1();
    
    // You'd do this
    Singleton::getInstance()->someMethod1();
    
    0 讨论(0)
  • 2020-12-02 05:56
    // file Foo.php
    class Foo
    {
      static function init() { /* ... */ }
    }
    
    Foo::init();
    

    This way, the initialization happens when the class file is included. You can make sure this only happens when necessary (and only once) by using autoloading.

    0 讨论(0)
  • 2020-12-02 05:57

    Note - the RFC proposing this is still in the draft state.


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

    proposed for PHP 7.x (see https://wiki.php.net/rfc/static_class_constructor )

    0 讨论(0)
  • 2020-12-02 05:58

    Actually, I use a public static method __init__() on my static classes that require initialization (or at least need to execute some code). Then, in my autoloader, when it loads a class it checks is_callable($class, '__init__'). If it is, it calls that method. Quick, simple and effective...

    0 讨论(0)
提交回复
热议问题