2009-12-07 3 views
10

Je suis dans une situation où je dois instancier une classe avec des arguments provenant d'une instance d'une autre classe. Voici le prototype:PHP: Comment instancier une classe avec des arguments provenant d'une autre classe

//test.php 

class test 
{ 
    function __construct($a, $b, $c) 
    { 
     echo $a . '<br />'; 
     echo $b . '<br />'; 
     echo $c . '<br />'; 
    } 
} 

Maintenant, je dois instancier ci-dessus classe en utilisant ci-dessous cls de classe fonction:

class myclass 
{ 
function cls($file_name, $args = array()) 
{ 
    include $file_name . ".php"; 

    if (isset($args)) 
    { 
     // this is where the problem might be, i need to pass as many arguments as test class has. 
     $class_instance = new $file_name($args); 
    } 
    else 
    { 
     $class_instance = new $file_name(); 
    } 

    return $class_instance; 
} 
} 

Maintenant, lorsque je tente de créer une instance de classe de test en passant des arguments à elle:

$myclass = new myclass; 
$test = $myclass->cls('test', array('a1', 'b2', 'c3')); 

il donne l'erreur: Argument manquant 1 et 2; seul le premier argument est passé.

Cela fonctionne très bien si j'instancie une classe qui n'a aucun argument dans sa fonction de constructeur.

Pour les développeurs PHP expérimentés, ce qui précède ne devrait pas poser de problème. S'il vous plaît aider.

Merci

+0

Non lié à votre question, mais $ args sera toujours 'isset' puisque vous lui attribuez array() dans la définition de la fonction. Vous pouvez être intéressé par 'empty', ou' $ args = null'. – Tordek

+0

Je suis désolé, ce n'est pas non plus lié à votre question, mais ce que vous faites n'est pas cool. la réponse à votre question est la suivante: laissez votre constructeur prendre un tableau, avoir des attributs de classe, puis traiter le tableau et le mapper aux attributs de la classe. Mais encore une fois, vous faites quelque chose qui n'est pas cool. – DarthVader

+0

la classe de test et les autres doivent être faits par d'autres développeurs en utilisant leur propre manière avec des arguments et sans lui, donc je ne veux pas les limiter à seulement passer des arguments en tant que tableau aux constructeurs. – Sarfraz

Répondre

28

vous avez besoin Réflexion http://php.net/manual/en/class.reflectionclass.php

if(count($args) == 0) 
    $obj = new $className; 
else { 
    $r = new ReflectionClass($className); 
    $obj = $r->newInstanceArgs($args); 
} 
+0

Je suis vraiment inspiré par les connaissances que Stereofrog a parce que la plupart des gens ne connaissent même pas la classe de réflexion et je ne savais pas que nous pouvions utiliser la classe de réflexion pour transmettre des arguments de cette façon. Il a résolu mon problème, je n'ai pas pu trouver la solution pendant plusieurs jours. Même les développeurs les plus expérimentés n'ont pas été en mesure de fournir une réponse satisfaisante à ma question, ce qui est très important et tout le monde ici devrait se pencher sur ce scénario de la question. Quoi qu'il en soit, je suis très heureux de trouver une solution à cette question très importante. Merci stereofrog :) – Sarfraz

+1

Je cherchais une solution de base non-réflexion, mais on dirait que j'ai dû recourir à cela. Zut. – yclian

4

Vous pouvez:

1) Modifier la classe de test pour accepter un tableau qui contient les données que vous souhaitez passer.

//test.php 

class test 
{ 
     function __construct($a) 
     { 
       echo $a[0] . '<br />'; 
       echo $a[1] . '<br />'; 
       echo $a[2] . '<br />'; 
     } 
} 

2) initié à l'aide d'une méthode d'utilisateur au lieu du constructeur et appeler à l'aide de la fonction call_user_func_array().

//test.php 

class test 
{ 
     function __construct() 
     { 

     } 

     public function init($a, $b, $c){ 
       echo $a . '<br />'; 
       echo $b . '<br />'; 
       echo $c . '<br />'; 
     } 

} 

Dans votre classe principale:

class myclass 
{ 
function cls($file_name, $args = array()) 
{ 
     include $file_name . ".php"; 

     if (isset($args)) 
     { 
       // this is where the problem might be, i need to pass as many arguments as test class has. 
       $class_instance = new $file_name($args); 
       call_user_func_array(array($class_instance,'init'), $args); 
     } 
     else 
     { 
       $class_instance = new $file_name(); 
     } 

     return $class_instance; 
} 
} 

http://www.php.net/manual/en/function.call-user-func-array.php

Enfin, vous pouvez laisser votre constructeur params vide et utiliser func_get_args().

//test.php 

class test 
{ 
     function __construct() 
     { 
       $a = func_get_args(); 
       echo $a[0] . '<br />'; 
       echo $a[1] . '<br />'; 
       echo $a[2] . '<br />'; 
     } 
} 

http://sg.php.net/manual/en/function.func-get-args.php

1

Vous pouvez utiliser call_user_func_array() je crois.

ou vous pouvez laisser la liste des arguments du constructeur, puis à l'intérieur du constructeur utiliser cette

$args = func_get_args(); 
+0

La première partie de cette réponse aide à appeler le constructeur; la seconde partie pourrait aider dans cette classe à rendre l'interface plus agréable (il suffit de passer les arguments au lieu de les placer dans un tableau). – Tordek

1
class textProperty 
{ 
    public $start; 
    public $end; 
    function textProperty($start, $end) 
    { 
     $this->start = $start; 
     $this->end = $end; 
    } 

} 

objet $ = new TextProperty ($ début, $ fin);

ne fonctionnent pas?

0

La meilleure façon que je l'ai trouvé:

if ($depCount === 0) { 
      $instance = new $clazz(); 
     } elseif ($depCount === 1) { 
      $instance = new $clazz($depInstances[0]); 
     } elseif ($depCount === 2) { 
      $instance = new $clazz($depInstances[0], $depInstances[1]); 
     } elseif ($depCount === 3) { 
      $instance = new $clazz($depInstances[0], $depInstances[1], $depInstances[2]); 
     } 

Désolé un peu cru, mais vous devez comprendre l'idée.

Questions connexes