2008-12-25 9 views
6

J'ai 2 classes, principales et étendues. J'ai besoin d'utiliser les vars principaux en classe étendue.Utilisation de variables parents dans une classe étendue en PHP

<?php 
class Main { 
    public $vars = array(); 
} 

$main = new Main; 

$main->vars['key'] = 'value'; 

class Extended extends Main { } 

$other = new Extended; 

var_dump($other->vars); 

?> 

Qui je peux le faire?

Non valide par exemple:

<?php 
class Extended extends Main { 
    function __construct ($main) { 
    foreach ($main as $k => $v) { 
     $this->$k = $v; 
    } 
    } 
} 
?> 

J'ai besoin d'une solution plus transparente et efficace :)

+0

Je ne comprends pas. Je serais plus qu'heureux de répondre à votre question mais ce n'est pas assez clair. Voulez-vous construire "étendu" comme ($ obj = new étendu ($ main)) ou cherchez-vous des vars statiques? – nlaq

Répondre

4

EDIT: Ceci peut être résolu beaucoup mieux avec de contrôle Inversion (IoC) et Injection de dépendance (DI). Si vous utilisez votre propre cadre ou un autre sans Conteneur d'injection de dépendances essayez League/Container

Répondez ci-dessous à gauche comme l'histoire des réponses idiotes.


La bonne façon de figurer.

<?php 
class Config { 
    protected $_vars = array(); 

    protected static $_instance; 

    private function __construct() {} 

    public static function getInstance() 
    { 
     if (!isset(self::$_instance)) { 
      self::$_instance = new self(); 
     } 
     return self::$_instance; 
    } 

    public function &__get($name) { 
     return $this->_vars[$name]; 
    } 

    public function __set ($name, $value) { 
     $this->_vars[$name] = $value; 
    } 
} 

$config = Config::getInstance(); 
$config->db = array('localhost', 'root', ''); 
$config->templates = array(
    'main' => 'main', 
    'news' => 'news_list' 
); 

class DB { 
    public $db; 

    public function __construct($db) 
    { 
     $this->db = $db; 
    } 

    public function connect() 
    { 
     mysql_connect($this->db[0], $this->db[1], $this->db[2]); 
    } 
} 

$config = Config::getInstance(); 
$db = new DB($config->db); 
$db->connect(); 

class Templates { 
    public $templates; 

    public function __construct($templates) 
    { 
     $this->templates = $templates; 
    } 

    public function load ($where) { 
     return $this->templates[$where]; 
    } 
} 

$config = Config::getInstance(); 
$templates = new Templates($config->templates); 
echo $templates->load('main') . "\n"; 
+0

Je souhaite que le gars qui ne connaît pas PHP et modded moi expliquerait pourquoi. – OIS

+0

Je ne vais pas tomber en panne, mais vous manquez vraiment dans la zone de conception OOP. Vous ne devez JAMAIS étendre les classes de configuration - Les objets de configuration doivent être contenus dans les objets qui les utilisent, et non pas dans d'autres classes. Désolé, mais c'est stupide. – nlaq

+0

Je ne fais pas ça, mais c'est ce que le gars veut. Il n'a pas commencé comme une classe de config, mais c'est ce qu'il s'est avéré être ... – OIS

1

