Использование родительских переменных в расширенном классе в PHP
Вопрос
У меня 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;
}
}
}
?>
Мне нужно какое-то решение, более прозрачное и эффективное :)
Решение
РЕДАКТИРОВАТЬ:Это можно решить гораздо лучше с помощью Инверсия контроля (IoC) и Внедрение зависимости (ДИ).Если вы используете свой собственный фреймворк или тот, у которого нет Контейнер внедрения зависимостей пытаться Лига/Контейнер
Ответ внизу слева как история глупых ответов.
Правильный способ, как я понимаю.
<?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";
Другие советы
Это было бы легко возможно с помощью простого конструктора
<?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
?>
Я понимаю, что это очень старая информация, но на случай, если кому-то еще понадобится подсказка...
Вы рассматривали возможность использования статических переменных?
Шаблон проектирования ООП PHP таков, что статически объявленные переменные в родитель класс остается прежним в ребенок класс тоже.
Например...
<?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 — я уверен, что и в других версиях он будет таким же) даст вам следующий результат:
Тест:а
Судя по тому, что я смог собрать в вашем ОП, вы ищете способ переменные родительского класса остаться - даже в расширенных классах.Это решает эту проблему.
Чтобы вызвать переменные публично за пределами области класса (т.е.где вы обычно пишете $obj->вары), вам нужно будет создать в родительском классе функцию, которая ссылается на self::$variable_name
чтобы он мог вернуть эту переменную обратно в код, который использует либо этот класс, либо любой другой класс, который его расширяет.
Например, что-то вроде:
public function get_variable() {
return self::$variable;
}
Вы также можете создать волшебный метод, который будет динамически возвращать переменную self::$ в зависимости от того, что вы запрашиваете у экземпляра, т.е.метод или переменная.В любом случае вы можете подключить код, чтобы вернуть эквивалент self::$variable.
Читать http://php.net/manual/en/language.oop5.magic.php для получения дополнительной информации о различных магических методах, которые позволяют вам делать подобные вещи.
ОП был немного загадочным, поэтому я не был уверен, что это именно то, что вы хотели, но я не видел, чтобы кто-то здесь ссылался на статические переменные, поэтому решил вмешаться - надеюсь, это поможет!
Я думаю, вам нужно более четко представлять, чего вы хотите.Представьте, что у вас есть несколько экземпляров Main и Extended.Должны ли они все ссылаться на одни и те же данные, чтобы изменение данных в любом из них затронуло их все?
Если да, то один из подходов — использовать статическую переменную, привязанную к классу, а не к отдельному экземпляру.Другой вариант — создать отдельный объект (другого класса) для хранения ваших данных и передать его основным и расширенным классам при их создании.Каждый из них может хранить ссылку на него, например:
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);
Если нет, то вам нужны копии данных, а не ссылки на одни и те же данные.В этом случае ваш второй пример ближе, хотя я бы не стал просто слепо копировать всех участников.
уууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууууу
Вы хотите это:
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);
:)
РЕДАКТИРОВАТЬ:
также вы можете сделать это:
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");