views:

305

answers:

2

Disclaimer: Yes, I am forced to support PHP 4.3.0. I know it's dead. No I can't upgrade it, because I'm dealing with multiple servers some of which I don't have su access.

Well, since I can't use self:: since it's PHP5 specific, how should I go about implementing statics in a PHP4 class? So far from my research it seems that I can at least use the static keyword except only in a function context, I've seen another method that uses $_GLOBALS but I don't think I'll be using that.

Just so we're on the same page I need to access these PHP5 statics in 4:

public static $_monthTable = array(
     31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
public static $_yearTable = array(
     1970 => 0,            1960 => -315619200);

So far, I've come up with my own function that basically sets a static variable if one isn't found, and I hardcode all my static properties into it. However, I'm not entirely sure how I can reference those statics within anther method in the same class, assuming it isn't being instantiated and no constructor is fired, meaning I can't use $this.

class DateClass {

    function statics( $name = null ) {

        static $statics = array();

        if ( count( $statics ) == 0 ) {
            $statics['months'] = array(
                'Jan', 'Feb'
            );
        }

        if ( $name != null && array_key_exists($name, $statics ) ) {
            return $statics[$name];
        }
    }

};

var_dump( DateClass::statics('months') );

Question #1: Is this feasible? Should I try using a different method?

Question #2: How would I reference the statics from a method in the same class? I tried __CLASS__::statics but I think __CLASS__ is just a string so I'm not really invoking a method.

Note: I'll be implementing this into a framework which will be used on Apache2+/IIS6+, PHP4.3.0 to PHP 5.2, OSX/Linux/Windows.

+3  A: 

Answering your first question, I think your solution is good. I would extend it so variables could also be set and unset. I would also "prime" the static $statics differently, the value of unset variables defaults to null.

<?php
class DateClass {
  function statics( $name, $value=null, $unset=null ) {
    static $statics;
    // better way to "prime" $statics, it's null by default
    if ( !$statics ) {
      $statics = array( "months" => array( "Jan", "Feb" ) );
    }
    if ( $value )
      $statics[ $name ] = $value;
    if ( $unset )
      unset( $statics[ $name ] );
    // don't worry about checking for existence
    // values of unset variables and array keys always are null
    // that's what you should return
    return $statics[ $name ];
  }
}

Regarding your second question, you can use DateClass::statics() anywhere, even inside other methods (static or not) of DateClass. PHP4 also allows you to call DateClass::statics() as instance method even though you shouldn't do that. (It is also possible to call instance methods statically, as long as there is a $this in the outer scope. That's not pretty and you should definitely not do that ;-)

If you really want the call to DateClass to be more dynamic, you can use call_user_func, it's just a little more verbose.

<?php
class DateClass {
  function statics( ... ) { ... }
  function anotherStaticFunc() {
    var_dump( DateClass::statics( 'months' ) );
    // using __CLASS__ and call_user_func
    var_dump(
      call_user_func( array( __CLASS__, 'statics' ), 'months' )
    );
  }
  function instanceMethod() {
    var_dump( $this->statics( 'months' ) );
  }
}
fresch
+1  A: 

It's generally a bad idea to emulate language features. Since PHP 4 doesn't support static properties, I wouldn't recommend that you try something clever to make it appear as-if. I'd say that the most natural thing is to use global variables. Basically, that's what a static property is anyway - It's just namespaced. So use a namespacing-convention, to minimise the risk of nameclashes and you'll essentially have the same thing. Eg. instead of:

class Foo {
  static $ninja = 42;
}

You can use

$GLOBALS['foo_ninja'] = 42;
troelskn