Object-Oriented PHP: Autoloading, Serializing, and Querying Objects

In this object-oriented PHP tutorial, you learn how to automatically load classes, convert objects to strings, and inspect objects, properties and methods.

Object-Oriented PHP: Object-Oriented PHP: Autoloading, Serializing, and Querying Objects

Welcome to my fourth object-oriented PHP tutorial! If you missed the first three then you may want to take a look at those first, to give yourself a thorough grounding in PHP classes and objects:

If you've read all the articles up to this point then you're already familiar with the most important concepts of object-oriented programming in PHP: classes, objects, properties, methods, and inheritance. In this final (for now, at least!) tutorial in the series, I'm going to tie up some loose ends and look at some other useful OOP-related features of PHP:

  • How to automatically load classes on demand
  • Converting objects to and from strings for easy storage and transmission, and
  • Useful ways to find out more about a given class or object.

Ready? Let's go!

Autoloading classes

Forklift

As a general rule, it's a good idea to keep your PHP classes in separate files, with one class per file. For example, in a web forums application you might store the definition for the Member class in a file called Member.php, and the Topic class in a file called Topic.php. Typically you'd put these class files in a classes folder somewhere in your website:

classes/
  Member.php
  Topic.php

Then, if a PHP script in your application needs to create a Member object, it first includes the Member.php class file, like this:

<?php
require_once( "classes/Member.php" );
$member = new Member();
?>

Keeping your classes separated and organized like this is a great idea — not just to preserve your sanity, but also because it lets you use a handy PHP feature called autoloading.

Autoloading works like this. You create a function called __autoload() near the start of your PHP application. Then, whenever your code tries to create a new instance of a class that PHP doesn't know about, PHP automatically calls your __autoload() function, passing in the name of the class it's looking for. Your function's job is to locate and include the class file, thereby loading the class. PHP can then go ahead and create the object.

Let's try out autoloading. We'll write an __autoload() function to automatically load classes from a classes folder:

<?php

function __autoload( $className ) {
  $className = str_replace( "..", "", $className );
  require_once( "classes/$className.php" );
  echo "Loaded classes/$className.php<br>";
}

$member = new Member();
echo "Created object: ";
print_r( $member );

?>

Here's how the script works. First we create our __autoload() function, retrieving the required class name in the $className parameter. Our function first strips any ".." substrings from the class name since this can be a security loophole. Then it uses the PHP require_once() function to include the class file. It assumes that the class file is in a classes folder, and that its filename comprises the class name followed by the ".php" extension. The function also displays a status message using echo, so we can tell when it's done its job.

Then we test our function by creating a new Member object. Since we haven't previously loaded the Member class, PHP runs __autoload(), which attempts to load the class file classes/Member.php. PHP then creates the Member object. Finally, we display the created object by calling the PHP print_r() function.

To try out our script, let's create a classes folder in the same folder as the script, and put the following simple Member.php class file inside the classes folder:

<?php
 
class Member {
}

?>

Now, when we run the main script, it loads the classes/Member.php class file, creates a new Member object, and produces the following output:


Loaded classes/Member.php
Created object: Member Object ( ) 

Autoloading can be a great time-saver, especially if your application is big and contains a lot of classes. Rather than having to create lots of require_once() lines of code at the top of each script, you simply create an __autoload() function at the start of your application code, and let PHP do the rest!

Serializing objects

Playdoh

The next OOP topic we're going to explore is how to convert an object to a string, and vice-versa. This trick can be useful when you need to pass object data as strings of text between scripts and applications. Common situations include:

  • Passing objects via fields in web forms
  • Passing objects in URL query strings
  • Storing object data in a text file, or in a single database field

To convert an object to a string — and back again — you use the following PHP functions:

  • serialize() takes an object, and outputs a string representation of the object's class and properties.
  • unserialize() takes a string created by serialize(), and converts it back into a usable object.

Let's try out these two functions:

<?php
 
class Member
{
  public $username = "";
  private $loggedIn = false;
 
  public function login() {
    $this->loggedIn = true;
  }
 
  public function logout() {
    $this->loggedIn = false;
  }
 
  public function isLoggedIn() {
    return $this->loggedIn;
  }
}

$member = new Member();
$member->username = "Fred";
$member->login();

$memberString = serialize( $member );
echo "Converted the Member object to a string: '$memberString'<br>";
echo "Converting the string back to an object...<br>";
$member2 = unserialize( $memberString );
echo $member2->username . " is " . ( $member2->isLoggedIn() ? "logged in" : "logged out" ) . "<br>";
 
?>

Here we create a simple Member class with a public $username property, a private $loggedIn property, and three public functions: login(), logout() and isLoggedIn(). Our script then creates a new Member object, gives it a username of "Fred", and logs the member in.

