php - Serialized object coming out with internal value references -
this far strangest thing have seen in php, there surely sort of explanation.
using serialize()
storing objects. @ later point, revive them using unserialize()
.
today discovered problem object has been unserialized. picture scenario:
object__product_bundle object ( [collateralvalue] => [collateralgroup] => )
now imagine $obj
instance of object__product_bundle
shown above.
when did:
$obj->collateralvalue = 10;
and checked object variables, shown:
object__product_bundle object ( [collateralvalue] => 10 [collateralgroup] => 10 )
mindboggling!
i spent hour smashing head against table, didn't make sense. when started using var_dump()
on object, before making changes it, saw this:
object(object__product_bundle)#28 (15) { ["collateralvalue"] => &null ["collateralgroup"] => &null }
apparently these properties/variables somehow linked. researched &null
, found this question told me dealing sort of references.
but how?
my object comes serialized string.
now, taking @ serialized string found this:
s:15:"collateralvalue";n;s:15:"collateralgroup";r:15;
what r:15 ?
can issue?
how can problem addressed , come from?
edit
after digging deeper, found culprit.
orientiation:
the objects (as described above) stored property of object, item of shop cart.
class shopcart { public $storage; } $cart->storage[] = new shopcart_item(); class shopcart_item { public $object; }
$object
products (object__product_*
) stored.
upon placing order, aim of being repeated (subscription), entire shopcart
stored database blob.
whenever subscription order scheduled, automated task grabs old shopcart
, generates new order it.
and here found culprit - added properties (collateralvalue
etc.) later during development, there had been stored orders.
now during debugging found php starts creating references, although not understand why.
simply put:
static public function generateorderfromsubscription() { [...] $order = new object__webshop_order(); var_dump($subscription->cart); // <-- no references in here @ $order->cart = serialize($subscription->cart); var_dump($order->cart); // <-- suddenly, here have references }
apparantely, use __sleep()
each object__product_*
- returns variable names (including collateralvalue
, on).
the question becomes then: why php create references, when dealing new properties objects asleep structure has changed in meantime?
very confusing!
edit #2
finally hope.
my __sleep()
function returned hardcoded array of variable names, there ton of others never wanted store in database. approach apparently led current problem described in question.
i still not know why php creates references variables in objects awoken without having variables @ all, variables being returned in __sleep()
.
the sensible solution me, seemed to adapt __sleep()
. this:
public function __sleep(){ $vars=array( 'dbid', 'title', 'articleid', 'price_per_unit', ); if(isset($this->collateralvalue)) $vars[]='collateralvalue'; if(isset($this->collateralgroup)) $vars[]='collateralgroup'; }
this way, __sleep()
not return (any of 2 new) variable names (collateralvalue, collateralgroup) not in use in current object.
well let's analyse serialized string:
s:15:"collateralvalue";n;s:15:"collateralgroup";r:15;
first property (key):
s:15:"collateralvalue"
s
means string15
size of stringcollateralvalue
string value (and if string 15 characters long)
first property (value):
n
n
mean null
second property (key):
s:15:"collateralgroup"
s
means string15
size of stringcollateralgroup
string value (and if string 15 characters long)
second property (value):
r:15
r
means reference15
means 15 value. here 15 value propertycollateralvalue
, means if change value of it changes value ofcollateralgroup
property
for more information see: http://www.phpinternalsbook.com/classes_objects/serialization.html
Comments
Post a Comment