Login

Building Persistent Objects in PHP 5

The HTTP protocol is stateless, but sometimes it is necessary to make web applications store or remember information. This is sometimes referred to as persistent storage, and it takes on a number of different forms. This six-part series of articles will explain the concept and show you various ways to give your web applications a memory.

Very often, you’ll hear web developers to say (sometimes with a subtle sense of arrogance) that a certain application uses a persistent storage mechanism to save the data it needs to work properly. This is nothing but an elegant way to say that a web program uses a relational database, a simple text file or even a single cookie, to store pieces of data across different HTTP requests.

The stateless nature of the HTTP protocol frequently requires working with these storage mechanisms, even in their simplest form. Moreover, if you’ve developed a few web-based programs that interact with MS SQL, MySQL, or an Oracle database, then you’ve already created persistent data layers, whether or not you realized it.

Unquestionably, when using PHP 5 the most common type of persistent storage system associated with the language is one or multiple MySQL databases, but as I said before, cookies and plan text files also fall under this category. Typically, though a persistent storage mechanism will store chunks of data that don’t have an explicit meaning when analyzed separately, such as strings or numbers, it’s also possible to save entire objects, or a particular state of those objects.

This possibility brings to the table the concept of persistent objects, or objects that are capable of maintaining themselves or their state across several HTTP requests. The best part is that these objects are much simpler to create than you might think; the creation process requires only an intermediate background in using the object-oriented paradigm with PHP 5, as well as a basic idea of how to serialize and unserialize objects. That’s all you’ll need, really.

So, in this set of articles, I’m going to explain, with code samples, how to build persistent objects in PHP 5. First we’ll use simple cookies to “persist,” and once you’ve properly digested the the key concepts, I’ll utilize text files, and finally, a single MySQL database table.

Finally, I’d like to say that some of the classes that I’m going to build in the subsequent tutorials of this series will be inspired partially by the example class developed by Martin Jansen in its excellent article on Object Overloading in PHP 5. Kudos to him for that.

Having clarified that point, let’s leave the boring theory behind and start learning the basics on creating persistent objects. Let’s begin right away!

{mospagebreak title=Introducing persistent objects in PHP 5}

In order to explain how to create persistent objects in PHP 5, I’m going to begin building a simple class. It will use PHP’s native session mechanism to save a particular state of an object that stores some trivial data on a fictional user.

You’ll understand the way this class will work much better if you see its initial definition, so below I included its partial source code. Pay close attention to 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];

}

}

}

As I explained a few moments ago, all that the above “User” class does is store an instance of itself in a simple session variable, in this particular case referenced as $_SESSION[‘user’]. This specific instance will first be created via a static factory method, which will load this object either from the session variable, or as an empty entity via a regular “new” construct.

Also, for the sake of making the class’s code a bit more compact I decided to implement the “__set()” and “__get()” magic PHP methods to assign and retrieve properties dynamically through the $data internal array. Naturally, the same process can be performed by declaring those properties within the class’s body.

Well, now that I have outlined how the previous “User” class functions, hopefully you’ll have a better idea of how to create objects that can save their state to a session variable, thus persisting across several HTTP requests.

But, wait a minute! The class in question actually doesn’t implement a method that saves an instance of itself. Where is that method, then? To be honest, it needs to be defined first, and then properly implemented.

However, this process will be discussed in detail in the section to come. So, to learn more about it, click on the link shown below and read the following segment.

{mospagebreak title=Implementing a destructor method}

In the course of the previous segment, I partially defined a sample class, which had the ability to create and assign properties dynamically. It had this ability due to a simple implementation of the so-called property overloading process, carried out by the complementary “__set()” and “__get()” PHP magic functions.

However, the most important point to note with reference to this class is that I intend to make it capable of saving an instance of itself to a session variable. So far, its factory method does load this instance, but there’s no a specific method that first stores the object on the session variable. So how can this be done?

Well, as you may know, there are many ways to save an instance of a class to a session variable. For instance, I could define a regular method called “save()” or something similar to do this, but in this particular case I’m going to use a destructor to perform this task. In doing so, the whole saving process will be handled transparently by the PHP engine.

Of course, it’s important to learn how to implement a destructor within the previous “User” class, so below I included its basic definition:

// save object to session variable

public function __destruct()

{

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

}

Were you expecting to see lengthier code? Fortunately, this is not the case. The implementation of this destructor does only one thing, namely save an instance of the “User” class to a predefined session variable. Since a destructor method is always called automatically right before the PHP interpreter finishes parsing a script, the instance will be stored via the session mechanism in a truly transparent manner.

Now that you’ve grasped the underlying logic that drives the previous destructor method, it’s time to see the complete definition of the “User” class, after adding this last method to 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);

}

}

Definitely, I’m not trying to pretend that creating persistent objects in PHP 5 is always that simple, but you’ll have to admit that understanding how the above “User” class persists during different HTTP requests is a straightforward process.

Even so, a concrete example is in order here, so you can see how to work with an instance of this sample class. Thus, in the last segment of this tutorial I’m going to create a script that first assigns some properties to an object spawned from the class, and then uses its destructor to save it to the $_SESSION[‘user] variable that you saw before.

Therefore, if you wish to learn how this example will be developed, click on the link displayed below and read the next section.

{mospagebreak title=Putting the sample User class into action}

As I said in the segment that you just read, the best way to understand how an instance of the “User” class defined earlier can be turned into a persistent object is by means of a simple example.

Below I included the complete source code of the class, complemented by a short script that shows how to create an object that persists across multiple HTTP requests, naturally assuming that session support has been enabled on the testing web server.

Here’s the corresponding code sample, so take your time to examine it closely:

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);

}

}

// example on using a persistent object

$user = User::factory();

$user->fname = ‘Alejandro';

$user->lname = ‘Gervasio';

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

There you have it. Believe it or not, creating a basic persistent object with PHP 5 is really a simple process, as demonstrated by the above code fragment. In this case, the “$user” object, which happens by mere coincidence to represent myself, has been assigned some properties, including my first and last names, and my (fictional) email address as well.

Nonetheless, there’s something else going on under the surface of the previous script. Once it finishes running, the destructor method is called, which saves the object to the predefined session variable. In doing so, it’s possible to restore it on a different web page and keep handling it as one would do with regular session data.

Finally, feel free to edit all of the code samples included in this tutorial, which hopefully will arm you with a better grounding in building persistent objects in PHP 5.

Final thoughts

That’s all for now. In this introductory chapter of the series, you learned the basics of creating persistent objects with PHP 5, which in this introduction to the subject used native sessions as the underlying persistent storage mechanism.

Also, it’s valid to point out that the class that I created in this article isn’t very flexible in its current state, because it permits you to use only a predefined session variable to store an instance of it. To overcome this issue, in the next tutorial I’m going to tweak its definition so that it’ll be able to use any user-supplied session variable.