Storing singleton objects in PHP sessions

A friend of mine, who is working on a sick little diet and exercise tracking application, asked me today if PHP allowed singleton objects to be stored in a session. My first reaction was absolutely they can be so long as you follow the normal rules of unserializing objects in PHP… namely, making sure the class is in scope before attempting to create an object from it OR having an autoloader that does that for you. But as I thought about it more I began to think that maybe this might not work as expected since singletons generally have no public access to their constructors. However, when an object is unserialized, it is instantiated, for lack of a better term, and populated with the data that was exposed from the serialization process.

Note: for those of you that are unfamiliar with the way PHP handles session data or are just wondering why I am using serialization so much in my examples, the basics are you start a session and PHP assigns a random MD5 hash to it as an id. You write data to the session via the $_SESSION superglobal array and when the script terminates or you call session_write_close(), PHP serializes the $_SESSION array and writes that serialized string to the file system for retrieval on subsequent requests so long as the session time limit has not expired. I really did not want to run this entire session process and inspect what was being written to my file system so I decided to mock that interaction myself by creating an arbitrary array, serializing it, grabbing the serialized string and unserializing it.

As I began to dig into this I started playing with PHP’s magic __sleep() and __wakeup() methods. Those seemed to do what I wanted them to do except in the case of protected and private properties of my class. As soon as I added those in my serialization took a crap all over itself, even when I cloned the singleton object and got the public properties exposed through get_object_vars(). So, thanks to the PHP manual – the most awesome tool in any PHP developer’s arsenal – I discovered the PHP Serializable interface.

This interface defines two methods: serialize() and unserialize(). These methods override the default behavior of __destruct() and __construct() so if you are using these you should keep that in mind and either put your __destruct() and __construct() code into these methods or allow for calls to __destruct() and __construct() from within these methods. Your homework is to decide which is the better implementation. 🙂

Now, back to the lesson at hand… the following object – let’s say it is saved to a file named dummy.php – is a super simple implementation of a basic singleton pattern. It includes both a serialize() and unserialize() method to allow it to be serialized for storage.

<?php
class DummySingleton implements Serializable {
    /**
     * Test properties of various visibility
     * @var string
     */
    public $dProp;
    public $dPropX = 'Nothing to see here folks';
    private $_prop = 'y u try see dis?';
 
    /**
     * Instance holder for this singleton
     * 
     * @var DummySingleton
     */
    private static $_instance = null;
 
    /**
     * Private singleton constructor, simply sets a property
     */
    final private function __construct() {
        $this->dProp = 'I was finally built';
    }
 
    /**
     * Singleton instance getter
     * 
     * @return DummySingleton
     */
    public static function getInstance() {
        if (self::$_instance === null) {
            self::$_instance = new DummySingleton();
        }
 
        return self::$_instance;
    }
 
    /**
     * Implementation of the Serializable interface, called automatically just 
     * before this object is serialized. This will override any calls to a
     * __destruct method, so if you have a destructor you should call it from
     * here.
     * 
     * @return string
     */
    public function serialize() {
        return serialize(get_object_vars($this));
    }
 
    /**
     * When this object is created from an unserialization this method is called. 
     * It implements the Serializable interface and uses the data from the 
     * serialize() method herein. Since this method overrides the __construct
     * method you should make any accomodations for constructing your object
     * in this method.
     */
    public function unserialize($data) {
        // "Instantiate" our singleton
        self::getInstance();
 
        // Set our values
        if (is_array($data)) {
            foreach ($data as $k => $v) {
                $this->$k = $v;
            }
        }
    }
}
?>

If you build up this object then serialize it, then rebuild it from the serialization, you can see that it remains in tact. Let’s test this by simulating the session array, first creating an array then adding the DummySingleton object to that array, then serializing it:

<?php
// Grab the class
include 'dummy.php';
 
// Get our instance
$o = DummySingleton::getInstance();
 
// Set something into it for testing
$o->setFromOutside = 'What the hell is this madness?';
 
// Make an array of stuff
$a = array();
$a['name'] = 'Robert';
$a['id'] = 23;
 
