1

Background

I am trying to design a reasonably useful MVC framework from scratch primarilty for my own education before jumping into Laravel/Symfony.

I am trying to implement dependency injection because plan on expanding this framework in the future and I want to keep things modular and maintainable.

Here is the MVC repository: https://github.com/JethroHazelhurst/psr-4-mvc

(Note: the controller/routing system is hard coded for simplicity!)

Here is my flowchart showing how the MVC framework is structured without dependency injection.

enter image description here As I understand it, the main dependencies are...

  1. Core\Router depends on Foo\Controller
  2. FooController depends on Core\Controller (via the parent::__construct method)
  3. Core\Controller depends on Core\View
  4. Foo_Model depends on Core\model which depends on Core\Database

Questions

So I am a bit confused as to how I should use dependency injection here... for example: How do I implement dependency injection with parent::__constructors (if at all)?

Also, is depending on parent::__construct like this making the framework too tightly coupled?

Many thanks in advance for your considered reply.

Jethro Hazelhurst
  • 3,230
  • 7
  • 38
  • 80
  • Can you tell what program you used to build such cool flowchart? Thanks! – A191919 Jul 06 '16 at 14:55
  • Sure, I used just plane old paint.net, I use layers to keep it easy to edit. One layer for the routes, one layer for the background and did a Prt Scr for the code. It really helps me visualize the code and it would be awesome if there was a program that helped us visualize code like this! – Jethro Hazelhurst Jul 06 '16 at 15:00

2 Answers2

2

I think you are confusing Dependency Injection and extending classes.

Dependency injection handles external dependencies for a class. This means that if you use one class in another class (using class A in class B, not extending class A) it's a dependency. The dependency container will create the instances automatically and hand them over to the class which needs them.

Further reading here.

Community
  • 1
  • 1
Crofly
  • 396
  • 3
  • 4
  • Thanks for taking the time to respond... so the only reasonable place to use dependency injection is in the Core\Controller (new View) and Core\Model (new Database)? Hmmm... – Jethro Hazelhurst Jul 06 '16 at 13:26
  • Yes. Every class which uses other classes should get their dependencies handed over. This makes it way more easy to change dependencies later and another good thing is that your code is way more testable(mocking). That dont means you need a dependency/service container. But it is a good and central way to handle dependency problems. But if you build your classes in a way that all dendencies comes from external(construct or setters) you dont have to use a dependency container from the start. Its easy to start using it later. But i would prefer using it from start. – Crofly Jul 06 '16 at 13:39
  • You could have a look at http://pimple.sensiolabs.org/ its a very simple dependency container and good to learn how it works. – Crofly Jul 06 '16 at 13:41
  • Thank you so much Croftly, things are starting to make sense. – Jethro Hazelhurst Jul 06 '16 at 13:42
2

You will actually need to implement dependency injection then. Presently there is none; no object are being passed their dependencies. In your constructors, you should be receiving the objects needed for correct execution. It's the basis of dependency injection.

Dependency injection would happen at the bootstrap phase of an application. I think of bootstrap as the action of preparing the environment to actually handle whatever it is called to do, in our case handling a http request.

Generally an index.php only calls a bootstrap.php file. That bootstrap file will route the request to a specific controller, creating dependencies along the way.

Using parent::__construct() is perfectly fine, it's how you will actually pass the objects dependencies. However, you can question why you need it. I don't see why your Controller should extend a core Controller. They actually don't always have the same dependencies, making it harder to manage if you make them all inherit from a base class.