Serializing Objects Into Session Data For Object Persistence in PHP

Posted by Tres Sun, 11 May 2008 14:18:00 GMT

One of the biggest problems that we find in the realm of PHP web applications is that there is no native object persistence between page requests. Clients getting around in a PHP application normally means instantiating and re-instantiating objects as needed. A page that needs access to the Client object wound create a new Client() every time client data were needed, or keep a bunch of global variables held in session data.

Because of the way some web applications are engineered, for some unfortunate databases, this meant that every page hit was another call to the database to populate the instance variables associated with the current client. For some unfortunate web app maintainers, this meant that they needed to figure out why their global session variable wasn't returning expected results.

An easy way to get around this is to use session variables to store objects. It is almost just like object serialization to a file in Java; however, PHP won't serialize anything but the single object you want to store; it doesn't take care of class parents, interfaces being implemented or any other instantiated objects that may be required to maintain state. In PHP the developer is responsible for making sure that any object dependencies are also serialized and de-marshalled as needed.

The upside is that PHP will not only allow you to serialize your objects, but makes the serialization, marshaling process automatic.

So if you're using sessions for your site anyway, you can get object persistence for free. Just assign your object by reference to the session variable that you want to use. So, for our Client example above, we'd do something like this:

$client_object = &$_SESSION['client_object'];
$client_object = new Client( $client_id );

print( "First Name: " . $client_object->getClientFname() . "\n" );
print( "Last Name: " . $client_object->getClientLname() . "\n" );
print( "Balance Due: " . $client_object->getClientBalance() . "\n" );

One caveat here is that your class must be defined before the session_start() function call is made in your program. This is easy if you're using an __autoload() function to provide access to your classes; just place the session_start() call after your __autoload() and everything should Just Work.

Posted in ,  | Tags , , ,

Using PHP __autoload() For Better OOP Class Management

Posted by Tres Sat, 19 Apr 2008 08:42:00 GMT

Keeping your classes well organized is an extremely important process once you reach the point where you’re dealing with hundreds of classes and thousands of lines of code. One of the ways that Java implicitly facilitates better organization is by forcing classes into their own files.

Unlike Java, where strict conventions make loading of called classes automatic, with PHP, you can put your classes anywhere, just as long as they’re in a file that the interpreter knows about via an include or require.

This kind of organization is just fine if you’re working on a smaller code base, but quickly breaks down when you’re dealing with a larger project; however,PHP does offer the built-in function __autoload() which automatically attempts to load any class or interface which hasn’t been defined yet. So you can take advantage of single-class files without needing to include (potentially) hundreds of files.

The only thing is, you’ve got to put together the _autoload yourself. Here’s the implementation of _autoload() that I’m currently using. It will load classes, interfaces and configuration files. It uses setincludepath() to define where it should be looking for files.


/**
 * 
 *  
 *
 * @copyright 2008
 * @package ProjectX
 * @subpackage SystemConf
 * @author Tres Wong-Godfrey
 * 
 */


define( "LIBRARY", "/usr/local/emersius/projectx/library/" );

define( "COMMON_LIBRARY", "/usr/local/emersius/common/" );

define( "CONF_DIR", "/usr/local/emersius/conf/" );


/**
 * 
 * Object autoloader for projectX
 * 
 * @access public
 * @param string The name of the class being loaded
 *
 */
function __autoload($class)
{
    //turn down the volume of error reporting while we're running the autoloader so we don't get warnings from the include_once() calls.
    $old_error_reporting_level = error_reporting( 1 );
    try {
        switch( TRUE ) {
            case include_once("class.${class}.php"):
            return;

            case include_once("intf.${class}.php"):
            return;

            case include_once( "conf.${class}.php" ):
            return;

            default:
            throw new FileNotFoundException(__CLASS__.'::'.__FUNCTION__ . "Fault occured in ".__FUNCTION__. "can not find incldued library ${class}.\n");

        }
    } catch( FileNotFoundException $e ) {
        die( $e->getMessage() . "\n" . $e->getTraceAsString() );
    }

    //turn the error reporting back up to what it was
    error_reporting( $old_error_reporting_level );


}

/**
 * Sets the path where we will look for files when they
 * are requested.
 */
set_include_path(
        get_include_path()
        .PATH_SEPARATOR.LIBRARY
        .PATH_SEPARATOR.CONF_DIR
        .PATH_SEPARATOR.COMMON_LIBRARY
        .PATH_SEPARATOR.COMMON_LIBRARY."/classes/"
        .PATH_SEPARATOR.COMMON_LIBRARY."/classes/logging/"
        .PATH_SEPARATOR.COMMON_LIBRARY."/classes/exceptions/"
        .PATH_SEPARATOR.COMMON_LIBRARY."/classes/models/"
        .PATH_SEPARATOR.COMMON_LIBRARY."/interfces/"
);

Posted in , ,  | Tags , , , , ,