PHP Objects and Sessions

December 11, 2008 – 1:24 pm

We stumbled across an interesting issue at work today with the Zend Framework and objects.  We’re working on a filter for a series of reports that carries over from page to page and in the process of development, decided it would be best to move this from page to page within an object.

The error we were receiving while doing so however was “The script tried to execute a method or access a property of an incomplete object.”  Doing a bit of reading up on php.net, it turns out that php serializes an object, then when the session is started, it unserializes the object.  You won’t actually find out there’s a problem until you call a method that is supposed to reside within the object.

The work around for this problem is loading the class into memory before starting your session.  In our situation, we’re running the Zend Framework which start’s the session on it’s own and it seems unsensible to modify the Zend libraries but we still had a problem with an incomplete object.  Thus on my path to finding a way to work around this problem, I created class.cow.php.

class cow {

	var $name;
	var $milk;

	function __construct() {
		$this->name = 'bessie';
		$this->milk = false;
	}
	function moo() {
		echo "mooo!!!!
";
	}

	function gotMilk() {
		if($this->milk == true) {
			return true;
		} else {
			return false;
		}
	}
}

Cow has all of the basics for our needs.  You can tell your cow (all cows are named Bessie btw) to moo, or check if it’s ready to be milked.  For my test, I created 2 files, the first was index1.php which will be used to create our session object, the second is index2.php which we used to load our cow object from memory.

index1.php

name."
";

	$calf->moo();

	if($calf->gotMilk()) {
		echo "We can milk ".$calf->name."
";
	} else {
		echo $calf->name." still doesn't have any milk.
";
	}
	echo "waiting...
";
	$calf->milk = true;
	if($calf->gotMilk()) {
		echo "We can milk ".$calf->name."
";
	} else {
		echo $calf->name." still doesn't have any milk.
";
	}

	$_SESSION['calf']=$calf;
?>

index2.php

name."
";
	$calf->moo();

	if($calf->gotMilk()) {
		echo "We can milk ".$calf->name."
";
	} else {
		echo $calf->name." still doesn't have any milk.
";
	}
	echo "waiting...
";
	$calf->milk = true;
	if($calf->gotMilk()) {
		echo "We can milk ".$calf->name."
";
	} else {
		echo $calf->name." still doesn't have any milk.
";
	}

?>

Both files are mostly identical except for the line $calf = $_SESSION['calf']; in index2.php.

Here is where we get the error: Notice: main() [function.main]: The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition “cow” of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition in index2.php on line 6.

The solution was to load the class, then unserialize and re-serialize our object. The code change to $calf = unserialize(serialize($_SESSION['calf'])); resolves the issue and all works as normal. This was pretty interesting food for thought for me, hopefully you found it to be the same.

  1. 2 Responses to “PHP Objects and Sessions”

  2. That looks pretty hacky. Maybe we should handle this use case in ZF. You can create an issue in our issue tracker for community discussion and/or start a thread on the general list.

    By Wil Sinclair on Dec 11, 2008

  3. I think u should go back to the tried and true method of shuffling hundreds of serialized objects in every single one of your $_GET requests.

    By mrBlaQ on Mar 12, 2009

Post a Comment