Using parent variables in a extended class in PHP
Asked Answered
A

5

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

Aparicio answered 25/12, 2008 at 21:37 Comment(1)
I don't get it. I would be more then happy to answer your question but it's not clear enough. Do you want to construct "extended" like ($obj = new Extended($main)) or are you looking for static vars?Robrobaina
D
4

EDIT: This can be solved much better with Inversion of Control (IoC) and Dependency Injection (DI). If you use your own framework or one without Dependency Injection Container try League/Container

Answer below left as history of foolish answers.


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";
Dd answered 25/12, 2008 at 21:46 Comment(5)
I wish the guy who don't know PHP and modded me down would explain why.Dd
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.Robrobaina
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...Dd
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" :)Robrobaina
Redid to reflect this is a config class not some random Main class which it started out as.Dd
A
6

It would be easily possible with a simple constructor

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

?>
All answered 2/3, 2011 at 12:46 Comment(0)
D
4

EDIT: This can be solved much better with Inversion of Control (IoC) and Dependency Injection (DI). If you use your own framework or one without Dependency Injection Container try League/Container

Answer below left as history of foolish answers.


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";
Dd answered 25/12, 2008 at 21:46 Comment(5)
I wish the guy who don't know PHP and modded me down would explain why.Dd
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.Robrobaina
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...Dd
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" :)Robrobaina
Redid to reflect this is a config class not some random Main class which it started out as.Dd
C
2

I realize this is super-old, but in case anyone else needs a clue...

Have you considered using static variables?

The PHP OOP design pattern is such that statically declared variables in a parent class remain the same in the child class, too.

For example...

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

Running this code (on PHP 5.3- I'm sure it's the same for other versions, too) will give you the following result:

Test is: a

From what I could gather in your OP, you are looking for a way for the parent class variables to remain - even in extended classes. This solves that problem.

To call the variables publicly outside of the class scope (i.e. where you'd normally write $obj->vars), you'd need to create a function in the parent class that references self::$variable_name so that it can throw that variable back to the code that utilizes either that class, or any other class that extends it.

For example, something like:

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

You could also create a magic method that would dynamically throw back the self::$variable based on what you ask the instance for - i.e. a method or a variable. You could wire the code to throw back the self::$variable equivalent in any case.

Read http://php.net/manual/en/language.oop5.magic.php for more info on the various magic methods that allow you to do this kind of stuff.

The OP was a bit cryptic so I wasn't sure if that's exactly what you wanted, but I didn't see anyone else here reference static variables so thought I'd chime in - hope it helps!

Clicker answered 6/3, 2010 at 11:58 Comment(1)
Interesting. but what happens if you have declare and assign $test inside the __construct() method? I ask this because you can't do public static $this->test;Wore
M
1

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.

Magically answered 25/12, 2008 at 23:14 Comment(0)
R
0

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");
Robrobaina answered 25/12, 2008 at 23:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.