0

I have seens many posts about it but no real answer :(. My problem is the following :

I have the following Bean class :

<?php
class ResultBean {


private $_label;
private $_resultSet;
private $_headerSet;
private $_numRows = 0;
private $_numFields = 0;
private $_empty = TRUE;
private $_dataArray;
private $_headerArray;

public function __construct($label) {
    $v = trim($label);
    $this->_label = empty($label) ? "" : $v;

}

public function setResultSet($value) {

    if(!$value){
        $this->_resultSet = null;
        $this->_empty = TRUE;
    }else{
        $this->_resultSet = $value;
        $this->_empty = FALSE;
    }

    return $this;
}

public function getResultSet() {
    return $this->_resultSet;
}

public function getLabel() {
    return $this->_label;
}

public function setLabel($value) {
    $v = trim($value);
    $this->_label = empty($value) ? null : $v;
    return $this;

}

public function setHeaderSet($value) {
    $this->_headerSet = !$value ? null : $value;
    return $this;   
}

public function getHeaderSet() {
    return $this->_headerSet;
}

public function setNumRows($value) {
    $this->_numRows = $value;
    return $this;
}

public function getNumRows() {
    return $this->_numRows;
}

public function setNumFields($value) {
    $this->_numFields = $value;
    return $this;
}

public function getNumFields() {
    return $this->_numFields;
}

public function setDataArray($value) {
    $this->_dataArray = $value;
    return $this;
}

public function getDataArray() {
    return $this->_dataArray;
}

public function setHeaderArray($value) {
    $this->_headerArray = $value;
    return $this;   
}

public function getHeaderArray() {
    return $this->_headerArray;
}


public function getEmpty() {
    return $this->_empty;
}

public function __get($propertyName) {
    $method = 'get' . ucfirst($propertyName);
    if (!method_exists($this, $method)) {
        $method = 'is' . ucfirst($propertyName);
        if(!method_exists($this, $method)) {
            throw new Exception('Invalid read property ' . $propertyName . ' in ' . get_class($this) . ' class.');
        }
    }
    return $this->$method;
}

public function __isset($propertyName) {
    try {
        $_value = $this->__get($propertyName);
        return !empty($_value);
    } catch (Exception $e) {
        /* if a property isn't readable it isn't set*/
        return false;
    }
}

public function __set($propertyName, $value) {
    $method = 'set' . ucfirst($propertyName);
    if ('mapper' == $method || !method_exists($this, $method)) {
        throw new Exception('Invalid write property ' . $propertyName . ' in ' . get_class($this) . ' class.');
    }
    return $this->$method($value);
}



}
?>

In my index.php, I instantiate two beans :

$peopleBean = new ResultBean("Participants");
$countryBean = new ResultBean("Countries");

and would like to use them as following :

$beanArray[0] = $peopleBean;
$beanArray[1] = $countryBean;


for($i = 0; $i < 2; $i++){

    $resultArray = array();
    $bean = $beanArray[$i];

    echo "bean label :" . $bean->label . " <br/>";
    etc.

I get the following error message when loading my page :

Fatal error: Uncaught exception 'Exception' with message 'Invalid read property getLabel in ResultBean class.' in path/resultBean.php:103

Stack trace: #0 path/resultBean.php(106): ResultBean->__get('getLabel') #1 path/index.php(123): ResultBean->__get('label') #2 {main} thrown in path/resultBean.php on line 103

From all the pages I have read, it is not possible to use the java-style class-casting $bean = (ResultBean) $beanArray[$i].

How can I fix this ? Thank you =)

NOTE : I load the classes using an override of the __autoload() function and it works fine.

NOTE2 : I do make calls (outside of the array) like $peopleBean->numRows = *smthing*and it also seems to work.

Floran Gmehlin
  • 824
  • 1
  • 11
  • 34
  • @skwee which return are you mentioning ? In the getMethods of the bean ? – Floran Gmehlin Jun 01 '13 at 20:31
  • just curious: why are you using setters and getters if you are using magic PHP __get and __set methods? how does this make any sense? – fsw Jun 01 '13 at 20:35
  • @fsw: Syntactic sugar. Also it allows you to transparently switch a property from "dumb" to "smart" without breaking client code (although this is not a very strong argument because you could simply decide to never expose dumb properties in the first place). – Jon Jun 01 '13 at 20:38
  • @Jon I think this was the historical use of setters and getters. With __set and __get you can change your property from "dumb" to "smart" without them. Some PHP programming schools recommend using setters and getters because this way caller sees clearly that he is calling a method and not getting a property. But if in your final code you are using $class->label instead of $class->getLabel() I really don't see any point of this. – fsw Jun 01 '13 at 20:51
  • @fsw: You cannot do that cleanly with *just* magic methods -- where is the implementation going to go? Do you want `__get` to become a 200-line `switch`? Also, this way allows you to define `getX`/`setX` in a *derived* class and it will work without you having to touch the base class code. And finally, the syntax argument is IMHO bordering on religious so let's not take it up. – Jon Jun 01 '13 at 20:55
  • @Jon, haha, I know property vs setter can be religious :) It's your code. I am just saying it is pretty awkward to use both approaches at once. You can use setters but why aren't you simple using $class->getProperty()? I think that when you mix this approaches the way you did you have semantic disadvantages of both, execution is a bit slower and it is errogenous (as we just seen). You can check for example second answer here http://stackoverflow.com/questions/4478661/getter-and-setter – fsw Jun 01 '13 at 21:14
  • @fsw: Sure, your points are valid. Personally I use this technique only if `__get` and `__set` is in a base class; just saying that there are a couple of things going for it as well. – Jon Jun 01 '13 at 21:23

1 Answers1

6

Your __get implementation is wrong.

Instead of this:

return $this->$method;

You want this:

return $this->$method();

or this:

return call_user_func(array($this, $method));

As it stands, the code correctly detects that you have a getLabel method but then it tries to read a getLabel property, so __get is called again, does not find a getGetLabel method and throws.

Two additional tips:

  1. Use foreach instead of for.
  2. You don't need to cast objects to anything in PHP; just call the methods.
Jon
  • 428,835
  • 81
  • 738
  • 806