0

Let's say I have a static array and I would like to add some more values into it in a child class. Since PHP does not have static constructor, I really don't know how to achieve this in a clean manner (I definitely don't want to add anything under the class definition and can't change the autoloader)

This is what I would like to achieve (obviously doesn't work)

class Parent{
    public static $meta = [1,2,3];
}

class Child extends Parent{
    public static $meta = array_merge(parent::$meta,[4,5]);

}
1
  • I'd recommend you to create singleton class that would share static information between classes you want. Commented Dec 29, 2017 at 16:46

3 Answers 3

2

What you want isn't possible with vars inside classes. Instead I would suggest to provide the acccess to the var over an getter method. On top of this, I would suggest to make the static var protected, to prevent unwanted access from outside.

Using late static binding, you could provide a static function in the parent class, which merges the own var with the vars from the inherited class.

class A {
    protected static $meta = [1,2,3];

    public static function getMeta() {
        if (__CLASS__ == static::class) {
            return self::$meta;
        }
        return array_merge(self::$meta, static::$meta);
    }
}

class B extends A {
    protected static $meta = [4,5];
}

var_dump(B::getMeta());

The comparison of __CLASS__ == static::class is only needed for this example - if you go with assiciative arrays and just want to append new options, you could just ignore this and use a simple return self::$meta + static::$meta;

Keep in mind, this works only for one level inheritance. If you need a cascade of new $meta vars in the child classes, you have overwrite the getMeta method in the child classes too.

Sign up to request clarification or add additional context in comments.

1 Comment

But calling A::getMeta() would return [1,2,3,1,2,3] which is a weird behavior
1

you are redefining an attribute in your child class which is not recommended. You can check here alternatives

Moreover parent is not an allowed name for a class. A solution would be to implement a static method wich return the property. Like this

class ParentClass{
    public static $meta = [1,2,3];

    public static function getMeta() {
        return self::$meta;
    }
}

class Child extends ParentClass{
    public static function getMeta() {
        return array_merge(parent::getMeta(),[4,5]);
    }
}

var_dump(Child::getMeta());

Result is

array(5) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
  [3]=>
  int(4)
  [4]=>
  int(5)
}

You can check this live here : https://3v4l.org/v8Mtm

Hope this help.

Comments

1

The only way I can imagine doing this (without using a constructor or adding to the the class definition) is to use define consts like so;

/* FOO CLASS FILE */
define('FOO_META', [1, 2, 3]);

class Foo{
    public static $meta = FOO_META;
}

/* BAR CLASS FILE */
define('BAR_META', array_merge(FOO_META, [4, 5, 6]));

class Bar extends Foo{
    public static $meta = BAR_META;
}

echo 'Foo-Meta = ' . implode(', ', Foo::$meta) . '<br>';
echo 'Bar-Meta = ' . implode(', ', Bar::$meta) . '<br>';

Class properties can only be assigned const values inside the class definition. You will need to use a constructor (or some other method) to do this dynamically. If you use the above method, I would recommend using namespaces like so:

define('foo\META', [1, 2, 3]);
define('bar\META', array_merge(foo\META, [4, 5, 6]));

EDIT: if these classes consist only of this one property, why not just use the defines by themselves? They are essentially the same thing without the additional overhead.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.