// Add the singleton
$a['dummy'] = $o;
 
// Serialize it
$s = serialize($a);
?>

The serialized output from this yields:

a:3:{s:4:"name";s:6:"Robert";s:2:"id";i:23;s:5:"dummy";C:14:"DummySingleton":187:{a:4:{s:5:"dProp";s:19:"I was finally built";s:6:"dPropX";s:25:"Nothing to see here folks";s:5:"_prop";s:16:"y u try see dis?";s:14:"setFromOutside";s:30:"What the hell is this madness?";}}}

If you take that string and subsequently load it and unserialize it then inspect it, you’ll see that the singleton object has been restored along with all private properties of it:

<?php
// $s is our serialized string from above
$o = unserialize($s);
var_dump($o);
?>

Output:

array(3) {
  ["name"]=>
  string(6) "Robert"
  ["id"]=>
  int(23)
  ["dummy"]=>
  object(DummySingleton)#1 (3) {
    ["dProp"]=>
    NULL
    ["dPropX"]=>
    string(25) "Nothing to see here folks"
    ["_prop":"DummySingleton":private]=>
    string(16) "y u try see dis?"
  }
}

Since this is, in essence, the process that PHP follows for its default session management it’s safe to say that you can, indeed, store singleton objects in a PHP session. Now onto to bigger and better questions, like…

Why would you ever want to store a singleton object instance in a PHP session?

Newest title: Book reviewer

A few days ago I received an email from Packt Publishing, “a UK based publishing firm specializing in focused IT books” asking if I would be willing to review a new book they are publishing entitled Zend Framework 1.8 Web Application Development. The book, written by Keith Pope, appears to cover the basics of using the Zend Framework to build web applications rapidly.

According the book description:

The Zend Framework has a flexible architecture that lets you build modern web applications and web services easily. The MVC components make the maintenance and testing of your applications easier. However, it is not only an MVC framework for developers. It also provides an easy-to-use high-quality component library that is designed to be used the way you want, picking up specific components without requiring the use of whole framework.

It’s easy to get started and produce a powerful and professional looking web site when you’ve got this book to hand. Taking you through a real-life application, it covers the major Zend Framework components, as well as throwing light on the best practices and design issues faced when building complex MVC applications.

This book takes you through detailed examples as well as covering the foundations you will need to get the most out of the Zend Framework. From humble beginnings you will progress through the book and slowly build upon what you have learned previously. By the end, you should have a good understanding of the Zend Framework, its components, and the issues involved in implementing a Zend Framework based application.

I am actually looking forward to reading what Keith has put together. With some of the more recent improvements to the Zend Framework I have been really considering putting the framework to use in a project. Hopefully having examples to follow will point me in the proper direction.

Regardless, I am looking forward to reading what Keith has to say about developing with the Zend Framework. And if nothing else, at least I get a free chapter of a new PHP book out of the deal. 😉

Getting books details by ISBN in PHP

Sometimes I love being a geek. Today, as I set out to inventory my collection of almost 500 books or so, I wanted to find a fast way to get the information on the book I wanted based on the books ISBN. This was because I was already getting tired of typing five books into the inventory (yes, I am that lazy) and I really did not want to keep typing out the authors name, the title and the subtitle for each book.

So I went to ISBNdb.com and entered an ISBN thinking I would be able to just copy and paste the book information from the output. That turned out to be overwhelmingly difficult since their output of the search is really convoluted. I knew what I wanted to get and they didn’t offer that.

But they did offer an API and, after reading their docs, I realized that I could write a script that would take an ISBN and return to me the information I was looking for in a way that I could just copy and paste it. Remarkably, it was faster and easier than I thought it would be. I actually developed this little snippet, freely available for you here, in about 5 minutes. Hope it helps you in some way, if you are looking for such a thing.

NOTE: Before using this code make sure to sign up for your own API key. In order to do that you will need to register for an account with ISBNdb.com and then create a key. But as soon as you do you will have immediate access to their API. The API is simple, responding to the request with a simple XML output. Anyhow, without further ado, here is the little script I put together to fetch me the data I was looking for the way I wanted it.

<?php
/**
 * Set this value to your own API key
 */
