Chris Tonkinson
Chris Tonkinson

Reputation: 14459

Is it possible to define an anonymous function in class scope?

I'd like to assign anonymous functions to arrays in PHP inside of a class, but I keep stumbling over syntax errors.

class Stuff {
  private $_preference_defaults = array(
    'cookie'    => true,
    'session'   => true,
    'database'  => true,
    'filter'    => function($input) { return true; },
    'sanitizer' => function($input) { return $input; },
  );
};

Will throw an unexpected T_FUNCTION syntax error, and it doesn't matter whether or not the array is static. I got desperate and tried the "old" way of doing it:

class Stuff {
  private $_preference_defaults = array(
    'cookie'    => true,
    'session'   => true,
    'database'  => true,
    'filter'    => create_function('$input', 'return true;'),
    'sanitizer' => create_function('$input', 'return $input;'),
  );
};

And this led to an unexpected '(', expecting ')' syntax error. However, if I define the functions ahead of time, it does work:

class Stuff {
  function _preference_default_filter($input) {
    return true;
  }
  function _preference_default_sanitizer($input) {
    return true;
  }
  private $_preference_defaults = array(
    'cookie'    => true,
    'session'   => true,
    'database'  => true,
    'filter'    => _preference_default_filter,
    'sanitizer' => _preference_default_sanitizer,
  );
};

And then I'm able to call those functions within a class method:

function do_stuff($foo) {
  return $this->{$this->_preference_defaults['filter']}($foo);
}

Not only is this syntactically sour, in my head it wreaks of poor style and I can imagine this sort of trickery causing headaches in the future.

  1. Am I not able to create an anonymous function at class (static) scope? (I'm thinking maybe because a valid Closure object cannot be created in that context?)
  2. Is there a more... PHP... means to the same end? That is to say, is there a "better" way of assigning trivial default callbacks to array values in class scope? The final snippet I provided gets the job done for sure, but I'd prefer a solution that won't leave me asking the optometrist for a stronger prescription.

Upvotes: 1

Views: 338

Answers (3)

xdazz
xdazz

Reputation: 160833

Just set the method name as string.

class Stuff {  
  private $_preference_defaults = array(
    'cookie'    => true,
    'session'   => true,
    'database'  => true,
    'filter'    => '_preference_default_filter',
    'sanitizer' => '_preference_default_sanitizer',
  );

  function _preference_default_filter($input) {
    return true;
  }

  function _preference_default_sanitizer($input) {
    return true;
  }
};

And then call by:

function do_stuff($foo) {
  return $this->{$this->_preference_defaults['filter']}($foo);
}

Or

function do_stuff($foo) {
  return call_user_func(array($this, $this->_preference_defaults['filter']), $foo);
}

Upvotes: 0

Evert
Evert

Reputation: 99533

This indeed will not work. During the, lets say, declaration phase you can generally not do much fancy things.

However.. because your properties are just private, and not static.. simply declare everything in the constructor. Problem solved!

This syntax:

'sanitizer' => _preference_default_sanitizer,

Is really bad.. With E_NOTICE on you will actually find it coverts _preference_default_sanitizer to a string first, which is why this may work.

Upvotes: 1

zerkms
zerkms

Reputation: 254916

Am I not able to create an anonymous function at class (static) scope? (I'm thinking maybe because a valid Closure object cannot be created in that context?)

Yes, because the initial values of class attributes should be known in parsing step, while function call and anonymous function require runtime

Also see here to get the additional details: https://stackoverflow.com/a/9029556/251311

And cannot get your second question :-S

Upvotes: 1

Related Questions