Pre-defining dependencies for controller objects.

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
Chris30
Forum Newbie
Posts: 15
Joined: Sat Jan 19, 2013 4:52 pm

Pre-defining dependencies for controller objects.

Post by Chris30 »

I've been using registry pattern for a very long time. Basically, I load all the classes using a main object (even if they're not required by the controller itself) and controllers can reach them.

It loads like 20 classes currently.

Like this:

Code: Select all

$this->database = new Database();
$this->bbcode = new BBCode();
... //moar here
$this->image = new Image();
However, I want to define dependencies for my controllers. For example, my register controller only depends on "database class, recaptcha class and filter class". Nothing else.

I kept reading about Dependency Injection and Dependency Injection containers. So, I want to create a solution like this:

Code: Select all

//load register controller
$this->controller = DependencyContainer::Load('register');

function Load($objectName)
{
     return new $objectName(new Database(), new Recaptcha(), new Filter());
}

Is it called DI/DI Container?
Is this a better approach than my current system?
Am I completely lost?
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Pre-defining dependencies for controller objects.

Post by Christopher »

You can certainly use a DI Container. However, I think usual practice for MVC Controllers is to have them explicitly instantiate their dependencies. Since typically the Front Controller loads only the requested "Action" Controller, it has already achieved some efficiency by limiting what needs to be included. If you then add a DI map of all the dependencies for all the Controllers then you have defeated this efficiency.
(#10850)
Chris30
Forum Newbie
Posts: 15
Joined: Sat Jan 19, 2013 4:52 pm

Re: Pre-defining dependencies for controller objects.

Post by Chris30 »

Christopher wrote:You can certainly use a DI Container. However, I think usual practice for MVC Controllers is to have them explicitly instantiate their dependencies. Since typically the Front Controller loads only the requested "Action" Controller, it has already achieved some efficiency by limiting what needs to be included. If you then add a DI map of all the dependencies for all the Controllers then you have defeated this efficiency.
I don't understand what you're trying to explain. Can you explain it with a little code sample? English isn't my native language so I'm having a hard time understanding some words, like instantiate etc.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Pre-defining dependencies for controller objects.

Post by Christopher »

One benefit of MVC with a Front Controller (in PHP) is that it only loads the code you need. The Front Controller uses the route (and other HTTP parameters) to determine which Controller to load. The Controller usually loads the View which uses Models to generate the web page. That provides a structured alternative to old way where every URL is a different PHP script.

Because loading some dependencies are part of this design, doing the loading with DI is just an extra layer. Some micro-frameworks do have all the dependency wiring in one place. But that is because they intended for smaller apps.

PS - instantiate means to create a single object variable from a class.
(#10850)
Chris30
Forum Newbie
Posts: 15
Joined: Sat Jan 19, 2013 4:52 pm

Re: Pre-defining dependencies for controller objects.

Post by Chris30 »

Christopher wrote:One benefit of MVC with a Front Controller (in PHP) is that it only loads the code you need. The Front Controller uses the route (and other HTTP parameters) to determine which Controller to load. The Controller usually loads the View which uses Models to generate the web page. That provides a structured alternative to old way where every URL is a different PHP script.
It's same in pretty much all frameworks. I do know about MVC pattern.
Christopher wrote: Because loading some dependencies are part of this design, doing the loading with DI is just an extra layer. Some micro-frameworks do have all the dependency wiring in one place. But that is because they intended for smaller apps.
That's the question I'm not getting.

My current approach for loading dependencies is like this:

Code: Select all


    class EngineModel
    {
            var $database, $bbcode, $filter;
            function __construct($config)
            {
                    $this->database = $this->createDatabase($config['DB_NAME']);
                    $this->bbcode = $this->createBBCode();
                    $this->filter = $this->createFilter();

                    $controller = $_GET['page'];
                    $controller = new Controller($this);
                    $controller->Start();
            }

           function createDatabase($config)
           {
                 require_once('library/database.php');
                 return new Database($config['DB_NAME']);
           }

          function others() { }
    }


     class Controller
     {
              function __construct() { }
             
              function Start()
              {
                     $this->enginemodel->filter->filterBasic($_POST);
                     $this->enginemodel->database->query($query);
              }
     }

Something like this. EngineModel loads every library class in construct, even if the controller doesn't need any of those.

But, I want a DI/DI Container approach, like this;

Code: Select all


//load register controller
$this->controller = DependencyContainer::Load('register'); //instead of new Controller();

function Load($objectName)
{
     return new $objectName(new Database(), new Recaptcha(), new Filter()); //register controller's dependencies are only 3
}

I don't know if it is a valid DI/DI Container approach. That's basically what I'm asking. I just want to get things done a bit more professionally and learn high level techniques like DI/DI Containers by practise.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Pre-defining dependencies for controller objects.

Post by Christopher »

I think DI is just one way for you to load classes. I think use your Registry for common objects and to make objects easily available. Create the objects unique to the request inside the Controller, Model or View for that request.
(#10850)
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Re: Pre-defining dependencies for controller objects.

Post by Weirdan »

Alternatively, you could use Service Locator to only load necessary services (common classes) on demand. It's simpler than DI container, but the resulting code is not as testable.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Pre-defining dependencies for controller objects.

Post by Christopher »

Weirdan wrote:but the resulting code is not as testable.
You can mock the Service Locator ... they are usually fairly simple.
Chris30 wrote:But, I want a DI/DI Container approach, like this;

Code: Select all

//load register controller
$this->controller = DependencyContainer::Load('register'); //instead of new Controller();

function Load($objectName)
{
     return new $objectName(new Database(), new Recaptcha(), new Filter()); //register controller's dependencies are only 3
}
In looking at your code again, that should be done using a Front Controller -- which can be thought of as a DI Container or Factory just for Controllers.
(#10850)
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Re: Pre-defining dependencies for controller objects.

Post by Weirdan »

Christopher wrote:You can mock the Service Locator ... they are usually fairly simple.
Yes, you can. However (depending on how you use it though) Service Locators are frequently implemented as a Singleton, so they have essentially the same problems, testing-wise, as Singletons do.
Chris30
Forum Newbie
Posts: 15
Joined: Sat Jan 19, 2013 4:52 pm

Re: Pre-defining dependencies for controller objects.

Post by Chris30 »

Christopher wrote:
Weirdan wrote:but the resulting code is not as testable.
You can mock the Service Locator ... they are usually fairly simple.
Chris30 wrote:But, I want a DI/DI Container approach, like this;

Code: Select all

//load register controller
$this->controller = DependencyContainer::Load('register'); //instead of new Controller();

function Load($objectName)
{
     return new $objectName(new Database(), new Recaptcha(), new Filter()); //register controller's dependencies are only 3
}
In looking at your code again, that should be done using a Front Controller -- which can be thought of as a DI Container or Factory just for Controllers.
What is a front controller?
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Pre-defining dependencies for controller objects.

Post by Christopher »

Chris30 wrote:What is a front controller?
It is a single entry point for you application that loads the appropriate Controller based on the Request.
(#10850)
Post Reply