$apikey = '12345678';
 
/**
 * Initialize this var for use when forms are not posted
 */
$isbn = null;
 
/**
 * Initialize the result set var
 */
$rs = null;
 
/**
 * See if the form is posted
 */
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  /**
   * Get the ISBN from the form
   * 
   * No, there is no validation on this. This 
   * was for me and I knew I would not be at
   * all trying to trick my own script. USE 
   * THIS AS IS AT YOUR OWN PERIL.
   */
  $isbn = $_POST['isbn'];
 
  /**
   * Get the result as a SimpleXML object
   */
  $rs = simplexml_load_file("http://isbndb.com/api/books.xml?access_key=$apikey&index1=isbn&value1=$isbn");
}
?>
<html>
<head><title>ISBN Check</title></head>
<body>
<form method="post" action="<?php echo basename(__FILE__) ?>">
  <p>
    Enter an ISBN:<br />
    <input type="text" size="40" name="isbn" id="isbn" value="<?php echo $isbn ?>" />
  </p>
  <p>
    <input type="submit" name="submit" value="Search ISBN" />
  </p>
</form>
<?php
/**
 * Only output more stuff if there is a result
 */
if ($rs) : ?>
<hr />
Results for ISBN: <?php echo $isbn ?>:
<?php 
/**
 * Results for a book are in $rs->BookList->BookData
 * 
 * You can see this using var_dump($rs);
 */ 
$book = $rs->BookList->BookData;
?>
<p>
  <strong><?php echo $book->Title; ?></strong><br />
  <?php echo !empty($book->TitleLong) ? $book->TitleLong . '<br />' : null; ?>
  <?php echo $book->AuthorsText; ?><br />
  <?php echo $book->PublisherText; ?><br />
  <?php echo $isbn; ?>
</p>
<?php endif; ?>
</body>
</html>

Typical output might look like (from one of the books I was checking on):


Results for ISBN: 0316116955:

The day the universe changed
James Burke
Boston : Little, Brown, c1985.
0316116955


I hope you enjoy this, if you happen to be looking for an ISBN search tool that you can run on your own. 😉

Microsoft Expression Web Super Preview

I just read an article on ZDNet that mentioned a recent “showing off” of Expression Web SuperPreview by Microsoft. SuperPreview allows web developers to view and debug web output and rendering as it would appear in Internet Explorer 6, 7 and 8. And I can’t help but wonder… why would we need a tool to check rendering if Microsoft actually handled rendering properly to begin with?

I am glad they have introduced this tool. Before this you had to install an application that would literally install multiple versions of IE on your machine. Then you would need to load your page in a new instance of whatever version you wanted to test. That really sucked. So having the option to inspect your rendering in one app across multiple versions of IE is definitely a boon. But still, why should you have to do that?

And speaking of browsers, a friend of mine the a few weeks back brought up a point that I still enjoy… why are we still coding for browser based output anyway? The web as we know it is totally breaking out of the browser. Why are there still cross-browser compatibility issues and rendering problems?

While I applaud Microsoft on their efforts to help developers code for their broken, crappy, waste-of-software browser, I think I am leaning more towards my friend’s way of thinking. Maybe it is time to start thinking outside the browser box?

Regardless, if you are a developer developing on Windows and you need a tool that will help you see how things are going to work for you in IE 6, 7 and 8, this might be the tool for you.

Fun with PHP

Every now and again someone writes a line or two of code that really makes me smile. Such is the case with this outcome determinating and decision making class below. This code is being reproduced, with or without consent, from the PHP Developers Network‘s own scottayy.

<?php
/**
 * Coin flipper class helps determine outcome of situations in which an outcome
 * cannot be decided by sheer manpower alone.
 * 
 * @author Scott Martin <scottayy@devnetwork.net>
 * @license None, don't even try to use this or your hair will turn yellow
 */
class coin {
	/**
	 * The outcome determinators
	 * 
	 * Each invocation of this object will require a determinator upon which the
	 * object relies to build a determined outcome. These are those determinators.
	 * 
	 * @access private
	 * @var array
	 */
	private static $_sides = array('heads', 'tails');
 
