Realitätsverlust
Realitätsverlust

Reputation: 3953

Call a class method as soon as an object it extends is created

Assume we have the following class (simplified):

class SuperConfig {
    public $mainDir;

    public function setDir() {
        $this->mainDir = "path/to/dir";
    }
}

This class is supposed to be extended in EVERY other class in the project, and I do need the setDir() function of the parent to be executed. Obviously, I could do it like this:

class A extends SuperConfig() {
    public function __construct() {
        parent::setDir();
    }
    // ... other stuff is about to be done ...
}

and I could access the properties in the child class like this:

class A extends SuperConfig {
    public function doSomething() {
        SuperConfig::mainDir;
    }
}

This is a viable solution, but I got multiple hundreds of classes and doing this in every single one seems tedious. So, is there a way to do something like this:

class SuperConfig {
    public $mainDir;

    public function __extend() {
        $this->setDir();
    }

    public function setDir() {
        $this->mainDir = "path/to/dir";
    }
}

__extend() obviously doesn't work like that, but I'm wondering is there is a trick how I could make this work.

Upvotes: 0

Views: 41

Answers (4)

Manuel Mannhardt
Manuel Mannhardt

Reputation: 2201

Read deceze's answer for an actual solution to your problem.

I would like to point out tho, that you should not extend every class in your project from a Config class. There are several ways how you could improve that.

1.) Create a static config class which you simply can call everywhere without the need of creation

class SuperConfig {
    protected static $mainDir = null;

    public static function setMainDir($dir) {
        self::$mainDir = $dir;
    }
}

2.) Create a trait rather then a parenting class.

trait SuperConfig {
    protected $mainDir = null;

    public function setMainDir($dir) {
        $this->mainDir = $dir;
    }
}

which you then can use inside your classes:

class XYZ {
    use SuperConfig;

    public function doSomething() {
        $this->setMainDir('path/to/your/dir/');
    }
}

Note that you can do that in the constructor too (which is kinda what you want).

Im not saying those two solutions are the best, but I dont like the thought of extending all classes from a config class. Just does not make much sence. Just imagine that you can only extend from one class per time, while you can use as many traits as you wish (and also have as many static classes as you need).

Upvotes: 1

Marcin Orlowski
Marcin Orlowski

Reputation: 75629

Well, in this particular case you just need:

class SuperConfig {
    public $mainDir = "path/to/dir";
}

Upvotes: 0

Richard Parnaby-King
Richard Parnaby-King

Reputation: 14862

Put the constructor in the class that is being extended.

class SuperConfig {
    public $mainDir;

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

    public function setDir() {
        $this->mainDir = "path/to/dir";
    }
}

In any class that extends SuperConfig, if they have a constructor also, be sure to include parent::__construct(); so that setDir is called.

Upvotes: 1

deceze
deceze

Reputation: 522005

class SuperConfig {
    public $mainDir;

    public function __construct() {
        $this->setDir();  // consider moving setDir's code here as well,
                          // unless you have a good reason for it to be a method
    }

    public function setDir() {
        $this->mainDir = "path/to/dir";
    }
}

You simply do this, and then you expect all subclasses to call the parent constructor if they're overriding the constructor:

public function __construct() {
    parent::__construct();
    // more code
}

It's perfectly reasonable to expect children to call their parent constructor, unless they deliberately want to leave the instance in an unknown and potentially broken state.

Upvotes: 2

Related Questions