Login

Persistent Objects and Different Session Variables in PHP 5

Despite its rather intimidating name, persistent objects represent a pretty simple concept applied very often in software development. It’s aimed at creating structured entities that can maintain their status across different stages of an application. This six-part series will take the mystery out of persistent objects so you can use them in your own applications.

When using PHP 5 for developing web-based programs, creating this kind of object is even simpler. In most cases, the creation process is reduced to defining classes that are simply capable of keeping their state through several HTTP requests, in order to overcome the stateless nature of this protocol.

Naturally, popular storage mechanisms long available on the web like database tables, text files and even cookies are frequently used to save instances of a class. This implies that some objects may be more persistent that others, even when this characteristic is only relevant in the context in which they’re utilized.

However, as with many other topics related specifically to web development, building persistent objects in PHP 5 is a subject that’s definitely much better understood by example. So, in the first part of this series of articles I demonstrated how to define a basic class, which was provided with the ability to save an instance of itself to a predefined session variable, in this way maintaining its state across several web pages.

There are, however, a few issues that must be fixed regarding the way that this persistent class was initially defined. First, it’s necessary to show how to restore an instance of the class on a different web page, and second, it must have the ability to use different session variables for saving its instances, thus enhancing its flexibility.

Therefore, in this second installment of the series I’m going to show how to address the aforementioned issues. Let’s get started right now!

{mospagebreak title=Building a basic persistent class in PHP 5}

Before I begin demonstrating how to make the persistent class defined in the previous article slightly more flexible, first I’d like to summarize how to use it in its current state. This way, you’ll see how an instance of it can be saved to a specific predefined variable, and at later time, restored on a different web page.

So here is the complete definition of the persistent class. I decided to call it “User,” since it’s useful for storing data on a fictional user. Have a look at it:

class User

{

private $data = array();

// constructor (not implemented)

public function __construct(){}

// factory method

public static function factory()

{

session_start();

if(isset($_SESSION[‘user’]) === TRUE)

{

return unserialize($_SESSION[‘user’]);

}

return new User();

}

// set undeclared property

public function __set($property, $value)

{

$this->data[$property] = $value;

}

// get undeclared property

public function __get($property)

{

if (isset($this->data[$property]) === TRUE)

{

return $this->data[$property];

}

}

// save object to session variable

public function __destruct()

{

$_SESSION[‘user’] = serialize($this);

}

}

Well, to be frank, understanding how an instance of the previous “User” class can persist across different HTTP requests isn’t rocket science. As you can see, the class restores (or creates) a user object via its “factory()” method, while its destructor takes care of storing the corresponding instance to a statically-assigned session variable, called “$_SESSION[‘user’]. It’s really that simple.

Now that you remember how the previous “User” class was defined originally, it’s time to demonstrate its actual functionality. To do that, I’m going to spawn an object from it, which will store some data about me on the specified session variable (and don’t think that I’m being too egocentric, since it’s only for example purposes).

The code fragment that performs this task is the following:

// example on creating a persistent object

$user = User::factory();

$user->fname = ‘Alejandro';

$user->lname = ‘Gervasio';

$user->email = ‘alejandro@mydomain.com';

Behind this short script, a few interesting things are happening. First, it creates a new user object by way of the static “factory()” method, and then it uses property overloading to assign dynamically some values to three undeclared properties. Finally, it saves the object to the $_SESSION[‘user’] variable via the class’s destructor.

Of course, it’s also possible to create persistent objects in a more conventional way, without using some of the magic methods offered by PHP 5, but I decided to code the “User” class like this to make it a bit more compact.

Now, returning to the previous code sample, once the user object has been saved to the specified session variable, it’s necessary to show how it can be restored and modified on a different web page. To achieve this, the page in question should look similar to this:

<?php

class User

{

private $data = array();

// constructor (not implemented)

public function __construct(){}

// factory method

public static function factory()

{

session_start();

if(isset($_SESSION[‘user’]) === TRUE)

{

return unserialize($_SESSION[‘user’]);

}

return new User();

}

// set undeclared property

public function __set($property, $value)

{

$this->data[$property] = $value;

}

// get undeclared property

public function __get($property)

{

if (isset($this->data[$property]) === TRUE)

{

return $this->data[$property];

}

}

// save object to session variable

public function __destruct()

{

$_SESSION[‘user’] = serialize($this);

}

}

// assign new properties to the persistent object

$user = User::factory();

$user->fname = ‘John';

$user->lname = ‘Doe';

$user->email = ‘john@domain.com';

?>

From the above example, it’s clear to see how easy it is to retrieve the persistent object created previously on a different web page, as well as to assign new values to its properties. In this particular case, I decided to modify those properties, but naturally it’s possible to load the object via its “factory()” method and keep its internal state untouched. That was really simple to do, wasn’t it?

So far, so good. At this stage, I showed you how to create and use an object that’s capable of maintaining its status through two different web pages by using only a single session variable. However, as I said in the introduction, the object’s originating class in its current state is pretty inflexible, since it stores the pertinent instance on a predefined variable that can’t be inputted from the outside.

