views:

46

answers:

3

Let's see if I can describe this properly...

I have an abstract class that when other classes extend from it, I'd like for the abstract class' data to be reset to zero.

The idea being that I have a pile of classes extending this and using MySQL table's for data structure. I don't want to query the DB with every class instantiation to determine the class' data ("SHOW COLUMNS FROM tablename).

So for every class, I'd like for it to each "Have we created this class before? If so, we know the class' structure, if not, grab the table columns and create the class as well as store the table columns for later use."

I've been using the following for testing my idea:

$columns = array("Column 1", "Column 2", "Column 3");

abstract class AbstractClass {

    protected static $colFields = array();

    public function __construct() {
        $this->setVars();
    }

    private function setVars() {
        global $columns;
        if (count(self::$colFields) == 0) {
            var_dump("Array length is 0");
            foreach ($columns as $key) {
                self::$colFields[] = $key;
                if (!isset($this->$key))
                    $this->$key = null;
            }
        }
        else {
            var_dump("Array length is not 0");
            foreach (self::$colFields as $key) {
                $this->$key = null;
            }
        }
    }

    public function test() {
        var_dump($this);
    }

}

class ObjectA extends AbstractClass {};

class ObjectB extends AbstractClass {};


$objectAA = new ObjectA();
$objectAB = new ObjectA();
$objectAC = new ObjectA();

$objectAC->test();

$objectBA = new ObjectB();
$objectBB = new ObjectB();
$objectBC = new ObjectB();

$objectBC->test();

And the script's output is:

string(17) "Array length is 0"
string(21) "Array length is not 0"
string(21) "Array length is not 0"
object(ObjectA)#3 (4) {
["className":protected]=>
string(7) "ObjectA"
["Column 1"]=>
NULL
["Column 2"]=>
NULL
["Column 3"]=>
NULL
}
string(21) "Array length is not 0"
string(21) "Array length is not 0"
string(21) "Array length is not 0"
object(ObjectB)#6 (4) {
["className":protected]=>
string(7) "ObjectB"
["Column 1"]=>
NULL
["Column 2"]=>
NULL
["Column 3"]=>
NULL
}

I'm expecting the first instantiation of ObjectB to output the "Array length is 0" segment, then continue on.

Can anyone help?

+4  A: 

I suggest that you do not store the cached table information in your abstract class. Create a new class called TableInformationRepository or something like that. Have your child class or abstract class query the TableInformationRepository for information about tables/classes. In the TableInformationRepository, cache the information you want keyed by class name or table name.

Scott Saunders
I was thinking of going this route and I just may have to. Storing all the table definitions in a big fat array/object just isn't as elegant. :/
Charlie
A: 

To add to what Scott Saunders said - why not use a singleton for that?

http://php.net/manual/en/language.oop5.patterns.php - example #2

vlad b.
I'll have to play with this... I just implemented a basic cache thingy like Scott suggested but I'm going to have to look into this...
Charlie
I would suggest a multiton. This is a related pattern to singleton, but not very common to everybody. It allows more then one instance. This way you could control having one instance for each db-table.
faileN
Even more great info. Thanks guys! Already looking into this one as well.
Charlie
A: 

In PHP, if you don't redeclare protected/public static fields in the subclasses, they will all belong to the same reference set. This means a change in a protected property will be reflected in all the classes.

Example:

class A {
    public static $field = "1";
}
class B extends A { }
B::$field = 2;
echo A::$field; //2

On the other hand:

class A {
    public static $field = "1";
}
class B extends A {
    public static $field = "1";
}
B::$field = 2;
echo A::$field; //1

You can also break the reference set by hand:

class A {
    public static $field = "1";
}
class B extends A { }
$v = 2;
B::$field = &$v;
unset($v);
echo A::$field; //1
Artefacto