Then we call serialize(), passing in the Member object. serialize() returns a string representation of the object, which we store in $memberString and display in the page:


Converted the Member object to a string:
'O:6:"Member":2:{s:8:"username";s:4:"Fred";s:16:"MemberloggedIn";b:1;}'

Then we convert our string representation back to a new Member object by calling unserialize(), and store the new object in the $member2 variable. To check that our new object is fully present and correct, we display its $username property and call its isLoggedIn() method to check that the member is logged in. This displays:


Converting the string back to an object...
Fred is logged in

As you can see, the string created by serialize() contains the class name, as well as the property names and values inside the object. (Private properties have the class name prepended to them, with a null byte on either side of the class name.) However, the class's methods are not stored in the string.

Therefore, in order for unserialize() to work, the class of the object to be unserialized must be defined by the time you call unserialize(). You can define the class in the same script as the call to unserialize(), or you can include the class file using require_once(). Alternatively, you can create an __autoload() function as we did earlier in the tutorial. PHP will call __autoload() if it can't find the class of the object you're trying to unserialize.

serialize() and unserialize() can also work on other data types, such as arrays. However they don't work with resource data types.

Sleeping and waking up

Sometimes it's useful to do some cleaning up before serializing an object. For example, you might want to write unsaved object data to a database and close the database connection. Similarly, after you've unserialized an object, you might want to restore its database connection and perform other setup tasks so that the new object can be used properly.

To this end, PHP lets you add a couple of magic methods to your class:

  • __sleep() is called automatically just before an object is serialized using serialize().
  • __wakeup() is called automatically just after an object is unserialized using unserialize().

Your __sleep() function should return an array of property names. These are the properties that serialize() should include in the resulting string. You can use this feature to omit any unnecessary or unwanted properties from the string.

Let's extend our previous example script to include __sleep() and __wakeup() methods:

<?php
 
class Member
{
  public $username = "";
  private $loggedIn = false;
 
  public function login() {
    $this->loggedIn = true;
  }
 
  public function logout() {
    $this->loggedIn = false;
  }
 
  public function isLoggedIn() {
    return $this->loggedIn;
  }

  public function __sleep() {
    echo "Cleaning up the object...<br>";
    return array( "username" );
  }

  public function __wakeup() {
    echo "Setting up the object...<br>";
  }

}

$member = new Member();
$member->username = "Fred";
$member->login();

$memberString = serialize( $member );
echo "Converted the Member object to a string: '$memberString'<br>";
echo "Converting the string back to an object...<br>";
$member2 = unserialize( $memberString );
echo $member2->username . " is " . ( $member2->isLoggedIn() ? "logged in" : "logged out" ) . "<br>";
 
?>

This script produces the following output:


Cleaning up the object...
Converted the Member object to a string: 'O:6:"Member":1:{s:8:"username";s:4:"Fred";}'
Converting the string back to an object...
Setting up the object...
Fred is logged out

Some interesting things to note about this script:

  • Our __sleep() and __wakeup() methods don't do any actual cleanup or setup; instead they merely display the messages "Cleaning up the object..." and "Setting up the object...".
  • Since we only include the $username property in the array that __sleep() returns, the resulting serialized string doesn't contain the $loggedIn property.
  • As a result, the unserialized object's $loggedIn property takes on its default value of false, so when we call isLoggedIn() on the unserialized object, it returns false. This is why the script displays "Fred is logged out".

If you want to include a __sleep() method and you want all of your object's properties to be serialized, then you'll need to list all of the property names in the array that __sleep() returns. An easy way to do this is to use the PHP array_keys() and get_object_vars() functions, as follows:

public function __sleep() {
  // Clean up
  return array_keys( get_object_vars( $this ) );
}

Another useful cross-platform way to serialize object data for passing around is to convert it to a JSON string. See our JSON Basics tutorial for details.

Finding out about objects and classes

Magnifying glass

PHP gives you a number of handy functions for discovering information about objects and classes. This can be useful if your code needs to work with an object from another application, and it can also help you to write reusable, flexible code. By using these functions to query an object, you can find out its class, see whether it's descended from a given class, inspect its methods and properties, and more.

Here's a short list of some of these useful functions:

Function Description
get_class( $obj ) Returns the name of the class of which $obj is a member
get_parent_class(
$className or $obj )
Returns the name of the class that is the parent of the class $className, or the parent of the class of which $obj is a member
is_a( $obj, $className ) Returns true if $obj's class is $className, or if $obj's class is descended from $className
$obj instanceof $className Does the same thing as the is_a() function
get_class_methods(
$className or $obj )
Returns an array containing the names of all the methods in the specified class $className or object $obj
get_class_vars( $className ) Returns an associative array of all the properties in the specified class $className, along with their default values
get_object_vars( $obj ) Returns an associative array of all the properties in the supplied object $obj, along with their current values