Je pense que vous devez être plus clair sur ce que vous voulez. Imaginez que vous ayez plusieurs instances de Main et Extended. Devraient-ils tous se référer aux mêmes données, de sorte que si vous modifiez les données dans l'un d'entre eux, ils sont tous affectés? Si oui, alors une approche consiste à utiliser une variable statique, qui est liée à la classe plutôt qu'à l'instance individuelle. Un autre consiste à créer un objet séparé (d'une classe différente) pour stocker vos données et les transmettre aux classes Main et Extended lorsqu'elles sont créées. Ils pourraient stocker chacun une référence à elle, par exemple .:

class Main { 
    public $data; 
    function __construct(Data $data) { 
    $this->data = $data; 
    } 
} 
class Extended extends Main {} 

$ourData = new Data(); 
$ourData->vars = array(1,2,3); 

$main = new Main($ourData); 
$other = new Extended($ourData); 

Sinon, vous voulez des copies des données, plutôt que des références aux mêmes données. Dans ce cas, votre deuxième exemple est plus proche, bien que je ne copierais pas aveuglément tous les membres.

0

oooooooooooooooooooooooooooooooooooooooooooooooooooooh

vous voulez ceci:

class Config 
{ 
    private $m_vars = array(); 

    function __get($name) 
    { 
     return $this->m_vars[$name]; 
    } 

    function & __set($name, $value) // << the & is important! 
    { 
     $this->m_vars[$name] = $value; 
    } 
} 

class Db 
{ 
    funciton __construct(Config $config) 
    { 
     $this->Connect($config->host, $config->user, $config->pass, $config->db); 
    } 
} 

$config = new Config(); 
$config->host = "localhost"; 
... 
$db = new Db($config); 

:)

EDIT:

aussi, vous pouvez le faire:

class Templator 
{ 
    private $m_config = null; 
    function __construct($config) 
    { 
     $this->m_config = $config; 
    } 

    function PrintTemplate($name) 
    { 
     echo file_get_contents($this->m_config->template_path . $name); 
    } 

} 

$config->template_path = "./templates/"; 
$temp = new Templator($config); 
$temp->PrintTemplate("index.html"); 
2

Je me rends compte que c'est super-vieux, mais au cas où quelqu'un d'autre a besoin d'un indice ...

Avez-vous envisagé d'utiliser des variables statiques?

Le modèle de conception PHP POO est telle que statiquement variables déclarées dans une classe parent restent les mêmes dans l'enfant classe aussi.

Par exemple ...

<?php 
class A { 
    public static $test = 'a'; 

    public function test() { 
     echo 'Test is: '.self::$test; 
    } 

} 
class B extends A { 
    public static $test = 'b'; 
} 
$obj = new B; 
$obj->test(); 
?> 

L'exécution de ce code (sur PHP 5.3- Je suis sûr que c'est la même pour les autres versions, aussi) vous donnera le résultat suivant:

test est: un

De ce que j'ai pu rassembler dans votre OP, vous cherchez un moyen pour les variables de classe parent rester pour rester - même dans les classes étendues. Cela résout ce problème.

Pour appeler les variables publiquement en dehors de la portée de la classe (là où vous auriez normalement écrire obj- $> vars), vous aurez besoin de créer une fonction dans la classe parente qui fait référence à self::$variable_name afin qu'il puisse renvoie cette variable au code qui utilise cette classe ou toute autre classe qui l'étend.

Par exemple, quelque chose comme:

public function get_variable() { 
    return self::$variable; 
} 

Vous pouvez également créer une méthode magique qui dynamiquement rejettera l'auto :: $ variable en fonction de ce que vous demandez l'instance pour - à savoir une méthode ou une variable . Vous pouvez câbler le code pour rejeter l'équivalent de la variable self :: $ dans tous les cas.

Lisez http://php.net/manual/en/language.oop5.magic.php pour plus d'informations sur les différentes méthodes magiques qui vous permettent de faire ce genre de choses. L'OP était un peu énigmatique, donc je ne savais pas si c'était exactement ce que vous vouliez, mais je n'ai vu personne d'autre ici référencer des variables statiques alors je pensais que j'aurais pu entrer - j'espère que ça aide!

+0

Intéressant. mais que se passe-t-il si vous avez déclaré et assigné $ test à la méthode __construct()? Je pose cette question parce que vous ne pouvez pas faire de public static $ this-> test; – sqram

6

Il serait facilement possible avec un simple constructeur

<?php 

class One { 

    public static $string = "HELLO"; 

} 

class Two extends One { 

    function __construct() 
    { 
     parent::$string = "WORLD"; 
     $this->string = parent::$string; 
    } 

} 

$class = new Two; 
echo $class->string; // WORLD 

?> 
Questions connexes