note 46586 added to language.oop5.reflection
| From: | russ dot collier at NOSPAM dot gmail dot com | Date: | Sat, 16 Oct 2004 04:58:37 +0000 |
| Subject: | note 46586 added to language.oop5.reflection | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-78644@lists.php.net to get a copy of this message | ||
If you've ever wanted to do dynamic class loading in PHP5, especially when the class
you're trying to dynamically load is a Singleton (and therefore you cannot use the new
operator, and calling static methods on variable classnames produces a PHP syntax error :-) such as
$className::staticMethod()), you can do something like this example below, using the PHP5 Reflection
API:
<?php
abstract class Shape
{
/**
* Implicitly will throw an Exception from the Reflection API
*/
static public function makeShape( $shapeName )
{
$shapeInstance = null;
$shapeClass = new ReflectionClass( $shapeName );
$shapeMethod = $shapeClass->getMethod( 'getInstance' );
$shapeInstance = $shapeMethod->invoke( null );
$shapeClass = null;
$shapeMethod = null;
return $shapeInstance;
}
abstract public function doStuff();
}
class Triangle extends Shape
{
private static $instance = null;
private function __construct() { }
public static function getInstance()
{
if ( null == self::$instance )
{
self::$instance = new self;
}
return self::$instance;
}
public function doStuff() { }
}
/**
* .... Client/user code
*/
$typeOfShape = 'Triangle';
$shape = null;
try
{
$shape = Shape::makeShape( $typeOfShape );
}
catch ( Exception $e )
{
print "Error creating shape '$typeOfShape'! " . $e->getMessage() .
"\n";
}
if ( null != $shape )
{
// $shape will be an instance of Triangle
$shape->doStuff();
}
?>
So by changing the value of $typeOfShape you can dynamically load the appropriate Shape subclass at
runtime, thus facilitating a sort of plug-in style architecture for your classes. You can just drop
in new Shape subclasses and not have to modify any of the Shape class code to support these new
subclasses in the Shape::makeShape() factory method :-)
If your subclasses are all in separate files, you could even make the 'including' of these
files dynamic as well, by adding these lines to the Shape::makeShape() method after the
$shapeInstance is initialized, but before the Reflection API is called:
<?php
ini_set( 'include_path', ini_get( 'include_path' ) . PATH_SEPARATOR .
'/path/to/your/php/class/include/files' );
/**
* Assuming your subclasses are in files called 'class_$shapeName.php' :-)
* Of course doing a dynamic require() could be a security problem depending
* on how you validate/clean your $shapeName method parameter (if at all ;-))
*/
require_once( "/path/to/your/php/class/include/files/class_$shapeName.php" );
?>
----
Manual Page -- http://www.php.net/manual/en/language.oop5.reflection.php
Edit -- http://master.php.net/manage/user-notes.php?action=edit+46586
Delete -- http://master.php.net/manage/user-notes.php?action=delete+46586&report=yes
Reason: bad code -- http://master.php.net/manage/user-notes.php?action=delete+46586&report=yes&reason=bad+code
Reason: spam -- http://master.php.net/manage/user-notes.php?action=delete+46586&report=yes&reason=spam
Reason: useless example -- http://master.php.net/manage/user-notes.php?action=delete+46586&report=yes&reason=useless+example
Reason: contains commercial links -- http://master.php.net/manage/user-notes.php?action=delete+46586&report=yes&reason=contains+commercial+links
Reason: useless note -- http://master.php.net/manage/user-notes.php?action=delete+46586&report=yes&reason=useless+note
Reject -- http://master.php.net/manage/user-notes.php?action=reject+46586&report=yes
Search -- http://master.php.net/manage/user-notes.php