Pergunta

Eu tenho 2 classes, principal e estendida. Eu preciso usar principais vars na classe estendida.

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

$main = new Main;

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

class Extended extends Main { }

$other = new Extended;

var_dump($other->vars);

?>

Quem eu posso fazer isso?

Não válido por exemplo:

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

Eu preciso de alguma solução mais transparente e eficiente:)

Foi útil?

Solução

Editar : Isso pode ser resolvido muito melhor com Inversão de Controle (COI) e Dependency Injection (DI). Se você usar o seu próprio quadro ou um sem Dependency Injection Container Liga / Container

Resposta abaixo esquerda como história de respostas tolas.


A figura correta maneira que eu.

<?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";

Outras dicas

Seria facilmente possível com um construtor simples

<?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

?>

Sei que isso é super-idade, mas no caso de alguém precisa de uma pista ...

Você já pensou em usar variáveis ??estáticas?

O padrão de projeto PHP OOP é tal que as variáveis ??estaticamente declarados em um pai classe permanecem os mesmos no criança classe, também.

Por exemplo ...

<?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();
?>

A execução desse código (em PHP 5.3- Eu tenho certeza que é o mesmo para outras versões, também) vai lhe dar o seguinte resultado:

Test é: a

Do que eu poderia reunir-se em seu OP, você está procurando uma maneira para que os variáveis ??de classe pai para permanecer - mesmo em classes estendidas. Isto resolve o problema.

Para chamar as variáveis ??publicamente fora do escopo de classe (ou seja, onde você normalmente write $ obj-> vars ), você precisa criar uma função na classe pai que as referências self::$variable_name de modo que ele pode jogar isso de volta variável para o código que utiliza tanto que classe, ou qualquer outra classe que estende-lo.

Por exemplo, algo como:

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

Você também pode criar um método mágico que dinamicamente jogar para trás o self :: $ variável com base no que você perguntar a instância para - método ou seja, um ou uma variável. Você poderia ligar o código para jogar para trás o self :: $ equivalente variável em qualquer caso.

Leia http://php.net/manual/en/language. oop5.magic.php para mais informações sobre os vários métodos mágicos que lhe permitem fazer este tipo de coisas.

O OP foi um pouco enigmática, então eu não tinha certeza se isso é exatamente o que você queria, mas eu não vi mais ninguém aqui referenciar variáveis ??estáticas então pensei que eu gritei - espero que ajude

Eu acho que você precisa ser mais claro sobre o que você quer. Imagine que você tinha vários casos de ambos principal e estendida. Caso todos eles se referem aos mesmos dados, de modo que se você alterar os dados em qualquer um deles, eles estão todos afetados?

Se sim, então uma abordagem é usar uma variável estática, que é ligada à classe em vez da instância individual. Outra é criar um objeto separado (de uma classe diferente) para armazenar seus dados e passá-lo para o principal e as classes estendidas quando eles são criados. Poderiam cada loja uma referência a ele, por exemplo:.

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);

Se não, então você quer cópias dos dados, em vez de referências para os mesmos dados. Nesse caso, o seu segundo exemplo é mais perto, embora eu não iria simplesmente copiar cegamente todos os membros.

oooooooooooooooooooooooooooooooooooooooooooooooooooooh

Você quer isto:

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:

Além disso, você pode fazer isso:

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");
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top