-1

From php manual:

[...] Static method calls are resolved at compile time. When using an explicit class name the method is already identified completely and no inheritance rules apply. If the call is done by self then self is translated to the current class, that is the class the code belongs to. Here also no inheritance rules apply [...]

..so im looking for a way to emulate the standard oop inheritance with static singleton.

Code explain better:

// Normal inheritance: my goal.
class Foo{
    public function test(){
        echo "Foo->test()\n";
    }
}

class Bar extends Foo{
    public function other_test()
    {
        echo "Bar->other_test()\n";
    }
}


$obj = new Bar();
echo get_class($obj) . "\n";
$obj->test();
$obj->other_test();
/*
 Output:
Bar
Foo->test()
Bar->other_test()
*/


// How i would love to do:
class Foo2{
    public static function test2()
    {
        echo "Foo2::test2()\n";
    }

    // Singleton?
    public static $_instance;
    public static function get_instance()
    {
        if(is_null(self::$_instance))
        {
            self::$_instance = new self();
        }
        return self::$_instance;
    }
}

class Bar2 extends Foo2{
    public static function other_test2()
    {
        echo "Bar2::other_test2()\n";
    }
}

$obj2 = Bar2::get_instance();
echo get_class($obj2) . "\n";
$obj2::test2();
$obj2::other_test2();
/*
 Output:
Foo2
Foo2::test2()
Fatal error: Call to undefined method Foo2::other_test2()
*/

echo "\n-------\n";

// How im doing actually:
interface Foo3{
    public static function get_instance();
}

class Bar3 implements Foo3{
    // Singleton?
    public static $_instance;
    public static function get_instance()
    {
        if(is_null(self::$_instance))
        {
            self::$_instance = new self();
        }
        return self::$_instance;
    }
    public static function test3()
    {
        echo "Bar3::test3()\n";
    }
    public static function other_test3()
    {
        echo "Bar3::other_test3()\n";
    }
}


$obj3 = Bar3::get_instance();
echo get_class($obj3) . "\n";
$obj3::test3();
$obj3::other_test3();
/*
 Output:
Bar3
Foo3::test3()
Bar3::other_test3()
*/

The last 'way' force me to avoid the get_instance and static variables to be placed in the parent class, so I do not consider it as a best solution.. if for some reason my get_instance() function will change in the future, i dont want to edit all classes (inheritance! inheritance! we all want inheritance!)

So, is there a way or a best practices to solve this problem?

p.s: php5.3.2

Strae
  • 18,807
  • 29
  • 92
  • 131
  • 2
    [Don't use Singletons](http://googletesting.blogspot.com/2008/08/by-miko-hevery-so-you-join-new-project.html) – OZ_ Jul 14 '11 at 09:42
  • *(related)* [Who needs Singletons](http://stackoverflow.com/questions/4595964/who-needs-singletons/4596323#4596323) – Gordon Jul 14 '11 at 12:06
  • *(related)* [Static considered harmful](http://kore-nordmann.de/blog/0103_static_considered_harmful.html) – Gordon Jul 14 '11 at 12:06
  • Thanks for the links, i'll take a closer look to my design. – Strae Jul 14 '11 at 13:13

1 Answers1

5

The Singleton pattern in PHP is something like this:

class Singleton {
     private static $instance = null;

     // Constructor is private, so class cannot be instantiazed from outside
     private function __construct() {
     }

     public static function getInstance() {
         if (static::$instance === null) {
              static::$instance = new Singleton();
         }
         return static::$instance;
     }

     public static function test() {
         echo 'Singleton::test()';
     }

     public function __sleep() {
         throw new Exception('Serialization is not alowed.');
     }

     public function __wakeup() {
         throw new Exception('Serialization is not alowed.');
     }

     public function __clone() {
         throw new Exception('Cloning is not alowed.');
     }
}

For you is important that keyword static, then this:

class B extends Singleton {
    public static function test2() {
         echo 'B::test2()';
    }
}

$b = B::getInstance();
B::test();
B::test2();
// Singleton::test()
// B::test()

Is this you looking for?

rath3r
  • 323
  • 1
  • 6
  • 19
Jakub Truneček
  • 8,800
  • 3
  • 20
  • 35
  • Mh yes, i was missing `new static();`. Thanks mate, you made my day! – Strae Jul 14 '11 at 09:42
  • For complete answer is important to say, that late static binding feature comes with PHP 5.3 and more info can be found here: http://php.net/manual/en/language.oop5.late-static-bindings.php. – Jakub Truneček Jul 14 '11 at 09:49
  • @Jakub Truneček Interesting re: late static binding, thanks for opening my eyes to it. – GordyD Jul 14 '11 at 17:37