Static classes in PHP via abstract keyword? Static classes in PHP via abstract keyword? php php

Static classes in PHP via abstract keyword?


If your class is not meant to define some super-type, it should not be declared as abstract, I'd say.

In your case, I would rather go with a class :

  • That defines __construct and __clone as private methods
    • so the class cannot be instanciated from outside
  • And, this way, your class could create an instance of itself


Now, why use a Singleton, and not only static methods ? I suppose that, at least a couple of reasons can be valid :

  • Using a singleton means using an instance of the class ; makes it easier to transform a non-singleton class to a singleton one : only have to make __construct and __clone private, and add some getInstance method.
  • Using a singleton also means you have access to everything you can use with a normal instance : $this, properties, ...
  • Oh, a third one (not sure about that, but might have its importance) : with PHP < 5.3, you have less possibilities with static methods/data :
    • __callStatic has only been introduced in PHP 5.3
    • There is no __getStatic, __setStatic, ...
    • Same for a couple of other Magic methods !
  • Late Static Binding has only been added with PHP 5.3 ; and not having it often makes it harder, when working with static methods/classes ; especially when using inheritance.


This being said, yes, some code like this :

abstract class MyClass {    protected static $data;    public static function setA($a) {        self::$data['a'] = $a;    }    public static function getA() {        return self::$data['a'];    }}MyClass::setA(20);var_dump(MyClass::getA());

Will work... But it doesn't feel quite natural... and this is a very simple example (see what I said earlier with Late Static Binding, and magic methods).


What you describe is permitted by the PHP language, but it's not the intended usage of an abstract class. I wouldn't use static methods of an abstract class.

Here's the downside of doing that: Another developer could extend your abstract class and then instantiate an object, which is what you want to avoid. Example:

class MyRegistry extends AbstractRegistry { }$reg = new MyRegistry();

True, you only need to worry about this if you're handing off your abstract class to another developer who won't comply with your intended usage, but that's why you would make the class a singleton too. An uncooperative developer can override a private constructor:

class Registry{  private function __construct() { }}class MyRegistry extends Registry{  public function __construct() { } // change private to public}

If you were using this class yourself, you would simply remember not to instantiate the class. Then you wouldn't need either mechanism to prevent it. So since you're designing this to be used by others, you need some way to prevent those people from circumventing your intended usage.

So I offer these two possible alternatives:

  1. Stick with the singleton pattern and make sure the constructor is also final so no one can extend your class and change the constructor to non-private:

    class Registry{  private final function __construct() {  }}
  2. Make your Registry support both static and object usage:

    class Registry{  protected static $reg = null;  public static function getInstance() {    if (self::$reg === null) {      self::$reg = new Registry();    }    return self::$reg;  }}

    Then you can call Registry::getInstance() statically, or you can call new Registry() if you want an object instance.

    Then you can do nifty things like store a new registry instance inside your global registry! :-)

    I implemented this as part of Zend Framework, in Zend_Registry


As other guys said, you cannot instantiate an abstract class. You could use static methods in your class to prevent instantiating, but I'm not really a fan of doing so unless I have a proper reason.

I might be little bit off-topic now, but in your example you said you wanted this for Registry pattern class. What is the reason you don't want to instantiate it? Wouldn't it better to create an instance of Registry for each registry you want to use?

Something like:

class Registry {    private $_objects = array( );    public function set( $name, $object ) {        $this->_objects[ $name ] = $object;    }    public function get( $name ) {        return $this->_objects[ $name ];    }}

I wouldn't even use Singleton in this case.