Page 1 of 2

OOP session strategy brainfart

Posted: Tue Sep 16, 2003 7:48 am
by Heavy
I am building my first object oriented PHP application and this is my first OOP attempt ever - any language.

I am working on the login page and have this at the top:

Code: Select all

<?php
//other includes and objects off topic are excluded in this post.
	session_start();
	require "constants.php";
	require constant('CLASSES_INCLUDE_PATH') . "/class.db.php";
	require "appclasses/class.user.php";
	
	//Big problem:
	$objDB = new DB();

	if (!isset($_SESSION['objUser'])){
		$_SESSION['objUser'] = new user($objDB);
	}
	//:melborp giB

	header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
// here goes the rest. blablablablabla...

?>
I ran into a wall when typing the "new user();" part.
I will use sessions and I will place objUser in the session. I guess that could be done exactly the way I did above.

The user object initialisation takes a parameter $objDB which is refered to like this in the user class initialisation:

Code: Select all

<?php
class user{
	var $objDB;
	var $intLoggedInID;

	function user(&$objDB){
		$this->objDB = & $objDB; // Here, the $objDB has to be initialised before.
	}
	
	function attemptLogin($strUsername, $strPassword){
		$arrUser = $this->objDB->queryGetFirstRow('SELECT ID FROM Users where strUsername=''' . $strUsername  . ''' and strPasswordHash=PASSWORD(''' . $strPassword . ''') ');
		if ($arrUser){
			$this->intLoggedInID = $arrUser['ID'];
		}else{
			return false;
		}
	}
}

?>
It seems to me that if I go with this design, this script will run fine but next time, it will not be recreated since it is in the session. This probably leaves the reference $_SESSION['objUser']->objDB broken.

This gets me wondering:

1: Should I store the session data without storing the object?
2: Should I also have the $objDB stored in the session?

If I go the "1" way, I will lose the structure I believe I am designing right now. I don't want that.
If I go the "2" way, memory won't be used effectively.

Which way would an experienced PHP-OOP-developer go?
Am I completely off track?

Posted: Tue Sep 16, 2003 10:08 am
by Heavy
I have been browsing the web to get a grip of this. The article that is closest to my problem is in the manual. Yet, it does not seem to recommend what I should do.

If I am not adviced otherwise, I guess I will have to declare my objects like this:

This must go into session:
* objects that store data in session

This must go into session because of reference:
* objects that do not store data, but are connected to session stored objects by reference.

...in other words, those two objects mentioned in the first post, $_SESSION['objUser'] and $objDB.

I guess I will have to put $objDB in session as well. ...and all other objects that are referenced to in an object that is stored in session?

I don't like such a solution but it might be the best way.
As commented here:
don't worry about resources, it's the way it has to work.

Posted: Wed Sep 17, 2003 2:55 am
by Heavy
Maybe this should have gone into the advanced section instead... Noone has replied yet and this topic is kind of surrounded with questions of another level :roll:

I am getting sort of comfortable with the thought of having all the connected objects in the session.

But before I get too committed to such practise, it would feel better if one of you good guys had commented this, and maybe saved me some time if this desicion is completely wrong or there is a better way to go.

I will post my solution later to end this topic anyway.

Posted: Wed Sep 17, 2003 5:12 am
by twigletmac
I've moved this to Advanced Theory and Design, so hopefully some of the OOP gurus can give you some pointers.

Mac

Posted: Wed Sep 17, 2003 2:42 pm
by ryanwpatterson
I am somewhat of a newbie to PHP, but am very experienced with OO. In the short time I have been using PHP, I have done what you're trying to do without any issues. I believe you need to include the definition of the class in every page that accesses the object, even when it's stored in the session. So, you should be OK doing something like this:

MyClasses.inc
----------------
class Foo
{
$var bar;

function SetBar($p_bar)
{
$this->bar = $p_bar;
}
function GetBar()
{
return $this->bar;
}
}

Now,

somefile.php
---------------
require_once('MyClasses.inc');

objFoo = new Foo();
objFoo = $_SESSION['foo'];
objFoo->SetValue('someval');
echo objFoo->GetValue();

...


In short, my design decision, coming from OO, would be to store the object in the session as opposed to storing simple data types. As long as the class definition is available for the page, everything should work fine.

Posted: Wed Sep 17, 2003 3:34 pm
by Heavy
OK, but it is a huge difference between

Code: Select all

<?php
 function SetBar($p_bar)
{
$this->bar = $p_bar;
} 
?>
and

Code: Select all

<?php
 function SetBar(& $p_bar)
{
$this->bar = & $p_bar;
} 
?>
I am initialising the class like this:

Code: Select all

<?php
//the class:
class user{
   var $objDB;

   function user(&$objDB){
      $this->objDB = & $objDB;
   }
} 

// the code:
 $objDB = new DB();
 $_SESSION['objUser'] = new user($objDB);
 
?>
The little ampersand & tells PHP to pass that variable by reference. Since you're familiar with OO I figure you know what that means as well.

Thus, this gives me access to the very same data:

Code: Select all

<?php
echo $objDB->strVendor;
echo $_SESSION['objUser']->objDB->strVendor;
?>
That is what I want to achieve and also what is my problem.
Since $objDB is outside the $_SESSION and dies when script ends, the $_SESSION['objUser']->objDB is dead on next page view.

So. I wonder how to do it a better way than making $objDB a session var as well...

Right now I've settled for putting it in the $_SESSION, but it is not too late to talk me out of doing so.


***********
Someone who really KNOWS english, please tell me if it is "aswell" or "as well". Thanks!

Posted: Wed Sep 17, 2003 8:35 pm
by McGruff
References in php are succintly explained in the Eclipse read me file - download the package here: http://www.students.cs.uu.nl/people/voo ... /index.php

..and the classes themselves are worth reading through :)

What is $objDB and just how many mb does it take up?

Posted: Thu Sep 18, 2003 3:39 am
by Heavy
Thank you for the link.
I read it's home page, I downloaded it and I read some of the documentation and the USAGE TIPS part of the README.

I will read some of the classes also, but haven't yet.

The $objDB is a small object for accessing the db. Today this db is only mysql.
It doesn't really store anything that is valuable between pages (and it shouldn't). Therefore, I don't think it should go into session.

Here is the core of my problem.

I don't need $objDB in session.
$_SESSION['objUser'] needs to be in session, because it holds different things you'd expect from a session implementation of user data, IE: $_SESSION['objUser']->intUserID.

$objDB;
is the same object as
$_SESSION['objUser']->objDB

$_SESSION['objUser'] is alive across pages, and $objDB is not.

On next page processing the $_SESSION['objUser']->objDB reference will be broken, since $objDB was something that existed in the last script.

This leaves me two ways to go:
1:
$_SESSION['objUser'] must check whether $_SESSION['objUser']->objDB exists on every page that it should be used, before it can be used. and create it otherwise.
This doesn't make sence since there are other objects using the $objDB as well, and if the reference $_SESSION['objUser']->objDB has to be reconnected, so must all the other session objects' objDB members. Forcing me to kind of start it all over again.

2:
objDB is be rewritten so it is a session var: $_SESSION['objDB'].
Then all $_SESSION['objDB'] is the same as $_SESSION['objUser']->objDB by reference. This would provide a constant object structure.
One drawback is that so many objects need to be in session, wasting memory...
On the other hand, objects not in memory has to be recreated on every page load.

So, none of the ways seem optimal but I am going for the second one as long as noone persuades me otherwise.
Of course, I could do this without posting my thoughts here, but I have a feeling I am overdoing it. So I hope someone will confirm my ideas or strike them down in favour of better ones.

$_SESSION['ObjDB'] is to be used in several objects, IE:
$_SESSION['objUser']->objDB
$_SESSION['objCourse']->objDB
$_SESSION['objBasket']->objDB
$_SESSION['objTest']->objDB

Just examples. Only the first one exists today.
This is why I connect to it by reference. To save memory...

Posted: Thu Sep 18, 2003 6:50 am
by McGruff
The best ways of combining objects is something that I'm still working out myself. That said, here are a few thoughts.

A minor redesign could maybe remove the $objDB property from the other objects, if you can do that? $objDB query results could be set as properties instead of the entire $objDB object.

The whole idea of "persistent" objects isn't one I've experimented with - and possibly goes against the grain of a scripting language like php? An alternative to storing whole objects in sessions might be just to store their properties in sessions as arrays. Add some new setter fns and you can re-initialise the objects on each page load in their previous state. That's pretty much the same as what is happening with the objects-as-session-vars method so I'm not sure if it would sidestep your problems. Also, could it be that you would run into some kind of chicken-and-egg referencing issue if the other objects are intertwined?

More questions than answers I'm afraid :?

Posted: Thu Sep 18, 2003 8:09 am
by Heavy
If I write objects that are designed to have script lifetime and not session lifetime, I have to write a system or something to connect these objects to the session. Then I can load fewer objects into a script and have their data sleeping in the session until I populate them. (I guess this is what you were talking about, McGruff. Let's call this the McGruff method in further discussion.)
Hmmm... This actually sounds good... I wonder how I would implement it...
It would also require me to save their data back into session when every page is done. (bad, if it can't be done automatically by reference or something)
It also require me to do this procedure for every page, since the objects themselves are not in the session.


Such workaround is not needed when objects actually are in the session.

I have settled for this:
All objects that store data and the objects they are connected to by reference are in the session. This saves some time restoring blah blah etc at top of script, but it also forces me to include all classes at every script that does something.

Anyways, the all-objects-in-session "solution" is a shorter way to goal right now. I hope I am not completely wrong with this philosophy.

Posted: Thu Sep 18, 2003 5:28 pm
by Heavy
Well... I had some issues with the chicken at first, but I came down to conclusion that the $_SESSION god created the chicken so that the chicken could start reproducing. Of course, good god $_SESSION also created a rooster to mate with her.

Here it is, the McGruff method. Not pretty but it works. Test the script somewhere and you'll se for yourself:

Code: Select all

<?php
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");

function populateObjVarsByRef(& $object, $strObjName){
	$arrVarNames = array_keys(get_class_vars(get_class($object)));

	if (isset($_SESSION[$strObjName])){
		//object data exists in session. Connect references to every var except objects.
		foreach ($arrVarNames as $strVarName){
			if (substr($strVarName,0,3) != 'obj'){
				$object->$strVarName  = & $_SESSION[$strObjName][$strVarName];
			}
		}
		return TRUE;
	}else{
		foreach ($arrVarNames as $strVarName){
			if (substr($strVarName,0,3) != 'obj'){
				// this initialises any var to be 0.
				// If this is not the purpose, set is after call to this function
				// in the class constructor.
				$_SESSION[$strObjName][$strVarName] = 0;
				$object->$strVarName = & $_SESSION[$strObjName][$strVarName];
//				Important rows. Any object data has reference to session data.
//				Thus, it is saved to session when execution ends, and can be 
//				fetched back into object on next invokation, thanks to this function. 
			}
		}
		return FALSE;
	}
}
/*
I couldn't find any function that retrieves the name of the object, so I pass it as a parameter.
In the constructor, the object var probably doesn't even exist, so this is a little problem.
Feels a little ugly.
*/
class foo{
	var $fooVar;
	function foo($strObjName){
		if (!populateObjVarsByRef($this, $strObjName)){
			$this->fooVar = 10;
		}
	}
	
	function decrementFooVar(){
		$this->fooVar--;
	}
}

class bar{
	var $objFoo;

	function bar($strObjName, & $objFoo){
		if (!populateObjVarsByRef($this, $strObjName)){
		}
		$this->objFoo = & $objFoo;
	}
	
	function incrementFooVar(){
		$this->objFoo->fooVar++;
	}
}

session_start();
if ($_GET['clear'] == 1){
	$_SESSION=array();
}

$objFoo = new foo('objFoo');
$objBar1 = new bar('objBar1', $objFoo);
$objBar2 = new bar('objBar2', $objFoo);

if (isset($_GET['incrVarName'])){
	${$_GET['incrVarName']}->incrementFooVar();
}

if (isset($_GET['decrement'])){
	$objFoo->decrementFooVar();
}

echo '<pre>';
echo "<a href="{$_SERVER['SCRIPT_NAME']}?incrVarName=objBar1">load again - \$objBar1->incrementFooVar()</a><br>";
echo "<a href="{$_SERVER['SCRIPT_NAME']}?incrVarName=objBar2">load again - \$objBar1->incrementFooVar()</a><br>";
echo "<a href="{$_SERVER['SCRIPT_NAME']}?decrement=1">load again - \$objFoo->decrementFooVar()</a><br>";
echo "<a href="{$_SERVER['SCRIPT_NAME']}?clear=1">load again - but empty session</a><br><br>";

echo '$objFoo->fooVar: ' . $objFoo->fooVar . "<br>";
echo '$objBar1->objFoo->fooVar: ' . $objBar1->objFoo->fooVar . "<br>";
echo '$objBar2->objFoo->fooVar: ' . $objBar2->objFoo->fooVar . "<br>";
echo '<br>Session data:<br>';
print_r($_SESSION);
echo "</pre>";
?>
One thing remains.
What method is most efficient? (I'm not asking anyone to benchmark it...)
Both are ugly.
This one require less organisation.
The other one is a little cleaner.

I like this one more right now. Please have your opinion thrown at me...

Posted: Thu Sep 18, 2003 8:40 pm
by McGruff
I changed to my own coding style so I could work with it more easily. Camel back var names confused me!

Can you use your populateObjVarsByRef fn in a constructor? Since the class hasn't been instantiated, and all properties set, get_class_vars() and get_class() have nothing to return (I think).

In any case, listing the properties by name, although tedious, perhaps makes the class definition easier to read since you can see at a glance what all the properties are.

I didn't think about assigning session vars to properties by reference - as you say saves having to dump object properties at the end of scripts since they are mirrored in $_SESSION at all times.

All class properties now exist in the superglobal scope throughout the script - and hence are available to everything everywhere without any argument passing. Intriguing. Would that be frowned upon?

I know it's considered bad practice to use globals. With reg globals on, there's a risk that any unset vars will be poisoned. Apart from that, it's generally recommend to reduce the scope of any variable as far as possible. That way, if you get a bug, it's much easier to see where vars are being set.

However, $_SESSION vars aren't same as global. They can't be poisoned (at least not directly). The scope issues possibly do not arise: although you COULD access them from anywhere, the script below encapsulates access to these vars in classes, using them in specific scopes.

Anyone got any comments on that?

Code: Select all

<?php

// Need to add some setters to classes to set properties 
// in the no-session case - or maybe use polymorphism.
class Foo
{
    var $var1 = null;
    var $var2 = null;
    var $var3 = null;

    var $foovar;         // a counter logging.. what?

    function Foo()
    {
        if(isset($_SESSION['Foo']))
        {
            $this->fooVar = 10;
            $this->var1 =& $_SESSION['Foo']['var1']; 
            $this->var2 =& $_SESSION['Foo']['var2']; 
            $this->var3 =& $_SESSION['Foo']['var3']; 
        }
    }

    function decrementFooVar()
    {
      $this->fooVar--;
    }
}

class Bar
{
    var $var1 = null;
    var $var2 = null;
    var $var3 = null;

    var $objFoo;

    function Bar()
    { 
        if(isset($_SESSION['Bar']))
        {
            $this->var1 =& $_SESSION['Bar']['var1']; 
            $this->var2 =& $_SESSION['Bar']['var2']; 
            $this->var3 =& $_SESSION['Bar']['var3']; 
        }
    }

    function setObjFooProperty(&$objFoo)
    {
      $this->objFoo =& $objFoo;
    }

    function incrementFooVar()
    {
      $this->objFoo->fooVar++;
    }
}

// NB: you might not want to empty the entire session..
function checkSessionClean()
{
    if ($_GET['clear'] == 1)
    {
        $_SESSION = array();
    }
}

/////////////
// in use: //
/////////////

session_start();
checkSessionClean();

$objFoo = new Foo();
$objBar1 = new Bar();
$objBar2 = new Bar();

$objBar1->setObjFooProperty($objFoo);
$objBar2->setObjFooProperty($objFoo);

?>

Posted: Fri Sep 19, 2003 12:05 am
by jason
Not entirely geared towards this discussion, however, the first post caught my eye. Mostly because I feel it's doing something it shouldn't do. Or rather, it could be improved.

Essentially, it's concerning the fact that you have a User class, and it's handling two seperate things: Logging the user in AND validating the user's input.

You do have, after all, an SQL query validating the users username and password. Of course, I will assume other forms on your site go through validation as well.

Bear with me for a moment.

Anyways, what you would be better off doing is separating your validation. Remove it from the user object. In fact, the user object could be thinned to something like:

Code: Select all

function login ($LoginValues)
{
        $Validations =& Inspector::validate($LoginValues);
        $Validations->enforce('username', 'password');
        if ( $Validations->isValid() ) {
                $this->setUsername($LoginValues['username']);
                $this->intLoggedInId = $this->getUserId();
        }
}
Now, I know what your thinking, how is that any better. Let me explain.

Validation is something you are always doing. You always want to ensure that the values you expect are indeed what you expect them to be. If you go through your code, you will probably find dozens of places where you are checking and double checking a whole variety of variables.

These are validations, and validations can be handled via the Strategy Pattern. Now, I got this idea after reading an article on phppatterns.com concerning Strategy patterns. I took the idea, and expanded on it. What I came up with is much farther along than what Harry writes about (though, it was an article on the Strategy pattern, not writing a complete validation setup).

Anyways, for my code. Every validator has it's own class. And each validation class has it's own file.

validate_username.php is one of them. validate_password.php is another one.

In each file, their is a single class, such as validate_username(), or validate_password().

Each of these classes provide a common interface that allows me to validate a large assortment of values quickly and easily.

So in this case, I would validate the username, and then the password, making sure each was indeed a valid username and password in the database.

I would probably call the files and classes something like validate_login_username and validate_login_password actually, just be be clear.

Anyways, now I don't have to worry about validating these variables when they come in. I just pass them to the Inspector, which runs through and validates every single value. So I am just passing in the $_POST array, I dont' have to worry about what is in the $_POST array. The Inspector will validate everything for me. This also means I won't forget to check an element by not explicitly validating it.

Anyways, the idea is to try and separate your validation from your User object's login method.

Posted: Fri Sep 19, 2003 3:35 am
by Heavy
In response to McGruff:
What is "Camel back var names"?
I find my style a very readable naming convention:
Every first letter of a word in a name should be capital except the first one.
A short prefix tells its type intention (I know PHP is not strictly typed):
$arrUsers
$strFirstName
$intUserID
$boolLoggedIn
etc.
I don't get confused.

If you mean this:
${$_GET['incrVarName']}->incrementFooVar();
Don't worry. I never do that. :D
McGruff wrote: Can you use your populateObjVarsByRef fn in a constructor? Since the class hasn't been instantiated, and all properties set, get_class_vars() and get_class() have nothing to return (I think).
Ummm... If you do a print_r($arrVarNames), you'll see that it works.
McGruff wrote: In any case, listing the properties by name, although tedious, perhaps makes the class definition easier to read since you can see at a glance what all the properties are.
Why? the populateObjVarsByRef () function is general. The only thing it doesn't sense and I started thinking about when trying to sleep and my roof was waking me up all the time because of the wind is that the if (substr($strVarName,0,3) != 'obj'){ part should be replaced with something that senses that the variable is about to be a reference to another object (or var). I guess this is not possible.

This is deprecated I guess:

Code: Select all

<?php
class Bar
{
    var $var1 = null;
    var $var2 = null;
    var $var3 = null;
}
?>
I quote:
PHP Manual wrote:

Code: Select all

<?php
/* None of these will work in PHP 4. */
class Cart
{
    var $todays_date = date("Y-m-d");
    var $name = $firstname;
    var $owner = 'Fred ' . 'Jones';
    var $items = array("VCR", "TV");
}

/* This is how it should be done. */
class Cart
{
    var $todays_date;
    var $name;
    var $owner;
    var $items;

    function Cart()
    {
        $this->todays_date = date("Y-m-d");
        $this->name = $GLOBALS['firstname'];
        /* etc. . . */
    }
}
?>
Also. Looking at your reply. What happens if you create two different objects of the one of your classes? You break the property references to the session! I passed the name of the object to the constructor to distinguish between objects, not classes.
McGruff wrote:All class properties now exist in the superglobal scope throughout the script - and hence are available to everything everywhere without any argument passing. Intriguing. Would that be frowned upon?

I know it's considered bad practice to use globals. With reg globals on, there's a risk that any unset vars will be poisoned. Apart from that, it's generally recommend to reduce the scope of any variable as far as possible. That way, if you get a bug, it's much easier to see where vars are being set.

However, $_SESSION vars aren't same as global. They can't be poisoned (at least not directly). The scope issues possibly do not arise: although you COULD access them from anywhere, the script below encapsulates access to these vars in classes, using them in specific scopes.

Anyone got any comments on that?
Indeed. I don't get what you are talking about. You are using the same $_SESSION global as I am, and you are not protecting it from beeing accessed any more than I do.

I question that your code has been tested, because:
  • $this->fooVar = 10; cannot point to var $foovar;
    $this->var1 =& $_SESSION['Foo']['var1']; causes all objects of that class use the same data. bad...
Yes, I know the "clear" code empties the session completely. It was only some simple test code to test whether the class references would work. And they do!

Maybe our intensions are different, but I used $objFoo->fooVar only to test whether the data would be saved into and restored from $_SESSION as expected.

yet another one

Posted: Fri Sep 19, 2003 3:41 am
by Heavy
Here comes another version of my objects-in-session philosophy.

I slimmed down the populateObjVarsByRef() function. It was bloated because of the hen and chicken problem I had in the beginning. Now, the function is rewritten.

I also changed the test case to show why I think the object name needs to go into session instead of the class name.

Please! McGruff, I humbly ask you to test it before replying, if you want to discuss this further.

Code: Select all

<?php
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");

function populateObjVarsByRef(& $object, $strObjName){
	//Slimmed down.
	$arrVarNames = array_keys(get_class_vars(get_class($object)));
	$boolSessionAlreadySet = isset($_SESSION[$strObjName]);
	foreach ($arrVarNames as $strVarName){
		if (substr($strVarName,0,3) != 'obj'){
			$object->$strVarName  = & $_SESSION[$strObjName][$strVarName];
		}
	}
	return $boolSessionAlreadySet;
}

class foo{
   var $arrNumbers;
   function foo($strObjName){
      if (!populateObjVarsByRef($this, $strObjName)){
      	// here goes construction:
      	// should only be executed one time.
         $this->arrNumbers = array(2);
      }
   }
   
   function setNumber0($intVal){
      $this->arrNumbers[0] = intval($intVal);
   }
}

class bar{
   var $objFoo;
   var $str1;

   function bar($strObjName, & $objFoo){
      if (!populateObjVarsByRef($this, $strObjName)){
      	$this->str1 = 'Just testing';
      }
      $this->objFoo = & $objFoo;
   }
   
   function alterData(){
      $this->objFoo->arrNumbers[1] += $this->objFoo->arrNumbers[0] ;
      $this->str1 .= (strlen($this->str1) ? ', ' : ''). $this->objFoo->arrNumbers[1];
   }
}

class homer extends bar{
   function alterData(){
      $this->objFoo->arrNumbers[1] -= $this->objFoo->arrNumbers[0] ;
      $this->str1 .= (strlen($this->str1) ? ', ' : ''). $this->objFoo->arrNumbers[1];
   }
}

session_start();
if ($_GET['clear'] == 1){
   $_SESSION=array();
}

$objFoo = new foo('objFoo');
$objBar1 = new bar('objBar1', $objFoo);
$objBar2 = new homer('objBar2', $objFoo);

if (isset($_GET['setVal'])){
   $objFoo->setNumber0($_GET['setVal']);
}

if ($_GET['calculate']=="1"){
   $objBar1->alterData();
}
if ($_GET['calculate']=="2"){
   $objBar2->alterData();
}

echo '<pre>';
echo "<a href="{$_SERVER['SCRIPT_NAME']}?setVal=2">load again - \$objBar1->setNumber0(2)</a><br>";
echo "<a href="{$_SERVER['SCRIPT_NAME']}?setVal=3">load again - \$objBar1->setNumber0(3)</a><br>";
echo "<a href="{$_SERVER['SCRIPT_NAME']}?calculate=1">load again - \$objBar1->alterData()</a><br>";
echo "<a href="{$_SERVER['SCRIPT_NAME']}?calculate=2">load again - \$objBar2->alterData()</a><br>";
echo "<a href="{$_SERVER['SCRIPT_NAME']}?clear=1">load again - but empty session</a><br><br>";

echo '$objFoo->arrNumbers[0]: ' . $objFoo->arrNumbers[0] . "<br>";
echo '$objFoo->arrNumbers[1]: ' . $objFoo->arrNumbers[1] . "<br>";
echo '$objBar1->objFoo->arrNumbers[0]: ' . $objBar1->objFoo->arrNumbers[0] . "<br>";
echo '$objBar1->str1: ' . $objBar1->str1. "<br>";
echo '$objBar1->objFoo->arrNumbers[1]: ' . $objBar1->objFoo->arrNumbers[1] . "<br>";
echo '$objBar2->objFoo->arrNumbers[0]: ' . $objBar2->objFoo->arrNumbers[0] . "<br>";
echo '$objBar2->objFoo->arrNumbers[1]: ' . $objBar2->objFoo->arrNumbers[1] . "<br>";
echo '$objBar2->str1: ' . $objBar2->str1. "<br>";
echo '<br>Session data:<br>';
print_r($_SESSION);
echo "</pre>";
?>