Extended class cannot access parent class variable

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
Bon Bon
Forum Commoner
Posts: 66
Joined: Sat Mar 13, 2004 10:21 pm
Location: UK

Extended class cannot access parent class variable

Post by Bon Bon »

I am trying to create a database->table->field model and things are not going too well. Basically the field class does not inherit the $_table variable from the table class so the $_table variable contains no value. But everything else works.

Any ideas on what I am doing wrong?

Code: Select all

<?php
class MysqliAccess {
  static private $_instance = NULL;
  static private $_mysqli;
  protected $_table;
  protected $_result;
  protected $_where;
  private function __construct () {
    self::$_mysqli = mysqli_init();
    self::_dbConnect();
    self::_setTables();
  }
  final private function _dbConnect () {
    self::$_mysqli->real_connect('ip address', 'user', 'password', 'table');
  }
  private function _setTables () {
    $this->_query('SHOW TABLES');
    while ($row = $this->_result->fetch_row()) {
      $table = $row[0];
      $this->$table = new Table($table);
    }
  }
  final protected function _tableExists ($table) {
    // removed to shorten code
  }
  final protected function _getTableFields ($table) {
    $this->_query('SHOW COLUMNS FROM `' . $this->_escape($table) . '`');
    if ($this->_result && $this->_result->num_rows > 0) {
      while ($row = $this->_result->fetch_row()) {
        $fields[] = $row[0];
      }
      return $fields;
    }
    return FALSE;
  }
  static public function getInstance () {
    // removed to shorten code
  }
  final protected function _escape ($variable) {
    // removed to shorten code
  }
  private function _query ($sql) {
    // removed to shorten code
  }
  public function fetchSingle ($field) {
    $this->_query('SELECT `' . $this->_escape($field) . "` FROM `$this->_table` $this->_where LIMIT 1");
    if ($this->_result) return implode('', $this->_result->fetch_row());
    return FALSE;
  }
}
class Table extends MysqliAccess {
  protected $_table;
  protected function __construct ($table) {
    if ($this->_tableExists($table)) $this->_table = $table;
    if ($fields = $this->_getTableFields($this->_table)) {
      foreach ($fields as $field) {
        $this->$field = new Field($field);
      }
    }
  }
}
class Field extends Table {
  private $_field;
  protected function __construct ($field) {
    $this->_field = $field;
  }
  public function __toString () {
    return $this->fetchSingle($this->_field);
  }
}
$db = MysqliAccess::getInstance();
?>
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Table redeclares $_table thereby making the parent's not accessible from $this->_table. parent::$_table would work however.
Bon Bon
Forum Commoner
Posts: 66
Joined: Sat Mar 13, 2004 10:21 pm
Location: UK

Post by Bon Bon »

Changing the code to the following causes the error mentioned below:

Code: Select all

class Table extends MysqliAccess {
  protected function __construct ($table) {
    if ($this->_tableExists($table)) parent::$_table = $table;
    else trigger_error("Table cannot be read from: $table.", E_USER_ERROR);

    if ($fields = $this->_getTableFields(parent::$_table)) {
      foreach ($fields as $field) {
        $this->{$field} = new Field($field);
      }
    }
  }
}
Fatal error: Access to undeclared static property: MysqliAccess::$_table

I want {$_table} to be different for every table class declared, will accessing the {$_table} variable in the parent scope still allow this?
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Hmm... I guess I confused the parent:: bit. You should be able to use $this->_table now that you've removed the redeclaration.

I'm not sure I understand why Field extends Table. A field isn't a Table. A Table is made of one or more fields however, but it's composed of fields, not a descendant of one.
Bon Bon
Forum Commoner
Posts: 66
Joined: Sat Mar 13, 2004 10:21 pm
Location: UK

Post by Bon Bon »

Now I have done that I get the following error:

Method Field::__toString() must return a string value

This is because $this->_table still contains no value.

I am extending the table class using the field class because I want to be able to do things like:

Code: Select all

$db->table_name->field->search('value'); // finds 'value' in 'field' from the table 'table_name'
echo $db->table_name->field;
Now maybe I have misunderstood OOP because I have really just started using classes in PHP but I assumed I should be able to do this.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

The function returns false in a particular case. It cannot do that. Return an empty string.
Bon Bon
Forum Commoner
Posts: 66
Joined: Sat Mar 13, 2004 10:21 pm
Location: UK

Post by Bon Bon »

It returns FALSE because fetchSingle returns FALSE because it is trying to run the following query:
SELECT `username` FROM `` LIMIT 1

As you can see by that, {$_table} is NULL, no value has been set and this is causing the query to fail, this is because the {$_table} variable is not being passed to the parent class. For what ever reason which I don't know, it seems strange to me because it can pass the {$_table} variable value from the Table class to the MysqliAccess but not from the Field class to the MysqliAccess class.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Bon Bon wrote:It returns FALSE because fetchSingle returns FALSE because it is trying to run the following query:
SELECT `username` FROM `` LIMIT 1

As you can see by that, {$_table} is NULL, no value has been set and this is causing the query to fail, this is because the {$_table} variable is not being passed to the parent class. For what ever reason which I don't know, it seems strange to me because it can pass the {$_table} variable value from the Table class to the MysqliAccess but not from the Field class to the MysqliAccess class.

Code: Select all

if (empty($this->_field)) {
  return "";
} else {
  return $this->_field;
}
I agree with ~feyd that your types make no sense. A field is not a table so don't subclass table to make one. This is one of the most common mistakes newcomers to OOP make (in all OO languages).
Bon Bon
Forum Commoner
Posts: 66
Joined: Sat Mar 13, 2004 10:21 pm
Location: UK

Post by Bon Bon »

The field name is not empty, it is the table name and that solution would do nothing to solve the problem.

The problem lies with the referencing of variables between 3 classes.

This is what I want to happen:
class 1 -> class 2 -> class 3
class 1 <- class 2 <- class 3

This is what happens:
class 1 -> class 2 -> class 3
class 1 <- class 2
class 1 <- class 3

I done some testing and using static variables I got the referencing to work using static variables but then this meant that I could only have 1 Table class and 1 Field class.

Now after I rethink I understand that I should not be extending classes like this, each class should have its own functionality and maybe sorting out what functions belong to which class might help solve the problem.

I will try splitting the classes, but in the future if I have the same problem but it made sense to pass the variable between 3 classes, each extending the parent, then I would still need a solution if anyone knows one?

Cheers for the help.
Post Reply