2

Let' suppose I have my code organized in classes and each class has its own file:

  • main.php, having class Main
  • config.php having class Config
  • security.php having class Security
  • database.php having class Database

Now, Main's constructor will initialize 3 objects, one for each of the other classes, and this way everything will look more or less like a class/subclass. The problem is that now Security might need something (a variable or function) from Config and Database something from Security.

// main.php
// here I include the other files
class Main {
    functions __constructor() {
        $this->Config = new Config();
        $this->Security = new Security();
        $this->Database = new Database();
    }
}

// config.php
class Config {
    public $MyPassword = '123456';
    public $LogFile    = 'logs.txt';
    // other variables and functions
}

// security.php
class Security {
    functions __constructor() {
        // NOW, HERE I NEED Config->Password
    }

    function log_error($error) {
        // HERE I NEED Config->LogFile
    }
}

// database.php
class Database {
    functions __constructor() {
        // Trying to connect to the database
        if (failed) {
            // HERE I NEED TO CALL Security->log_error('Connection failed');
        }
    }
}

So, how do I share those functions and variables between these nested classes inside Main? Of course, I could send those variables as arguments to the constructors but what happens when we need like 5 or 10 of them? I could send the entire object Config to Security and Security to Database,

// main.php
// here I include the other files
class Main {
    functions __constructor() {
        $this->Config = new Config();
        $this->Security = new Security($this->Config);
        $this->Database = new Database($this->Security);
    }
}

but is that reliable? Can I send only the reference (like a pointer, in C++)? Maybe I can send the hole Main object's reference as an argument in the constructor, and this way make everything available for everything.

// main.php
// here I include the other files
class Main {
    functions __constructor() {
        $this->Config = new Config();
        $this->Security = new Security(&$this);
        $this->Database = new Database(&$this);
    }
}

I don't even know if this is possible. What do you think? Are there any more conventional ways?

ali
  • 10,927
  • 20
  • 89
  • 138
  • Config could be a static class. Or, you classes could inheritates of base class Config. – Alexandre TryHard Leblanc Nov 03 '13 at 22:14
  • Database needs Security and Security needs Config. If Security inheritates Config and Database inheritates Security, does Database inheritates Config, too? What if Security needs Database? – ali Nov 03 '13 at 22:19
  • Yes it does inheritates config too :) – Alexandre TryHard Leblanc Nov 03 '13 at 22:20
  • 1
    1) I imagine you would soon realise, but you have some syntax errors in your example: `functions __constructor()` should be `function __construct()`. 2) This is what is known as "Dependency Injection"; all of your suggestions seem largely reasonable. 3) You don't need to worry about passing a pointer or reference to an object, as that's how objects naturally behave (specifically, `$foo =& $bar` makes `$foo` and `$bar` the same variable; but a variable only ever "points at" an object anyway, so `$foo = $bar` makes two variables pointing at the same object). – IMSoP Nov 04 '13 at 03:03

1 Answers1

0

As it is stated in comments you are starting to think in terms alined with Dependency Injection. You are defensively coding (and rightly so) to workaround the issue of SoC (Separation of Concerns). You might try like I did with something I call the Registry pattern (I'm ignorant on the subject so I named it after the windows registry). The registry holds all the objects that may need to be passed around. This gives some benefits on a practical level

  • If I'm not sure something else is going to need a var, I just tack it into the registry and the one which depends will know where to look for it, as long as I pass him the Registry
  • If my project is very small and I don't want to hassle around to much about the idea then this is an easy solution

There are quite a set of problems behind this pattern of thinking. Say the project starts to get bigger, I know it happens to me sometimes. Now simple tasks like debugging become mountain climbing as I try to find why a dependancy is not where I'm looking for it and I have to track down where it is set and at what point, and if some other piece of code changed it and why.

All this means is that instead of following the principles of SoC, we just passed the concern onto a third object that now bears ALL the responsibility. This "registry" object is now responsible for too many things and any changes that happen to it will ripple through all your code.

From what I've read around SO and other tutorials, if you have an object that is juggling too many dependancies (let's say constructor with 10 parameters) then we are probably not doing things right.

I hope someone else can chime in on this because I'm very interested on this subject but I have not been able to put it in practice (mainly due to ignorance)

hanzo2001
  • 1,338
  • 1
  • 10
  • 24