1

I am trying to realize my own MVC framework and invented a very nice way to provide definitions of virtual fields and additional relations.

According to some other high-voted post on stackoverflow, this should actually work:

class User extends Model {

  public $hasOne = array('UserSetting');

  public $validate = array();

  public $virtualFields = array(
      'fullname' => function () {
          return $this->fname . ($this->mname ? ' ' . $this->mname : '') . ' ' . $this->lname;
      },
      'official_fullname' => function () {

      }
  );
}

But it doesn't work. It says: Parse error: syntax error, unexpected T_FUNCTION. What am I doing wrong?

PS. talking about this one Can you store a function in a PHP array?

Community
  • 1
  • 1
Liglo App
  • 3,719
  • 4
  • 30
  • 54
  • no, I've checked it. It is 5.3.8. – Liglo App Jun 25 '13 at 17:21
  • 2
    Attribute declarations in a class definition can only be [constant values, not expressions.](http://stackoverflow.com/questions/2671928/workaround-for-basic-syntax-not-being-parsed). And anonymous functions simply aren't primitive types or structures. – mario Jun 25 '13 at 17:23

1 Answers1

3

You must define the methods in the constructor, or some other method, not directly in the class member declaration.

class User extends Model {

  public $hasOne = array('UserSetting');

  public $validate = array();

  public $virtualFields = array();

  public function __construct() {
     $this->virtualFields = array(
        'fullname' => function () {
            return $this->fname . ($this->mname ? ' ' . $this->mname : '') . ' ' . $this->lname;
        },
        'official_fullname' => function () {

        }
    );
  }
}

While that works, PHP's magic method __get() is better suited to this task:

class User extends Model {

  public $hasOne = array('UserSetting');

  public $validate = array();

  public function __get($key) {
     switch ($key) {
       case 'fullname':
           return $this->fname . ($this->mname ? ' ' . $this->mname : '') . ' ' . $this->lname;
       break;

       case 'official_fullname':
         return '';
       break;
    };
  }
}
popthestack
  • 496
  • 3
  • 7
  • It worked. Thank you. It's a little pity, however, because it isn't that clear and elegant as my idea originally was. Also because my constructor is a little bit more complicated and can accept some more arguments, which have to be passed through parent::__construct. But well, it is still pretty cool. Thanks again. I +1-ed it. – Liglo App Jun 25 '13 at 17:28
  • 1
    @BarthZalewski you may consider looking into PHP's magic methods, `__get()`, `__call()` and `__callStatic()`. Those methods are better suited to this sort of thing and will keep your constructor clean. http://php.net/manual/en/language.oop5.magic.php – popthestack Jun 25 '13 at 17:37