Search code examples
phpstatic-membersphp4

Using static properties in PHP >= 4.3.0?


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.


Solution

  • 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' ) );
      }
    }