Managing constants easily

  1. Problem
  2. Usage example
  3. Conclusion

Problem

For time to time i have models with constants (basicly status constants) which i use in diferent places and if these constant changes, i have to change mentions of constant in code elsewhere.

getConstants()

For this small problem i am using function getConstants().

public static function getConstants($token,$objectClass) {
	    $tokenLen = strlen($token);

	    $reflection = new ReflectionClass($objectClass); //php built-in 
	    $allConstants = $reflection->getConstants(); //constants as array

	    $tokenConstants = array(); 
	    foreach($allConstants as $name => $val) {
	        if ( substr($name,0,$tokenLen) != $token ) continue;
	        $tokenConstants[ $val ] = $val;
	    }

	    return $tokenConstants;
	}

Usage example

To add this function for every ActiveRecord class extend CActiveRecord

class ActiveRecord extends CActiveRecord {

   	/*
	    Get class constants by token.
	    If you set constants with same prefix, like:
		MY_STATUS_1
		MY_STATUS_2
		MY_STATUS_3

	    , you can get it by calling
	    Class::getConstants('MY');
	    or
	    Class::getConstants('MY_STATUS');
	*/
	public static function getConstants($token,$objectClass) {
	    $tokenLen = strlen($token);

	    $reflection = new ReflectionClass($objectClass); //php built-in 
	    $allConstants = $reflection->getConstants(); //constants as array

	    $tokenConstants = array(); 
	    foreach($allConstants as $name => $val) {
		if ( substr($name,0,$tokenLen) != $token ) continue;
		$tokenConstants[ $val ] = $val;
	    }
	    return $tokenConstants;
	}

}

After that extend new models with ActiveRecord class (not CActiveRecord)

class Media extends ActiveRecord {
     const TYPE_MUSIC = 'music';
     const TYPE_VIDEO = 'video';
     const TYPE_DOC = 'document';

     const STATUS_ACTIVE = 'active';
     const STATUS_REMOVED = 'removed';

    //...
}

and use self::getConstants() in models rules definitions, methods or outside model

class Media extends ActiveRecord {
//..
     public function rules()
     {
           return array(
                   array('type', 'in','range' => self::getConstants('TYPE_',__CLASS__)),
           );
     }
//..
    public static function getStatuses() {
        return self::getConstants('STATUS_',__CLASS__);
    }
    public static function getTypes() {
        return self::getConstants('TYPE_',__CLASS__);
    }

}

Somewhere else

print_r( Media::getConstants('STATUS_','Media') ); 
//or create Media method and use simplified
print_r( Media::getStatuses() ); 

Conclusion

Of course you don't need this if you have model with only two constants. It's more handy if you got tons of them.

Thanks and please leave comment if you have something to say.