views:

3729

answers:

6

I have 2 classes, main and extended. I need to use main vars in extended class.

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

$main = new Main;

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

class Extended extends Main { }

$other = new Extended;

var_dump($other->vars);

?>

Who I can do it?

No valid for example:

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

I need some solution more transparent and efficient :)

A: 

EDIT for config class what you want is either a singleton or a singleton where you can store it.

The correct way I figure.

<?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";
OIS
I wish the guy who don't know PHP and modded me down would explain why.
OIS
Im not going to downmod but you are really lacking in the OOP design area. You should NEVER extend Config classes - Config objects should be contained in the objects that consume them - not extended into other classes. Sorry, but this is plain silly.
nlaq
I don't do that, but thats what the guy wants. It didn't start out as a config class, but thats what it turned out to be...
OIS
Just say no to perpetuating sillyness :) I don't blame the OP at all but we should know better enough to point out that the OP made a bad design choice and it will bite him in the ass HARD if he basses his entire code structure off of this "anti-pattern" :)
nlaq
Redid to reflect this is a config class not some random Main class which it started out as.
OIS
A: 

Doesn't work. This is a real example:

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

  public $db = array();

  public function __get ($name) {
    return self::$__vars[$name];
  }

  public function __set ($name, $value) {
    self::$__vars[$name] = $value;
  }
}

$config = new Config;
$config->db = array('localhost', 'root', '');

class Vars extends Config {

  public function __construct () {
    var_dump($this->$db); // array (0) {}
    var_dump(parent::$db); // Fatal error: Access to undeclared static property: Config::$db
  }
}

$vars = new Vars;
?>

Thanks for your help :)

What does Vars represent? It sounds like it should contain a reference to $config, rather than extending Config. The instance ($config) contains your data, not the class (Config).
JW
1. You should edit your question instead of answering. 2. Thats not following my example at all. Do you want a different array for the parent and child class, or the same array for both?
OIS
A: 

I think you need to be more clear about what you want. Imagine that you had several instances of both Main and Extended. Should they all refer to the same data, so that if you change the data in any one of them, they're all affected?

If so, then one approach is to use a static variable, which is tied to the class rather than the individual instance. Another is to create a separate object (of a different class) to store your data, and pass it to the Main and Extended classes when they're created. They could each store a reference to it, e.g.:

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

If not, then you want copies of the data, rather than references to the same data. In that case, your second example is closer, although I wouldn't just blindly copy all members.

JW
A: 

This is my code:

<?php
class Config {
  public $db = array();
  public $templates = array();
}

$config = new Config;

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

class DB extends Config {
    function connect () {
     mysql_connect($this->db[0], $this->db[1], $this->db[2]);
    }
}

$db = new DB;
$db->connect();

class Templates extends Config {
    function load ($where) {
     return $this->templates[$where];
    }
}

$templates = new Templates;
$templates->load('main');
?>

I can do other solutions, but I don't want other solutions I need to know if this code is posible!

Other posible solutions that I don't want:

<?php
class DB {
    function connect ($config) {
     mysql_connect($config->db[0], $config->db[1], $config->db[2]);
    }
}

$db = new DB;
$db->connect($config);
?>

nor

<?php
class DB {
    private $config;

    function DB () {
     global $config;

     $this->config = $config;
    }

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

$db = new DB;
$db->connect();
?>

Sorry my english :)

No, your code won't work. Why wouldn't you want another solution that does?
JW
I just posted a solution which works.
OIS
1) Because isn't as transparent as I want :)
Redid my answer. With Config::getInstance() you can get the one object from anywhere. Just remember to use $config = Config::getInstance() and NOT $config = new Config();
OIS
A: 

oooooooooooooooooooooooooooooooooooooooooooooooooooooh

you want this:

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:

also, you can do this:

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");
nlaq
A: 
Lee