Page 1 of 2
Dynamic object instantiation -- oh joy!
Posted: Tue Aug 08, 2006 8:05 pm
by neophyte
Code: Select all
public function load_obj( $class, $handle, $args = null){
if(class_exists($class)){
$obj = $$handle = new $class;
}
$this->set_obj( $obj, $handle );
}
I'm trying to write a method that dynamically instantiates a class.
This little bit I wrote works. It creates an object. But what I haven't been able to get work is adding $args to $class for constructor arguments. I'm not sure how this is done. Every string solution I've tried has failed. (I've tried making args an array and implode it to a string.) Any ideas?
Tanks!
Posted: Tue Aug 08, 2006 8:07 pm
by Jenk
Factory and/or Service Locator Pattern.
This thread will be of use:
viewtopic.php?t=51794
Posted: Tue Aug 08, 2006 8:12 pm
by volka
ReflectionClass can do it
Code: Select all
<?php
class foo {
public function __construct($a, $b) {
echo $a, ' : ', $b;
}
}
$args = array(3, 'a');
$rc = new ReflectionClass('foo');
$obj = $constructor = $rc->newInstanceArgs($args);
var_dump($obj);
?>
Re: Dynamic object instantiation -- oh joy!
Posted: Tue Aug 08, 2006 9:12 pm
by Christopher
I believe this works:
You can use eval or reflection otherwise.
Posted: Tue Aug 08, 2006 9:13 pm
by neophyte
Jenk wrote:Factory and/or Service Locator Pattern. :)This thread will be of use:
viewtopic.php?t=5179
Okay I read the thread and I have one thing I'm not sure about. Why was this chosen over
Code: Select all
eval("\$this->instances['$name'] =& new {$name}(" . implode(', ', $arglist) . ');');
this method?
Code: Select all
$this->instances[$name] = new $name($this->args[$name]);
Posted: Tue Aug 08, 2006 9:17 pm
by Christopher
The eval method allows any number of args. Usually $arglist is built from args from the variable arg functions. The second only allows one arg.
Note - There is a loop before the eval() that builds the $arglist.
Posted: Tue Aug 08, 2006 9:18 pm
by Luke
<-- still looking for a way to not use eval
EDIT: Oh and I actually don't even use that class now
But instead I have turned that class into an abstract class and subclassed registries for more specific tasks.... (request, session, etc) and then I use __autoload in combination with pear naming to load the classes. Works well

Posted: Tue Aug 08, 2006 9:37 pm
by neophyte
arborint wrote:The eval method allows any number of args. Usually $arglist is built from args from the variable arg functions. The second only allows one arg.
Note - There is a loop before the eval() that builds the $arglist.
Just discovered that one for myself. It must be the comma that is not evaluated as code but as a string.
Thanks to you and the Space Goat for exploring this pattern to the hilt. I think I've found most of what I was looking for.
And yes __autoload for PHP 5 is the way to go for inclusion -- it being triggered by class_exists()
Posted: Tue Aug 08, 2006 10:30 pm
by Jenk
just use include_once/require_once within __autoload()
Posted: Tue Aug 08, 2006 11:16 pm
by neophyte
Here's what I got so far... Feel free to comment.
Code: Select all
class gg_registry{
private $stack;
/**
* Everything needed to instantiate the requested class
* Thanks to "The Ninja Space Goat" and "Aborint" at
* devnetwork for their help on this method.
*
* @static
* @param $class The name of the class to instantiate
* @param $handle The name of the object
* @param array $args an array of arguments to pass to the constructor
*/
public function load_obj($class, $handle, array $args) {
$argslist = array();
if(class_exists($class)){
if( empty($args) ){
$obj = $$handle = new $class;
} else {
//Arguments to process
$n = count($args);
for ($i=0; $i<$n; ++$i) {
$arglist[$i] = "\$args[$i]";
}
eval ("$" . "object = new {$class}(" . implode(', ', $arglist) . ');');
}
}
$this->set_obj( &$object, $handle);
}
/**
* This function is used for retrieving the registry obj in
* preparation for accessing objects it holds.
*
* @return object returns a registry object
*/
public static function &instance(){
static $reg;
if (!$reg){
$reg = new gg_registry;
}
return $reg;
}
/**
* Adds objects and variables to the stack. Use if the object is already
* instantiated. Works great for data objects or when load_obj for whatever
* reason doesn't yield desirable results.
*
* @access public
* @param object $object the object to be inserteregistry_test.phpd into the $GLOBALS container
* @param string $handle optional name of class to be made globally accessible
*/
public function set_obj( &$object, $handle = '' ){
$class = (empty($handle))? get_class($object): $handle;
$this->stack[$class] = $object;
}
/**
* A "getter" for retrieving objects from the registry.
*
* @access public
* @param string $handle The name of the class to retrieve from the $GLOBALS array or the handle for the variable
*/
public function &get_obj($handle){
return $this->stack[$handle];
}
} // end class
/**
* Automatically includes code for requested class
*
* @param string $classname
*/
function __autoload($classname){
if(strstr($classname, 'module')){
$path = $_SERVER['DOCUMENT_ROOT'].'modules/';
} else {
$path = $_SERVER['DOCUMENT_ROOT'].'lib/';
}
$ext = ".php";
$classname = substr_replace( $classname, '',0,3);
include_once($path.$classname.$ext);
}
Posted: Tue Aug 08, 2006 11:19 pm
by Jenk
Have a look in this thread re: use of eval() for args:
viewtopic.php?t=53274
Posted: Tue Aug 08, 2006 11:23 pm
by Luke

I believe that's the first time anybody has ever credited me in any type of code or even acknowledged me as a programmer.

Posted: Wed Aug 09, 2006 12:48 am
by Christopher
We started a thread around there to take a Registry to the next level and turn it into a Service Locator. I made a list of requirements. If we could come up with a Service Locator then Dependency Injection is just around the corner.
Posted: Thu Dec 21, 2006 4:54 pm
by daedalus__
Are you using php4?
volka wrote:ReflectionClass can do it
Code: Select all
<?php
$rc = new ReflectionClass('foo');
$obj = $rc->newInstanceArgs($args);
?>
Posted: Thu Dec 21, 2006 6:11 pm
by volka
Not the freshest thread, is it?
Daedalus- wrote:Are you using php4?
Who's addressed by this question?