It's important to note that functions such as get_class_methods(), get_class_vars() and get_object_vars() only return methods and properties that are in the same scope as the code that calls them. For example, a private method will be included in the output from get_class_methods() only if get_class_methods() is called from within a method of the class.

Let's try out some of these functions with an example script:

<?php
 
class Member {
 
  public $username = "";
  private $loggedIn = false;
 
  public function login() {
    $this->loggedIn = true;
  }
 
  public function logout() {
    $this->loggedIn = false;
  }
 
  public function isLoggedIn() {
    return $this->loggedIn;
  }

  public function listMyProperties() {
    echo "My properties are: ";
    print_r( get_object_vars( $this ) );
  }
}
 
class Administrator extends Member {
 
  public $adminLevel = 1;

  public function createForum( $forumName ) {
    echo "$this->username created a new forum: $forumName<br>";
  }
 
  public function banMember( $member ) {
    echo "$this->username banned the member: $member->username<br>";
  }
 
}

$admin = new Administrator();
$admin->username = "Mary";
$admin->login();

echo "1. $admin->username's class is " . get_class( $admin ) . "<br>";
echo "2. $admin->username's parent class is " . get_parent_class( $admin ) . "<br>";
echo "3. Is $admin->username a Member? " . ( is_a( $admin, "Member" ) ? "Yes" : "No" ) .  "<br>";
echo "4. $admin->username's methods are: ";
print_r( get_class_methods( $admin ) );
echo "<br>5. $admin->username's class properties are: ";
print_r( get_class_vars( get_class( $admin ) ) );
echo "<br>6. $admin->username's object properties are: ";
print_r( get_object_vars( $admin ) );
echo "<br>7. ";
$admin->listMyProperties();

?>

This script defines a Member class with a couple of properties and a few methods. It also defines an Administrator class as a child of the Member class. The Administrator class adds an extra public property, $adminLevel, and a couple of extra methods, createForum() and banMember(), that are specific to administrators.

After we've defined our classes, we create a new Administrator object, store it in the variable $admin, give it a username of "Mary", and log the admin in by calling the login() method.

In the last part of the script (lines 44-54), we try out various functions for inspecting our classes and object. Here's the output from the script:


1. Mary's class is Administrator
2. Mary's parent class is Member
3. Is Mary a Member? Yes
4. Mary's methods are: Array ( [0] => createForum [1] => banMember [2] => login [3] => logout [4] => isLoggedIn [5] => listMyProperties )
5. Mary's class properties are: Array ( [adminLevel] => 1 [username] => )
6. Mary's object properties are: Array ( [adminLevel] => 1 [username] => Mary )
7. My properties are: Array ( [adminLevel] => 1 [username] => Mary [loggedIn] => 1 ) 

Each function call works like this:

  1. get_class( $admin ) returns the string value "Administrator".
  2. get_parent_class( $admin ) returns the string value "Member".
  3. is_a( $admin, "Member" ) returns true.
  4. get_class_methods( $admin ) returns an array of method names from both the Administrator and Member classes. Since all the methods are public, they are all present in the array.
  5. get_class_vars( $admin ) returns an array of public property names and corresponding initial values from both the Administrator and Member classes.
  6. get_object_vars( $admin ) returns an array of public property names and corresponding current values for the object.
  7. Finally, we call a method of the Member class called listMyProperties(). This method also calls get_object_vars() and displays the result. However, since get_object_vars() is now called from inside the class, it also returns the class's private property, $loggedIn.

As you can see, PHP makes it very easy to query classes and objects to find out more about them. PHP also has other functions for querying objects, classes and interfaces, including class_exists(), get_called_class(), get_declared_classes(), get_declared_interfaces(), interface_exists(), is_subclass_of(), method_exists(), and property_exists().

Summary

In this tutorial you've looked at three miscellaneous features of PHP objects:

  1. Using the __autoload() function to get PHP to automatically load class files when they're needed
  2. How to convert objects to and from strings using PHP's serialize() and unserialize() functions, and
  3. Querying an object's class, ancestry, methods and properties using various PHP functions.

With these features, you have some useful tools to make your PHP classes and objects easier to work with.

I hope you've enjoyed this series of object-oriented PHP tutorials! If you've read all four tutorials then you have pretty much all you need to write great object-oriented PHP websites and apps. This isn't the end of the story however — PHP has many more useful OOP features up its sleeve, including:

  • Iteration: How to move sequentially through all the properties of an object
  • More magic methods, including __callStatic(), __isset(), __unset(), __toString(), __invoke(), __set_state(), and __clone()
  • Patterns: Techniques for achieving specific goals using objects
  • Cloning and comparing objects
  • Late static bindings, which give you more flexibility when calling inherited static methods

