0

I'm building a simple MVC framework in PHP and I'm stuck at the part where I have to create a BaseController class.

Every "page" controller needs to extend from this BaseController. Because this BaseController class will have properties that will give the user access to a template engine and a Logger class (and some other things).

The problem I have is that I'm not sure how to instantiate those things in the BaseController class. I can obviously hard code it in the __constructo() like this:

class BaseController
{
    protected $view;
    protected $log;

    public function __construct()
    {
        $this->view = new \namespace\view('param1', 'param2');
        $this->log = new Logger('name');
        $this->log->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING));
    }
}

But this doesn't make it very modular. It makes it hard to change the Logger class for example. Or if the user wants to change the template engine to Smarty for example.

I also can't really use a form of Dependancy Injection. Because then every controller that extends from the BaseController will have to pass those instances to the BaseController.

That would look something like this:

class BaseController
{
    protected $view;
    protected $log;

    public function __construct($view, $log)
    {
        $this->view = $view;
        $this->log = $log;
    }
}

HomeController

class HomeController extends BaseController
{
    public function __construct($view, $log)
    {
        parent::__construct($view, $log);

        // Do my own stuff
    }
}

To me that's not really user friendly when a user only wants to do a simple thing in the __constructor. Not even with an IoC.

So the only thing that I can think of now is to use a Service Provider from the __construct method in the BaseController. But I'm not really sure if that's the way to go? Maybe there is a better alternative?

So what would be a good solution to solve this problem?

PS. And if I do need a Service Locator, are there any good examples out there? The ones I've found were written by people that seemed like they didn't really know what they were talking about. They were basically copying each others blog posts.

Vivendi
  • 20,047
  • 25
  • 121
  • 196
  • What sort of stuff would you be logging while in a controller? The data from the request? – ibanore Mar 15 '14 at 14:47
  • @David That was actually more of an example, I don't really need a Log class in there. Bottom line is, is that I need some instances of classes in my BaseController class. I need a way to get them in there in a modular manner. – Vivendi Mar 15 '14 at 15:07

1 Answers1

1

You first need to think what's a controllers responsibility, why would it need access to logging functionality or why would it be setting the template engine or switching templates?

The controllers job is simply to extract the data from the request(mostly form data/user input) and sending it to the model layer via a service, it should not be selecting templates, that's the views job.

You obviously want you keep the dependencies of your base controller to a minimum so that when instantiating child controllers you don't have a big list of dependencies to inject.

My base controller has two dependencies, the request object and a view which are both injected in. Controllers are simple and light, no logic or anything fancy should happen in them. Once ever I had to use a logger in one of my controllers but that was just because PayPal was sending a request to it using the IPN system and I needed to log all the data in the request to a file to see what was going on, other than special cases like that I can't see why a controller would need a logger. In this case only the controller which dealt with the PayPal request held an instance of a logger, not the parent base controller.

You should always inject your dependencies. Don't instantiate objects in constructors, it makes your class tightly coupled to those objects.

If you end up using a service locator it can be a sign that your classes break the single responsibility principle of OOP.

Controllers are meant to be simple, don't over complicate them by adding in dependencies you think they might need in the future, especially not to the base controller or you may have a lot of refactoring to do.

ibanore
  • 1,500
  • 1
  • 12
  • 25