Search code examples
phpdesign-patternsstaticclass-design

How to emulate __destruct() in a static class?


I've coded a simple configuration class for my own framework.

There are simple functions like get(), set() or loadFile(). But all functions and variables are static.

And now I want to implement an autosave mechanism. I had the idea to create an instance (in my init() function) whose __destruct() will call the static destruct() function:

<?php

class Config
{
  static private $autoSave;
  static public function get() {} /* set(), save(), load(), etc. */

  static public function init($autoSave)
  {
    self::$autoSave = $autoSave;
    new Config();
  }
  static public function destruct()
  {
    if (self::$autoSave)
      self::save();
  }

  public function __destruct()
  {
    Config::destruct();
  }
}

?>

Are there any better solutions or is my design pattern completely wrong in this case?


Solution

  • Are there any better solutions or is my design pattern completely wrong in this case?

    Destructors are called on objects only, not for static classes.

    Instead you could convert your class from static to regular so you can create an instance of it. Then it will have the destructor. Additionally it makes your code easier to re-use and test.

    Additionally you're able to implement magic methods for __get and __set or ArrayAccess which often is useful for easy data storage and access as for a configuration.

    Alternatively, you can add a destructor object to a static class member to achieve what you're looking for:

    class ConfigDestructor
    {
      public function __destruct()
      {
        Config::destruct();
      }
    }
    
    class Config
    {
      static private $destructorInstance;
      static private $autoSave;
      static public function get() {} /* set(), save(), load(), etc. */
    
      static public function init($autoSave)
      {
        if (null === self::$destructorInstance) 
            self::$destructorInstance = new ConfigDestructor();
    
        self::$autoSave = $autoSave;
      }
      static public function destruct()
      {
        if (self::$autoSave)
          self::save();
      }
    }
    

    Just FYI: You wrote you want to add an auto-save functionality. There is a common gap to fall over for both __destruct() and register_shutdown_function:

    Note: Working directory of the script can change inside the shutdown function under some web servers, e.g. Apache.

    You should specify an absolute path to access the file you want to save into. See as well: PHP file creation/write within destructor.