Time permitting — and if the demand is there — I hope to cover some of the above topics in later tutorials. If you'd like to see tutorials on any of these topics, please let me know in the comments below.

Happy coding!

Photo credits: me5otron, Neeta Lind, Okko Pyykkö

Learn PHP With Ease!

Written by Matt Doyle — ELATED's resident Web programming expert — Beginning PHP 5.3 is a complete introduction to PHP, covering everything in these tutorials and lots more besides. Find out how to:

  • Set up PHP on your computer
  • Use strings, arrays, functions and objects
  • Create interactive Web forms
  • Handle cookies and sessions
  • Work with files on the server
  • Build database-driven sites with MySQL
  • Send emails from your scripts
  • Create images on the fly with PHP
  • Work with regular expressions
  • Write robust, secure PHP applications

...and lots more!

“What a pleasure it's been spending hours and hours studying PHP with this magical book.” — Lulio, Florida
“The book is not only great for learning, but I find myself using it constantly as a reference as well!” — David A. Stoltz

Buy Beginning PHP 5.3 now from Amazon.comBeginning PHP 5.3 or Amazon.co.ukBeginning PHP 5.3.

Follow Elated

Related articles

Responses to this article

9 responses (oldest first):

01-Jul-11 16:11
Bring on the other OOP tutorials. These are the best I have found on the net, and I've been searching high and low for quality tutorials that aren't rehashed and cloned versions.

I think getting into the in's and out's of the various concepts and applications of OOP PHP would prove invaluable, and book worthy (I'd buy it!).
02-Jul-11 11:32
In my opinion, when you will develop the functionality of the system using plug-ins (as is done in WordPress), it is better to use the spl_autoload_register(), because it can happen that some plug-in is already using __autoloader()... Well, then you can have a problem
04-Jul-11 23:19
@tbolton: Thank you so much I'll definitely look at writing more PHP OOP tutorials, since there seems to be a lot of demand for them.

I do cover OOP in my PHP book (shameless plug!) - I go through pretty much the same topics that I've covered in the 4 tutorials so far, but in a bit more depth:

http://www.amazon.com/gp/product/0470413964/

There are also code examples throughout the book that show OOP in action.

@th3mon: Good point, yes. spl_autoload_register() lets you register multiple autoload functions in a stack, which is handy if you're working with libraries or frameworks that have their own autoloaders:

http://php.net/manual/en/function.spl-autoload-register.php
11-Jul-11 09:09
Matt Doyle - How does your book compare to this: http://amzn.to/r1eyVl - I dnt wanna buy one and miss out from the other.

I willm if you say yours is better buy yours. However I am a new starter and asking for your honest opinion of what you think would benefit me more.

very nice article btw, Bookmarked!

12-Jul-11 02:48
@mpetherbridge: I haven't read that book so I've no idea! It looks like it covers object-oriented programming in PHP - that's about all I can say.

My book covers OOP but it also covers many other aspects of PHP. If you're a PHP beginner then I'd certainly recommend checking it out. You can see some of the book content on Amazon:

http://www.amazon.com/gp/product/0470413964/#reader_0470413964

Cheers,
Matt
28-Jan-12 19:01
Thank you very much, for now, it is the best PHP OOP tutorials i can find on the net. It will be nice if you continue this tutorial, especially about pattern and Late static bindings. And once again, thank you very much.
30-Jan-12 00:58
@m_goku: Thanks for the feedback! I might write a tutorial on those topics if there's enough demand.

Matt
25-Jul-12 21:09
another grateful reader here
really rare, useful tutorials
wish you best of luck and hope you will surprise us with other tutorials in the future
thanks
17-Nov-13 08:49
This is a great series of tutorials!

All things web have been a hobby of mine for many years, (since html4 with css2 became the latest standards), and I can honestly say that this series of tutorials is the best written I have ever found.

I first landed at your sites doors a couple of day's ago when I found a link to your 'CMS in and afternoon' series and because that was so well written decided to look further. Boy I'm glad I did, despite so many years of reading and running through other peoples tutorials many of the basic aspects had never been properly explained. Simply starting at the beginning with your tutorials and reading all the beginner level articles through to here has made a massive difference to my understanding of what I am actually doing and why things are done the way they are.

Definitely keep writing this series please!

Post a response

Want to add a comment, or ask a question about this article? Post a response.

To post responses you need to be a member. Not a member yet? Signing up is free, easy and only takes a minute. Sign up now.

Top of Page