Global on/off switches and PHP OOP

What’s the best way to implement “global on/off switches” in OOP for certain features of your site? Like the option to turn off the ability make posts (entirely), the ability to log in or register, and so on. I used global constants for these before but this seems break some OOP design theory (which I am brand new to). It is only for a single project, though. Is it still best to use constants in a config.php file and include that file everywhere? I will need to make use of these constants (or constant like objects) in several classes, some of which are entirely unrelated to each other. I know there are class constants, but the amount of editing it would take to incorporate those into every class seems like a downgrade from just including a config.php in the header of each page…

I guess I am running into a theory wall where it seems my interpretation of the OOP way of doing things seems like the wrong way.

In a nut shell I want to know what to do about:


define("REGISTRATION_ON", 1);

Typically, as applications grow larger and more complex, they become increasingly difficult to manage. “Design theory” gives us principles and patterns that help make the complexity manageable.

One of those principles is to, where possible, write portions of your code as if it were a standalone library. The idea is that a developer could understand and reuse that portion of your code without having to know or use the whole of your application.

To achieve that, your standalone library would have to cut all ties with the larger application. It can’t assume or rely on config files or global anything. Instead, whatever information it needs will have to be passed in as arguments.

Before, you might have done something like this:

function registerRequestAction()
{
    if (![COLOR="#FF0000"]REGISTRATION_ON[/COLOR]) {
        header("HTTP/1.1 404 Not Found");
        return;
    }

    // ...
}

But instead you’d do this:

function registerRequestAction([COLOR="#FF0000"]$registrationOn[/COLOR])
{
    if (![COLOR="#FF0000"]$registrationOn[/COLOR]) {
        header("HTTP/1.1 404 Not Found");
        return;
    }

    // ...
}

The difference is subtle but important. Now the function doesn’t need to know about the global environment anymore. Maybe the registration value ultimately comes from a constant… but maybe not. Maybe it comes from a config setting… but maybe not. The less our code knows, the more reusable it is.

If this logic was inside a class, we might write it this way:

class UserController
{
    [COLOR="#FF0000"]private $registrationOn;[/COLOR]

    [COLOR="#FF0000"]public function __construct($registrationOn)
    {
        $this->registrationOn = $registrationOn;
    }[/COLOR]

    public function registerAction()
    {
        if (![COLOR="#FF0000"]$this->registrationOn[/COLOR]) {
            header("HTTP/1.1 404 Not Found");
            return;
        }

        // ...
    }
}

Eventually, of course, you would undoubtedly still have to load some configuration, but you would do that in only one place, near the “front” of your application, and from that point on, you would pass those values as arguments.

Sounds like what you need is a configuration management system. The simplest way would probably be to create a class to get and set configuration values. You could write those values to a persistent storage like a database table. I would recommend scouring the internet for some examples of configuration management. You could also take a look at the Symfony Config component.

Thank you both, and especially thanks for those code examples Jeff - very informative. A question though - where should the “registrationOn” property’s value come from? Should that value be in a config file, or should it just be filled in when I make an object out of the UserController class? I think if I needed to fill the value of “registrationOn” every time I called the UserController class, that might lead to quite a bit of updating later because of trying to find out where the UserController class is instantiated as an object in various places.

I will check out the symfony component you mentioned, oddz. At this point, I am definitely re-inventing the wheel, but I like to that anyway for learning purposes. Currently, I am trying to create a basic website from scratch with various components as a way to learn oop and oop theory.

It could be both, actually. The “front” of your application could read that value from a config file if it chooses to, but then that value would be passed to the UserController (so that UserController can be ignorant of config files).

Indeed, you are absolutely right. :slight_smile: The way we solve that is by having a class whose only job is to know about (or “contain”) dependency information (such as UserController’s dependency on the registration value).

class Container
{
    protected $parameters = array();

    public function __construct(array $parameters = array())
    {
        $this->parameters = $parameters;
    }
    
    public function getUserController()
    {
        // The container knows what UserController depends on and how to create it
        return new UserController($this->parameters['registrationOn']);
    }
}

Then you would use it like this:

// The "front" of your application
class Front
{
    public function handle($request)
    {
        $config = include 'config.php';
        
        $container = new Container($config);
        
        $userController = $container->getUserController();
        $userController->registerAction();
    }
}

And of course the benefit we get from all this is that UserController (and any other class we handle in a similar way) gets to be blissfully ignorant of the global environment.

This is probably a topic well worth reading more about. The pattern where we pass in dependencies through arguments is called dependency injection, and the idea of a dependency “container” is called a [URL=“http://fabien.potencier.org/article/12/do-you-need-a-dependency-injection-container”]dependency injection container.

As Jeff Mott suggested the best way to do this would be to have a service manage configuration and delegate the injection of that service into controllers using dependency injection container. All of which would be much easier to understand if you were using a tried in true framework like Symfony rather than re-inventing the wheel. The primary principle though is that the class that manages configuration should know nothing about the controller. The configuration class instance should be injected into the controller, not the entire container. This can be done via simply passing via the constructor or more robustly adding a setter method to the controller to add the configuration. Than setting up an automated system of calling a method like init to act as a constructor override considering all dependencies should be added to a class instance before that class instance actually does anything.

Thanks so much - I think I am beginning to understand the idea a bit more. I am now learning about design patterns, so little disparate bits of knowledge are starting to come together. Reading through those links now, too. :slight_smile:

Oh design patterns now, good luck on that. Tbh the first time I read through design patterns I did not really understand much of them, at least not until I actually started to write down my own code. Not sure if my experience means anything to you, but the point is that learning design patterns by examples may not be effective(unlike language syntax like OOP). Its better if you work on your own application, by then you will see the power in design patterns. Again I must make it clear that its my own experience, everyone is different and you’ll likely to figure out a way to learn/grasp these concepts in your own way.