Page 1 of 1

Accessing parent class vars

Posted: Tue Apr 28, 2009 9:36 am
by ben.artiss
Hi everyone,

I'm still trying to make my own base CMS, but I'm baffled as to how I can access a parent class' vars. I can access class constants [define('NAME','val')] no problem however they don't let you store arrays in them.

There is a core class (singleton) which stores all other classes as public vars. So far I have core.class.php which has a function getInstance() to get just one instance of that object, and inside the __construct() of the core I create a new sql object, so I access the sql functions using $core->sql->func().

In the sql.class.php file I have a function test() which echos the constant LIB (defined by the core class) - that works no problem. However, trying to echo $this->emails or $core->emails or parent::emails just doesn't work! Does anyone know a solution to this?

Thanks, Ben

Re: Accessing parent class vars

Posted: Tue Apr 28, 2009 10:07 am
by user___
Give us some code. emails come from? In which class you instantiate it?

Re: Accessing parent class vars

Posted: Tue Apr 28, 2009 10:21 am
by ben.artiss
Thanks for the response user___

There are a few files which build up the system all based in /lib. Each viewable file (e.g. index.php) includes a file /lib/init.inc.php to start the session and include the necessary classes and configuration, so at the end of init.inc.php the following is run which loads the core:

Code: Select all

$core = core::getCore();
Incidentally, $emails comes from /lib/conf.inc.php which is included by init.inc.php.

Here's what the core class has:

Code: Select all

defined('INIT') or die(basename(__FILE__).' cannot be accessed in this way.');
 
class core {
    # Class containers
    private static $core;
    public $sql;
 
 
    # Variable containers
    const TESTMODE = false;
    const ROOT = false;
    const LIB = false;
    public $emails;
 
 
    # Initialise the core
    private function __construct() {
        global $_conf;
 
        define('TESTMODE', $_conf['testmode']);
        define('ROOT', $_conf['root']);
        define('LIB', $_conf['lib']);
 
        $this->emails = $this->get_emails($_conf['emails']);
        $this->sql = new sql;
    }
 
 
    # Get one instance of the core
    public static function getCore() {
        if (!self::$core) {self::$core = new core();}
        return self::$core;
    }
 
 
    # Get emails from conf.inc.php
    private function get_emails($array=false) {
        if (!$array || !is_array($array)) {$this->error('init::get_emails() requires an array'); return false;}
        $emails = array();
        foreach ($array as $key => $val) {$emails[$key] = $val;}
        return $emails;
    }
 
 
    # Internal error controller, only works if testmode is enabled in conf.inc.php
    private function error($message=false) {
        if (!trim($this->message)) {return false;}
        if (!$this->testmode) {echo '<p style="color:red;">'.$message.'</p>';}
    }
}
So in the __construct() it loads the sql class and assigns it to $this->sql. This is the sql.class.php:

Code: Select all

defined('INIT') or die(basename(__FILE__).' cannot be accessed in this way.');
 
class sql extends core {
    private $dbhost, $dbuser, $dbpass, $dbname, $db, $last_query;
 
 
    # Initialise the core
    public function __construct() {
        global $_conf;
 
        $this->dbhost = $_conf['dbhost'];
        $this->dbuser = $_conf['dbuser'];
        $this->dbpass = $_conf['dbpass'];
        $this->dbname = $_conf['dbname'];
    }
 
 
    # Test
    public function test() {
        echo LIB.' This must have worked... '.$core->emails;
    }
}
It's the very last part in the test() function where I'm having trouble. I've tried loads of different ways but it refuses to work! I've tried

$this->emails
$core->emails
parent::emails

... and others but no luck yet

Re: Accessing parent class vars

Posted: Tue Apr 28, 2009 10:42 am
by user___
I see what happens now. The problem is that when you inherit a class extends the constructor for one or another reason does not execute. the parent one. In order to call it you have to do it like this:

Code: Select all

parent::__construct();

Re: Accessing parent class vars

Posted: Tue Apr 28, 2009 11:01 am
by ben.artiss
Hmmm parent::__construct() is private because of the single instance, do you think I'm taking the wrong approach? Essentially I just want the 'global' data to be available to all subclasses, but contained within the core class.

From what I've been reading it doesn't look possible to access a variable from a parent class unless it's passed to the extending class and defined within it. Please tell me I'm wrong :P Really appreciate the help user___

Re: Accessing parent class vars

Posted: Wed Apr 29, 2009 5:29 pm
by ben.artiss
Just in case anyone searches for an answer to this one sometime (because it took me ages to get my head round it!), you can access a parent class' variables only if they are static. I had a fair bit of trouble using the singleton approach but it worked fine when I called a class in the normal method of $classname = new class. Have a look at this example:

Code: Select all

class core {
    public $info; // To store the class
    public static $url, $libpath;
 
    public function __construct() {
        self::$url = 'http://localhost/example';
        self::$libpath = '../lib';
        $this->info = new info;
    }
 
    # ... rest of class
}
 
class info extends core {
    __construct() {
        # load class
    }
 
    public function get_info_string() {
        $string = 'Website URL: '.parent::$url."\n";
        $string .= 'Library Path: '.parent::$libpath."\n";
        return $string;
    }
 
    # ... rest of class
}
 
$core = new core;
 
echo nl2br($core->info->get_info_string());
/* Output:
Website URL: http://localhost/example
Library Path: ../lib
*/
I know it's a poor example but it gives you an idea of the scope and syntax. Hope someone has a use for it sometime! :)

Re: Accessing parent class vars

Posted: Fri May 01, 2009 12:02 pm
by user___
Great you have solved your problem. This is what I meant.

Code: Select all

<?php
 
/*
 * The parent class sets a variable
 */
class parentClass {
    public $emails = "";
    public function __construct() {
        $this->emails = "some E-mails here";
    }
}
/*
 * This is the child
 */
class childClass extends parentClass {
    public function __construct() {
        parent::__construct();
        var_dump($this->emails);
    }
}
new childClass();
 
?>
When you extend a class the super constructor is not run so you must run it. One more thing, it is a good practice to keep your constructors public.

This is the result:

Code: Select all

string 'some E-mails here' (length=17)