Использование родительских переменных в расширенном классе в PHP - PullRequest
6 голосов
/ 26 декабря 2008

У меня есть 2 класса, основной и расширенный. Мне нужно использовать основные переменные в расширенном классе.

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

$main = new Main;

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

class Extended extends Main { }

$other = new Extended;

var_dump($other->vars);

?>

Кто я могу это сделать?

Недействительно, например:

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

Мне нужно какое-то решение, более прозрачное и эффективное:)

Ответы [ 5 ]

6 голосов
/ 02 марта 2011

Это было бы легко возможно с простым конструктором

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

?>
4 голосов
/ 26 декабря 2008

РЕДАКТИРОВАТЬ : Эту проблему можно решить гораздо лучше с помощью Инверсия управления (IoC) и Внедрение зависимости (DI). Если вы используете свой собственный фреймворк или один без Контейнер внедрения зависимостей , попробуйте Лига / Контейнер

Ответ ниже оставлен как история глупых ответов.


Правильный способ, которым я фигурирую.

<?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";
2 голосов
/ 06 марта 2010

Я понимаю, что это супер-старый, но на случай, если кому-то еще понадобится ключ ...

Рассматривали ли вы использование статических переменных?

Шаблон проектирования PHP OOP таков, что статически объявленные переменные в классе parent остаются такими же в классе child .

Например ...

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

Выполнение этого кода (на PHP 5.3 - я уверен, что он одинаков и для других версий) даст вам следующий результат:

Испытание: a

Из того, что я мог бы собрать в вашем OP, вы ищете способ, которым переменные родительского класса могут остаться - даже в расширенных классах. Это решает эту проблему.

Чтобы публично вызывать переменные вне области действия класса (т. Е. Там, где вы обычно пишете $ obj-> vars ), вам необходимо создать функцию в родительском классе, которая ссылается на self::$variable_name чтобы он мог выбросить эту переменную обратно в код, который использует либо этот класс, либо любой другой класс, расширяющий его.

Например, что-то вроде:

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

Вы также можете создать магический метод, который будет динамически отбрасывать переменную self :: $ в зависимости от того, для чего вы запрашиваете экземпляр - то есть для метода или переменной. Вы можете связать код, чтобы отбросить эквивалент переменной self :: $ в любом случае.

Прочитайте http://php.net/manual/en/language.oop5.magic.php для получения дополнительной информации о различных магических методах, которые позволяют вам делать подобные вещи.

ОП был немного загадочным, поэтому я не был уверен, что это именно то, что вам нужно, но я не видел, чтобы кто-нибудь еще ссылался на статические переменные, поэтому думал, что я включу - надеюсь, это поможет!

1 голос
/ 26 декабря 2008

Я думаю, вам нужно быть более ясным в том, что вы хотите. Представьте, что у вас было несколько экземпляров Main и Extended. Должны ли они все ссылаться на одни и те же данные, так что, если вы измените данные в одном из них, все они будут затронуты?

Если это так, то одним из подходов является использование статической переменной, которая связана с классом, а не с отдельным экземпляром. Другой способ - создать отдельный объект (другого класса) для хранения ваших данных и передать его классам Main и Extended при их создании. Каждый из них может хранить ссылку на него, например ::1003

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

Если нет, то вам нужны копии данных, а не ссылки на те же данные. В этом случае ваш второй пример ближе, хотя я бы не стал слепо копировать всех участников.

0 голосов
/ 26 декабря 2008

oooooooooooooooooooooooooooooooooooooooooooooooooooooh

Вы хотите это:

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:

также вы можете сделать это:

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