Hello All,
I think I have traced the most frequent most frustrating critical error I
experience during development. Often when using DTO and ActionForm objects,
I encounter corrupted values that then crash my application and shred the
response from the server so that nothing displays in my browser.
The problem seems to be rooted in the way PHP handles pass by reference when
it comes to scalar values. Obviously pass by reference is integral to the
success of studs. And thus, pass by reference is embedded everywhere.
My example will use the BeanUtils class. I often use the BeanUtils class to
copy properties from a DTO object returned from a service to a Form object
defined in my action. The properties usually map 1:1 between the DTO and
Form objects. My DTO and Form objects typically have getters that return
scalar values such as integers. As you know, the BeanUtils::copyProperty
method describes the $orig object, performs a series of gets on the $orig
object and stores them in a temporary array by reference...
[BeanUtils] Line 110: $properties[$name] =&
PropertyUtils::getSimpleProperty($bean, $name);
After the describe method, it then calls the populate method with loops
through the temporary array and invokes the BeanUtils::setProperty method
for each property, this method passes the value of $properties[$name] by
reference.
In setProperty, the value of $properties[$name], now $value is passed into
the MethodUtils::invokeMethod method via an array wrapper...
[BeanUtils] Line 245: MethodUtils::invokeMethod($target, $writeMethod,
array(&$value));
At this point the $value becomes corrupt and tends to cause a crash...
eventually.
I've seen this primarily affect integers. I was wondering if you have
experience similar behavior. I am running PHP 4.3.10-15 on a debian
installation.
If there is no way to avoid this issue, would it be appropriate to introduce
an Integer or Number object to the project? Pass by reference on objects
doesn't seem to have this problem.
Ok, please pardon the long over explanatory post. I have attached sample
code below my signature that will reproduce this behavior on my machine.
Regards,
Ryan
=========================================
class DTO {
var $integer;
function getInteger() {
return $this->integer;
}
function setInteger($int) {
$this->integer = $int;
}
}
$dto = new DTO();
$dto->setInteger(1);
$value =& $dto->getInteger();
var_dump(array(&$value));
echo " <---- note the integral sign, should say 'int'";
echo "<hr />";
echo "<hr />";
$dto = new DTO();
$dto->setInteger(1);
$value =& $dto->getInteger();
var_dump($dto);
echo " <---- note the integral sign, should say 'int'";
echo "<hr />";
echo "<hr />";
class DTO2 {
var $integer;
function getInteger() {
//call (int) cast function to return strings and integers.
return (int) $this->integer;
}
function setInteger($int) {
$this->integer = $int;
}
}
$dto = new DTO2();
$dto->setInteger(1);
$value =& $dto->getInteger();
var_dump($dto);
echo " <---- note 'int' not corrupted.";
echo "<hr />";
echo "<hr />";
$dto = new DTO2();
$dto->setInteger(1);
$value =& $dto->getInteger();
var_dump(array(&$value));
echo " <---- note integral sign again... back to same problem.";
echo "<hr />";
|