PHP: static subclass inheritance - do children share static variables?

As you can see below, I have a superclass (article) and two subclasses. I want each of the subclasses to have a static array that should contain all the 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{} 

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

- Creating 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 two arrays:

 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 should only contain reports, and the second should only contain 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 am new to php but have background from java.

+4
source share
2 answers

Everything happens in only one array for two reasons:

  • The $articles property is defined only in the Article class.

    Properties of a static class are not inherited in the same way as you would expect if you use non-static properties. Although they are accessible to child classes, they still refer to the same variable of the parent class, which leads to the behavior that you see here when both child classes use the same array. p>

    The only way to prevent this is to define a separate array in each of your child classes, for example:

     class Report extends Article { public static $articles = array(); } class Interview extends Article { public static $articles = array(); } 

    It really makes sense if you think of static variable declarations as code that runs when the class is defined. Creating a static variable and assigning it an empty array occurs when the Article class is defined. This will not happen again when the Interview and Report classes are defined. There only once, when it receives an empty array - there is only one common variable.

  • You use self in your add_Object_To_Array() method instead of static .

    • self:: refers to the class in which it is defined, therefore, since your add_Object_To_Array() method is defined in the Article class, it will refer to the Article::$articles array.

    • static:: Available since PHP 5.3 and refers to the class to which it is called. This is called Late Static Binding and will result in add_Object_To_Array() , which refers either to Report::$articles or to Interview::$articles depending on the type of object you are calling it on.

    This code will reference the two arrays that we declared in the first step:

     public function add_Object_To_Array() { array_push(static::$articles, $this); } 
+9
source

It seemed to me that I was proposing an alternative solution that slightly changes your design, but does not require static definitions in each subclass. Depending on your use, this may or may not be a better option than the first solution.

This solution uses get_class() to find the type of object that we store, and then save it in the parent class - in the submatrix associated with the class name:

 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 will work with any version of PHP, and not just with PHP 5.3+.

When you run this version with the original example, you get the following output:

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

If you have PHP 5.3 or later, you can expand it even further and use get_called_class() to define getInstances() static (in the Article class), which works as follows:

 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 as follows:

 print_r(Report::getInstances()); print_r(Interview::getInstances()); 
+3
source

Source: https://habr.com/ru/post/1491276/


All Articles