views:

242

answers:

2

To clarify:

  • no I can't make this pure PHP5
  • yes this code works in PHP 4.3.9.

I don't have any real world experience implementing or supporting PHP4 but I had to recently change my class so it supports both PHP4 and PHP5.

  • Can anyone foresee any possible issues in regards to my implementation of the singleton method used here? I only want one instance of this class.
  • I know I could completely get rid of the __construct method, should I? ( and move the function body of it to the Conf function ).
  • Could I have used self anywhere? I wasn't sure of its PHP4 support.


<?php

class Conf {
    function Conf( $filename ) {
     $this->__construct( $filename );
    }

    function __construct( $filename ) {
     echo $filename;
    }

    function getInstance( $filename ) {
     static $instance = null;
     if ( $instance == null ) {
      $instance = new Conf( $filename );
     }
     return $instance;
    }
}

$x = Conf::getInstance( 'file.xml' );
A: 

Your code is unnecessarily complex. You don't need the __construct method at all if you have the other one. (or vise versa, however, older versions of php don't support __construct)

Also, to implement the singleton pattern properly, the static instance should be class scope, and the constructor should be private.

class Singleton {
    private static $instance;

    private function Singleton(){
        //do stuff
    }

    function getInstance(){
        if(self::$instance == null){
            self::$instance = new Singleton();
        }

        return self::$instance;
    }
}

This article describes how to implement the Singleton Pattern in PHP4, and it's problems.

Malfist
yes I'm aware of the `__construct` deal, I guess I should just kill it entirely.Could you demonstrate how you would do it properly?
meder
also a thing to be aware of is __clone() it can duplicate the object and if you don't want that happening (which shouldn't be allowed in a true singelton pattern) you should override it and return null, or die.
Malfist
@Malfist - your updated code is exactly how I had my PHP5 code. I'm aware of that article, I was just looking for advice for someone who knew exactly the tricks implemented in said article in my context.
meder
The OP asked for PHP4 compatibility.
Justin Johnson
+1  A: 

To get around the unavailability of self in PHP4, you should change your getInstance method to the following:

class Conf {
    function Conf( $filename ) {
     $this->__construct( $filename );
    }

    function getInstance( $filename ) {
     static $instance = null;
     if ( $instance == null ) {
      $class = __CLASS__;
      $instance = new $class( $filename );
     }
     return $instance;
    }

    // Don't forget to block cloning
    function __clone() {
        trigger_error("Cannot clone a singleton", E_USER_WARNING);
    }
}

Edit: Because __CLASS__ will always be the class name of the class in which the function was defined, to support inheritance, you must redefine the getInstance method in every child class.

class Conf2 extends Conf {
    function newMethod() { echo "Do something"; }

    function getInstance( $filename ) {
     static $instance = null;
     if ( $instance == null ) {
      $instance = new self($filename);
     }
     return $instance;
    }
}

It's a drag, yes, but if you use the above method, you can just copy and paste. I believe this is fixed in PHP 5.3 with late static binding, but I haven't installed it yet to confirm.

Justin Johnson
Interesting. So is that `__CLASS__` basically a replacement for `self` since PHP4 can't support `self`?
meder
Yup, `__CLASS__` is a magic constant (http://us2.php.net/manual/en/language.constants.predefined.php).
Justin Johnson