	/**
	 * The determinating method
	 * 
	 * This method, when called, invokes a determination sequence and returns a
	 * determined value for use in decision making.
	 * 
	 * @access public
	 * @return string Randomly selected determinator
	 */
	public static function flip() {
		// Quick, randomize me some determinators
		shuffle(self::$_sides);
 
		// Quick, offer it back before it gets angry
		return self::$_sides[mt_rand(0, 1)];
	}
}
 
/**
 * We should always test our determinating decision establisher
 *
 * 2,4,6,8 You know you want to determinate
 */
echo coin::flip();
?>

For those that just have to have an object to instantiate (and you know who you are), there is this lightly modified version for your obsessive/compulsive selves:

<?php
/**
 * Coin flipper class helps determine outcome of situations in which an outcome
 * cannot be decided by shear manpower alone.
 * 
 * @author Scott Martin <scottayy@devnetwork.net>
 * @license None, don't even try to use this or your hair will turn yellow
 */
class coin {
	/**
	 * The outcome determinators
	 * 
	 * Each invocation of this object will require a determinator upon which the
	 * object relies to build a determined outcome. These are those determinators.
	 * 
	 * @access private
	 * @var array
	 */
	private $_sides = array('heads', 'tails');
 
	/**
	 * The determinating method
	 * 
	 * This method, when called, invokes a determination sequence and returns a
	 * determined value for use in decision making.
	 * 
	 * @access public
	 * @return string Randomly selected determinator
	 */
	public function flip() {
		// Quick, randomize me some determinators
		shuffle($this->_sides);
 
		// Quick, offer it back before it gets angry
		return $this->_sides[mt_rand(0, 1)];
	}
}
 
/**
 * We should always test our determinating decision establisher
 */
$coin = new coin;
 
/**
 * 2,4,6,8 You know you want to determinate
 */
echo $coin->flip();
?>

See, just looking at that code makes you want to smile doesn’t it? Geeks are great.

How would improve the look of this site?

I have made a good many changes to this theme in the few days that it has been alive. Since its launch a few day ago I have asked for critiques and constructive criticism from the PHP Developers Network. However, I think it might be better to ask your opinion as well seeing you might not visit the PHPDN community (tsk, tsk).

So I ask you, dear reader, if you were going to improve upon the way this theme appears, what would you do? What changes would you make if you were the designer?

I appreciate any responses you provide. I am looking forward to making this theme a usable, intuitive, clean interface and could use any and all feedback presented.

Thanks.

A bit of irony in the PHP world

According to an article today by TechCrunch, Zend Technologies, The PHP company, is cutting 25% of their PHP developer staff, perhaps with an eye towards selling the company.

Israeli startup Zend Technologies has fired 25 percent of its R&D team (at least ten people), as well as others across the company, in an attempt to become cash flow positive, says a source close to the company. A spokesperson from the company’s PR firm says: “Yes, I can confirm that Zend made the layoffs, but we cannot comment on the numbers or reasons for the action.”

Read the complete TechCrunch article here.

As I read the brief article I began to think that this is not really anything that should be too newsworthy. Many companies in the USA, and around the world in general, are feeling the pinch of a down economy. Companies have to do what they can to reduce cost while maintaining competitive prices for goods and services. What Zend is doing is not really that out of the ordinary.

And I am not sure that Zend, as a company, is really worth a huge amount of money like the Sun Microsystems acquisition of MySQL was. It might be tasty to some of the players in the industry right now like Oracle, IBM or even a Sun. But really, other than the Zend engine and the Zend IDE what exactly does Zend have to offer?

Whatever happens to Zend from all of this one thing is very important to remember. Many a PHP developer now has the opportunity to seek gainful employment from other companies that are seeking, heavily, PHP talent. Many Silicon Valley companies, including many companies in the social networking space, are looking for top tier PHP talent right now. Companies like Ning, Digg, Facebook, Technorati, Yahoo and Google are constantly hiring PHP developers.

Times are good for being a PHP developer. Maybe not so much if you worked for Zend. Nonetheless, now is a great time to know a great deal about PHP.