Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP: Sub class static inheritance - children share static variables?

As you can see below I have a super class (Article) and two sub classes. I want each of the sub classes to have a static array that shall hold all it's objects.

abstract class Article
{
    public static $articles = array(); // Variable for storing all the objects of each sub-class.

    public function add_Object_To_Array()
    {       
        array_push(self::$articles, $this);
    }
}

class Report extends Article{}
class Interview extends Article{}

-Making two Report objects and adding them to their array:

$tmp = new Report();
$tmp->add_Object_To_Array();

$tmp = new Report();
$tmp->add_Object_To_Array();

-Making two Interview objects and adding them to their array:

$tmp = new Interview();
$tmp->add_Object_To_Array();

$tmp = new Interview();
$tmp->add_Object_To_Array();

print_r(Report::$articles);
print_r(Interview::$articles);

-The above script spits out the two arays:

Array
(
    [0] => Report Object()

    [1] => Report Object()

    [2] => Interview Object()

    [3] => Interview Object()   
)
Array
(
    [0] => Report Object()

    [1] => Report Object()

    [2] => Interview Object()

    [3] => Interview Object()    
)

Which looks pretty similar if you ask me, but the first one should only contain Reports, and the second one only Interviews.

1. It seems that there is only one array, why is it only one array?
2. I have a static container of objects in the same class, is this bad coding? (Any suggestions?)

I'm pretty new to php, but have a background from java.

like image 267
MathiasCiarlo Avatar asked Jul 13 '13 18:07

MathiasCiarlo


1 Answers

I thought I'd present an alternate solution that changes your design slightly, but doesn't require static definitions in each subclass. Depending on your usage, this may or may not be a better option than the first solution.

This solution uses get_class() to find the type of the object we're storing, and then stores it in the parent class - in a sub-array keyed by classname:

abstract class Article
{
    public static $articles = array();

    public function add_Object_To_Array()
    {
        // get the actual class of the current object
        $class = get_class($this);
        // define an empty subarray for this class if we haven't seen it before
        if (!isset(self::$articles[$class])) {
            self::$articles[$class] = array();
        }
        // add this object to the appropriate subarray
        array_push(self::$articles[$class], $this);
    }
}
class Report extends Article{}
class Interview extends Article{}

The above code does not use late static binding, so it'll work with any PHP version, instead of just PHP 5.3+.

When you run this version with your original example, you'll get output like this:

Array
(
    [Report] => Array
        (
            [0] => Report Object
                (
                )

            [1] => Report Object
                (
                )

        )

    [Interview] => Array
        (
            [0] => Interview Object
                (
                )

            [1] => Interview Object
                (
                )

        )

)

If you do have PHP 5.3 or later, you can extend this even more and use the get_called_class() function to define a getInstances() static method (in the Article class) that works like this:

public static function getInstances()
{
    $class = get_called_class();
    // return isset(self::$articles[$class]) ? self::$articles[$class] : array();
    if (isset(self::$articles[$class])) {
        return self::$articles[$class];
    } else {
        return array();
    }
}

Then you can call this method in your example like this:

print_r(Report::getInstances());
print_r(Interview::getInstances());
like image 70
jcsanyi Avatar answered Oct 13 '22 22:10

jcsanyi