• No results found

Sample Introspection Program

In document programming PHP pdf (Page 150-158)

Example 6-2 shows a collection of functions that displaya reference page of informa- tion about an object’s properties, methods, and inheritance tree.

Introspection | 151

Example 6-2. Object introspection functions

// return an array of callable methods (include inherited methods) function get_methods($object) {

$methods = get_class_methods(get_class($object)); if(get_parent_class($object)) {

$parent_methods = get_class_methods(get_parent_class($object)); $methods = array_diff($methods, $parent_methods);

}

return $methods; }

// return an array of inherited methods function get_inherited_methods($object) {

$methods = get_class_methods(get_class($object)); if(get_parent_class($object)) {

$parent_methods = get_class_methods(get_parent_class($object)); $methods = array_intersect($methods, $parent_methods);

}

return $methods; }

// return an array of superclasses function get_lineage($object) { if(get_parent_class($object)) { $parent = get_parent_class($object); $parent_object = new $parent;

$lineage = get_lineage($parent_object); $lineage[] = get_class($object); } else { $lineage = array(get_class($object)); } return $lineage; }

// return an array of subclasses function get_child_classes($object) { $classes = get_declared_classes( ); $children = array( ); foreach($classes as $class) { if (substr($class, 0, 2) == '_ _') { continue; }

$child = new $class;

$children[] = $class; }

}

return $children; }

// display information on an object function print_object_info($object) { $class = get_class($object); echo '<h2>Class</h2>'; echo "<p>$class</p>"; echo '<h2>Inheritance</h2>'; echo '<h3>Parents</h3>'; $lineage = get_lineage($object); array_pop($lineage);

echo count($lineage) ? ('<p>' . join(' -&gt; ', $lineage) . '</p>') : '<i>None</i>';

echo '<h3>Children</h3>';

$children = get_child_classes($object);

echo '<p>' . (count($children) ? join(', ', $children) : '<i>None</i>') . '</p>'; echo '<h2>Methods</h2>'; $methods = get_class_methods($class); $object_methods = get_methods($object); if(!count($methods)) { echo "<i>None</i><br />"; } else {

echo '<p>Inherited methods are in <i>italics</i>.</p>'; foreach($methods as $method) {

echo in_array($method, $object_methods) ? "<b>$method</b>( );<br />" : "<i>$method</i>( );<br />"; } } echo '<h2>Properties</h2>'; $properties = get_class_vars($class); if(!count($properties)) { echo "<i>None</i><br />"; } else { foreach(array_keys($properties) as $property) {

echo "<b>\$$property</b> = " . $object->$property . '<br />'; }

}

echo '<hr />'; }

Serialization | 153

Here are some sample classes and objects that exercise the introspection functions from Example 6-2:

class A {

var $foo = 'foo'; var $bar = 'bar'; var $baz = 17.0;

function first_function( ) { } function second_function( ) { } };

class B extends A { var $quux = false;

function third_function( ) { } }; class C extends B { }; $a = new A; $a->foo = 'sylvie'; $a->bar = 23; $b = new B; $b->foo = 'bruno'; $b->quux = true; $c = new C; print_object_info($a); print_object_info($b); print_object_info($c);

Figure 6-2 shows the output of this code.

Serialization

Serializingan object means converting it to a bytestream representation that can be stored in a file. This is useful for persistent data; for example, PHP sessions automati- callysave and restore objects. Serialization in PHP is mostlyautomatic—it requires lit- tle extra work from you, beyond calling theserialize( ) andunserialize( ) functions:

$encoded = serialize(something); $something = unserialize(encoded);

Serialization is most commonlyused with PHP’s sessions, which handle the serializa- tion for you. All you need to do is tell PHP which variables to keep track of, and they’re automatically preserved between visits to pages on your site. However, ses- sions are not the only use of serialization—if you want to implement your own form of persistent objects, theserialize( ) andunserialize( ) functions are a natural choice.

An object’s class must be defined before unserialization can occur. Attempting to unserialize an object whose class is not yet defined puts the object into stdClass, which renders it almost useless. One practical consequence of this is that if you use PHP sessions to automaticallyserialize and unserialize objects, you must include the file containing the object’s class definition in everypage on your site. For example, your pages might start like this:

<?php

include('object_definitions.inc'); // load object definitions session_start( ); // load persistent variables ?>

<html>...

Serialization | 155

PHP has two hooks for objects during the serialization and unserialization process: _ _sleep( )and _ _wakeup( ). These methods are used to notifyobjects that they’re being serialized or unserialized. Objects can be serialized if theydo not have these methods; however, they won’t be notified about the process.

The_ _sleep( )method is called on an object just before serialization; it can perform anycleanup necessaryto preserve the object’s state, such as closing database connec- tions, writing out unsaved persistent data, and so on. It should return an arraycon- taining the names of the data members that need be written into the bytestream. If you return an empty array, no data is written.

Conversely, the _ _wakeup( ) method is called on an object immediatelyafter an object is created from a bytestream. The method can take any action it requires, such as reopening database connections and other initialization tasks.

Example 6-3 is an object class,Log, which provides two useful methods:write( )to append a message to the logfile, andread( )to fetch the current contents of the log- file. It uses_ _wakeup( ) to reopen the logfile and_ _sleep( ) to close the logfile.

Example 6-3. The Log.inc file

<?php class Log { var $filename; var $fp; function Log($filename) { $this->filename = $filename; $this->open( ); } function open( ) {

$this->fp = fopen($this->filename, "a")

or die("Can't open {$this->filename}"); }

function write($note) { fwrite($this->fp, "$note\n"); }

function read( ) {

return join('', file($this->filename)); }

function _ _wakeup( ) { $this->open( ); }

function _ _sleep( ) {

Store theLogclass definition in a file calledLog.inc. The HTML page in Example 6-4 uses theLog class and PHP sessions to create a persistent log variable,$l.

The output when this page is viewed is shown in Figure 6-3. fclose($this->fp); return array('filename'); } } ?> Example 6-4. front.php <?php include_once('Log.inc'); session_start( ); ?> <html><head><title>Front Page</title></head> <body> <?php $now = strftime("%c"); if (!session_is_registered('l')) { $l = new Log("/tmp/persistent_log"); session_register('l'); $l->write("Created $now");

echo("Created session and persistent log object.<p>"); }

$l->write("Viewed first page $now"); echo "The log contains:<p>"; echo nl2br($l->read( )); ?>

<a href="next.php">Move to the next page</a> </body></html>

Figure 6-3. The front page

Serialization | 157

Example 6-5 shows the file next.php, an HTML page. Following the link from the front page to this page triggers the loading of the persistent object$l. The_ _wakeup( ) call reopens the logfile so that the object is ready to be used.

Figure 6-4 shows the output ofnext.php.

Example 6-5. next.php <?php include_once('Log.inc'); session_start( ); ?> <html><head><title>Next Page</title></head> <body> <?php $now = strftime("%c");

$l->write("Viewed page 2 at $now"); echo "The log contains:<p>"; echo nl2br($l->read( )); ?>

</body></html>

Chapter 7

CHAPTER 7

In document programming PHP pdf (Page 150-158)