In reality, it’d be useful to provide the class with the ability to store its instances on different session variables, other than the predetermined $_SESSION[‘user’] that you saw before. Therefore, in the section to come I’m going to modify slightly the definition of the sample “User” class, so it can expose the aforementioned capability.

True to form, providing the previous “User” class with the capacity for saving its instances to different session variables is only a matter of tweaking the definition of its “factory() method and its destructor. Period.

You don’t believe that this process can be that simple? Well, to prove this, below I listed the enhanced version of this class, which now defines its factory method in a slightly different way. Here it is:

class User

{

private $data = array();

private static $key = ‘user';

// constructor (not implemented)

public function __construct(){}

// factory method

public static function factory($key = ”)

{

session_start();

if ($key != ”)

{

self::$key = $key;

}

if(isset($_SESSION[self::$key]) === TRUE)

{

return unserialize($_SESSION[self::$key]);

}

return new User();

}

// set undeclared property

public function __set($property, $value)

{

$this->data[$property] = $value;

}

// get undeclared property

public function __get($property)

{

if (isset($this->data[$property]) === TRUE)

{

return $this->data[$property];

}

}

// save object to session variable

public function __destruct()

{

$_SESSION[self::$key] = serialize($this);

}

}

As I explained before, now the “factory()” method of the above “User” class accepts a $key input argument, which is used internally to create the session variable responsible for storing class instances. On the other hand, the implementation of the destructor is subtly different too, which is a natural consequence, since it has to reflect the change introduced into the factory method.

Having provided the persistent “User” class with the ability to save its eventual instances to different session variables, it’s time to give it a try. In the final section of this tutorial I’m going to create another script, which will demonstrate the improved functionality of the aforementioned class.

To see how this last code sample will be developed, click on the link below and read the next few lines.

{mospagebreak title=Building a wrapping example}

To demonstrate how an instance of the enhanced “User” class can persist across two HTTP requests, I’m going to define a couple of PHP files. The first one will create a new user object, and the second will assign new values to its properties, once the object has been reloaded via its factory method.

Does this sound rather confusing to you? Fear not; just look at the definition corresponding to the first of these files:

<?php

class User

{

private $data = array();

private static $key = ‘user';

// constructor (not implemented)

public function __construct(){}

// factory method

public static function factory($key = ”)

{

session_start();

if ($key != ”)

{

self::$key = $key;

}

if(isset($_SESSION[self::$key]) === TRUE)

{

return unserialize($_SESSION[self::$key]);

}

return new User();

}

// set undeclared property

public function __set($property, $value)

{

$this->data[$property] = $value;

}

// get undeclared property

public function __get($property)

{

if (isset($this->data[$property]) === TRUE)

{

return $this->data[$property];

}

}

// save object to session variable

public function __destruct()

{

$_SESSION[self::$key] = serialize($this);

}

}

// example on creating a persistent object

$user = User::factory(‘newuser’);

$user->fname = ‘Alejandro';

$user->lname = ‘Gervasio';

$user->email = ‘alejandro@mydomain.com';

?>

Frankly speaking, nothing spectacular is happening here. The previous file shows how to create a brand new user object, which, thanks to the enhanced functionality of its originating class, is now stored on a different session variable called $_SESSION[‘newuser’].

On the other hand, it’s necessary to create a second file that retrieves this object and modifies its properties as well. The one below does that in a simple manner:

<?php

class User

{

private $data = array();

private static $key = ‘user';

// constructor (not implemented)

public function __construct(){}

// factory method

public static function factory($key = ”)

{

session_start();

if ($key != ”)

{

self::$key = $key;

}

if(isset($_SESSION[self::$key]) === TRUE)

{

return unserialize($_SESSION[self::$key]);

}

return new User();

}

// set undeclared property

public function __set($property, $value)

{

$this->data[$property] = $value;

}

// get undeclared property

public function __get($property)

{

if (isset($this->data[$property]) === TRUE)

{

return $this->data[$property];

}

}

// save object to session variable

public function __destruct()

{

$_SESSION[self::$key] = serialize($this);

}

}

// assign new values to properties of the persistent object

$user = User::factory(‘newuser’);

$user->fname = ‘John';

$user->lname = ‘Doe';

$user->email = ‘john@domain.com';

?>

As I expressed earlier, this second file simply reloads the user object created earlier via its factory method, and then assigns some new values to the corresponding properties. Finally, the new state of the object is saved internally to the specified session variable by means of its destructor, which demonstrates in a nutshell how easy it is to extend the functionality of the persistent “User” class.

And with this last example I’m finishing this article. As usual, feel free to edit all of the code samples shown in this tutorial, which hopefully will give you a more solid background in building persistent objects with PHP 5.

Final thoughts

That’s all for now. In this second part of the series, I demonstrated how to build a persistent class that has the ability to save its instances to different session variables. As you saw for yourself, building this particular class was pretty straightforward, so in theory you shouldn’t have major problems replicating it on your own testing web server.

Moving forward, in the next tutorial I’m going to discuss how to create persistent objects that use text files as their default storage mechanism, unlike simple cookies. So, now that you know what to expect from the forthcoming part of this series, you can’t miss it!