musicnothing
musicnothing

Reputation: 3985

PHP - Anonymous Function as Static Array Element

I'm attempting to make an achievement system for a memorization website ("You memorized 50 cards," etc.), and the method I'm trying to use is an array of anonymous functions:

class AchievementController extends Controller
{
    private static $rules = array(
        'card'=>array(
            1=>function() {
                //do check for achievement
            },
            2=>function() {
                //do check for achievement
            }
         ),
         'set'=>array(
            5=>function() {
                //do check for achievement
            },
            6=>function() {
                //do check for achievement
            },
         )
    );
    //...
}

The idea is that certain types of rules for achievements will be checked at certain times, i.e. when you learn a new card, the card subset will be checked. I had hoped to use a foreach loop like this:

foreach(self::$rules[$type] as $rule)
{
    $rule();
}

However, when I try to declare the $rules array, I get this error:

PHP Parse error: syntax error, unexpected 'function' (T_FUNCTION) in /.../controllers/achievement.php on line 24

If I declare $rules inside a function (NOT static), it works just fine. I can't put it inside a constructor, because this class is being used statically, so no constructor will be called.

My question is, is it possible for me to do this in a static array? Or ought I just to do something else?

(Extra question: Is there a better way than this to do achievements?)

Upvotes: 2

Views: 1436

Answers (3)

Mike Brant
Mike Brant

Reputation: 71384

It is not possible to do in a static array like this. The property declaration must be constant as noted in PHP docs here (http://www.php.net/manual/en/language.oop5.properties.php).

This declaration may include an initialization, but this initialization must be a constant value--that is, it must be able to be evaluated at compile time and must not depend on run-time information in order to be evaluated.

What you could perhaps do is have the function names defined statically, i.e.:

private static $rules = array(
    'card'=>array('function1', 'function2'),
    'set'=>array('function3', 'function4')
);

And then you could simply use these references to call NAMED method calls:

public static function function1 () {
     // some logic
}

public static function function2 () {
    // some logic
}

However, this whole thing seems very clunky. Seems to me you might want to have an achievement interface which defines certain methods (i.e. checkAchievements) and then have concrete implementing classes for cards, sets, etc.

Upvotes: 1

sybear
sybear

Reputation: 7784

No way you can pre-declare them (anonymous functions) in a class. You can do it inside a class method though:

class AchievementController extends Controller {
  public static $rules = array() ;

  public static function setup(){
    self::$rules = array(
      0 => function(){
        echo "One-statement array" ;
      }) ;

    //OR


    self::$rules[0] = function(){
      //Echo "ASD" ;
    } ;
    self::$rules[1] = function(){
      //Echo "ASD2" ;
    }
  }
}

AchievementController::setup() ; //Just calling pseudo-constructor for static class

Upvotes: 4

bwoebi
bwoebi

Reputation: 23777

Current PHP grammar only supports primitive types, arrays and compile time constants in predefined class variables. For an exact list of what it supports see also http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_language_parser.y#945.

What you can do is maybe declaring your class' methods as private and the use __callStatic as a wrapper. If the static property is then not yet set, set them. And then call the class method.

Or just make some setup at the beginning. like @Jari suggested.

Upvotes: 1

Related Questions