Here is a good post for:
http://fr.php.net/manual/fr/function.call-user-func-array.php
################################################################
from taylor
08-May-2005 12:04
<?php
/**
* Create an object of a specified type using an array as the parameters
* to the constructor. NOTE: does not maintain proper
* types for the arguments. They are all converted to strings.
* @param $type Type type of object to create (class name)
* @param $args The arguments to pass to the constructor
*/
function createObjArray($type, $args=array()) {
if ( !class_exists($type) ) {
return NULL;
}
// build argument list; be sure to escape string delimeters
$func = create_function('$str', 'return str_replace("\'","\\\'",
$str);');
$sargs = "'" . join( "','", array_map($func,$args) ). "'";
// build & eval code; return result
$seval = "return new $type($sargs);";
return eval($seval);
}
?>
#################################################################
I dont like eval too but i think that is depending on the pb we want to
solve... if you can change contrutor from each object may be better to use
jockem solution that is more secure (added some change for php4).
#################################################################
class Test
{
var $v;
// constructor for php4
function Test($args){
$this->__construct($args);
}
// constructor for php5
function __construct($args = array())
{
extract((array) $args);
$this->v=$v;
}
}
$className = "Test";
$construct_params = array("v"=>"param1","param2","param3");
//if (class_exists($className, false)) { ---> for php5
if (class_exists($className)) { // for php4
$obj = new $className($construct_params);
} else {
die("Hack off mate.");
}
var_dump($obj);
##################################################################
// I had to test this to see if it works! the first 2 attempts are
bogus // but you can run them to see what happens -- also the 3 attempt is
a pretty // weird construction and I would be interested to know if anybody
has thoughts // on calling the ctor in this way (essentially calling it
twice) //
Never see a such solution, but may use a register funct instead...
##################################################################
class Test
{
var $v;
function Register($objName, $v=1){
# auto register object if needed
if(!isset($GLOBALS[$objName])){
$GLOBALS[$objName]=true;
$GLOBALS[$objName]=new Test($v);
}else{
return $GLOBALS[$objName];
}
}
function Test($v){
$this->__construct($v);
}
function __construct($v)
{
$this->v=$v;
}
}
$className = "Test";
$construct_params = array("obj", "param1","param2","param3");
//if (class_exists($className, false)) { ---> for php5
if (class_exists($className)) { // for php4
call_user_func_array(array(($className), "Register"), $construct_params);
} else {
die("Hack off mate.");
}
var_dump($obj);
##################################################################
Love phpsec too ;-)
Hope this finaly help!
Olivier
Le Mercredi 22 Juin 2005 11:38, Jochem Maas a écrit :
olivier wrote:
Hi,
I answered this also, but apparently I only replied to the OP...
(reproduced here - minus the typos in my first post on this topic :-/)
if (class_exists($className, false)) {
$obj = new $className($construct_params);
} else {
die("Hack off mate.");
}
Try something like:
$classname = "MyClass";
$construct_params = array("param1","param2","param3");
$return =null;
if(class_exists($classname)){
$param=explode(" ',' ", $construct_param);
this should be join() not explode(), but even then it won't work,
and even if it did you would only be able to pass strings (i.e. no objects,
arrays, resources, etc)
for this you should probably be looking at call_user_func_array() e.g:
class Test
{
public $v;
function __construct($v = 1) { $this->v = $v; }
}
$className = "Test";
if (class_exists($className, false)) {
// I had to test this to see if it works! the first 2 attempts are
bogus // but you can run them to see what happens -- also the 3 attempt is
a pretty // weird construction and I would be interested to know if anybody
has thoughts // on calling the ctor in this way (essentially calling it
twice) //
// ATTEMPT 1
//$obj = call_user_func_array(array($className,"__construct"),
array(3)); // ATTEMPT 2
//$obj = call_user_func_array(array(new $className,"__construct"),
array(3)); // ATTEMPT 3
call_user_func_array(array(($obj = new $className),"__construct"),
array(3));
} else {
die("Hack off mate.");
}
var_dump($obj);
# You must add here some security checks....
eval("$retrun = new $className($param)");
typo! 'retrun' (I spell 'return' like that alot too :-)
btw eval() sucks and is not really needed, although granted it's an
easy/flexible solution in terms on being able to pass args to the ctor
(constructor), my thought would be that the classes you wish to init this
way should have a specific interface/design with regard to accepting ctor
args. A very simple example:
class Test
{
function __construct($args = array())
{
extract((array) $args);
}
}
var_dump($return);
}
Hope this help!
Olivier
Le Mercredi 22 Juin 2005 05:33, Eli a écrit :
Hi,
I want to create an object in a form that I get the class name and its
parameters, and I need to create that object...
oh and don't blindly accept whatever is sent by the form - sanitize the
class name and args before you use them! best general resource for this
kind [php-]thing is (IMHO) http://phpsec.org/ [ "Shifting Expectations" ;-)
]
How can this been done?
i.e:
$classname = "MyClass";
$construct_params = array("param1","param2","param3");
/* Now create the object with the given classname and params... how? */
-thanks, Eli