-3

I have a simple PHP MVC framework that works this way:

   StaticFramework (1)
          |
          V
         DIC (2)
          |
          V
     HTTPRequest
          |
          V
         App <-> Router
          |
          V
      Controller <-> Model
          |
          V
         View
          |
          V
     HTTPResponse

(1) StaticFramework is a static "Front controller" that gives the App its default dependecies with the (2) DIC (Dependency Injection Container), which works in a similar way to Pimple. The container can be accessed to change those default dependecies. For example, the Router class is injected in the App by the DIC.

I have a problem here, as it is a MVC application, I have 3 important layers:

  • Model;
  • View;
  • Controller.

Injecting the View is easy as it is only a class which has a render method that renders a PHP or HTML file, so I just have to inject one instance of View in my Controller.

But injecting the Model in the Controller seems harder. Each Model is a separate class and so I can't inject it as I do for the View. Each Model might also require other dependecies, such as a Database or a XML class for example.

Moreover, I cannot predict which models the Controller will require, as it might need several of them, for example, the ArticleController requires the ArticleModel and the UsersModel.

I have a few solutions:

  • Injecting a ModelFactory class in the Controller which will instanciate the models for the Controller. But as each Model might require different dependencies, the ModelFactory must know which one it will need, which doesn't seem possible with a DIC similar to Pimple;
  • Not injecting models in the Controller, and leaving each of them as a separate class, that extends what they need. For exemple, a Model should extend Database if it requires a MySQL connection. But it means the model is tightly dependent of its parent, and it makes it impossible for a Model to use mock classes or have several data sources, for example, what if a Model needs both Database and XML?

So, what is the best way to inject models in the Controller in the case of my framework?

Thank you in advance for your answers.

Informancien
  • 255
  • 3
  • 13
  • 2
    pimple is not DIC it's service locator – Linus Sep 14 '16 at 09:34
  • ^ It's a glorified associative array used as a service locator – Jimbo Sep 14 '16 at 09:41
  • @Linus I know some other DICs work in a different way, like predicting dependecies with reflection and such, but how is Pimple not a DIC? Moreover, I know that service locator is an anti-pattern as it creates tight coupling between the application and the service locator. But for example, if you inject a `Container` (a Pimple-like one) in another object for it to get its dependencies from the said `Container`, how is it creating tight coupling and so is an anti-pattern? By the way, thank you for your comment. – Informancien Sep 16 '16 at 21:07
  • 1
    @TheKitsuneWithATie have a look upon this http://stackoverflow.com/questions/16472924/design-patterns-how-to-create-database-object-connection-only-when-needed/16605563#16605563 and any DI container is Serivce locator if injected into Objects – Linus Sep 16 '16 at 21:22

2 Answers2

5

Gods below, this makes me really sad.

  • "static framework" means that the basis of your code is in global state
  • pimple is not a DI container
  • what you describe is not a "view", but a dumb template
  • model is a layer, not a class to be injected
  • you should learn to use namespaces instead of abusing suffixes

</rant>

Your controllers should be interacting with Services. The model is the entire thing containing persistence abstractions, domain entities, services, repositories and things that are used to describe the business logic of your application.

Anyway, to populate your controllers with the necessary services, you should use a proper dependency Injector. I would recommend either Auryn (reflection-based) or Symfony DI (configuration based).

Jimbo
  • 25,790
  • 15
  • 86
  • 131
tereško
  • 58,060
  • 25
  • 98
  • 150
  • First of all, `StaticFramework` is not required for the `App` to work, as I said, it only gives it its default dependencies, so the `StaticFramework` (which is more of a "front controller" I think) can completly be unused if you want. Second, I use namespaces in my real code, but I gave simple class names here just to give an example. Also, I'm aware that the Model is a layer and not a class, but when I say a "Model", here, I mean a class that manages/retreives data (SQL, XML, cache...) for the `Controller`. Also, I'll look at the DICs you recommanded, thanks. – Informancien Sep 16 '16 at 20:58
  • 1
    It doesn't matter what you mean, it's what you say - we all need to be speaking a common, ubiquitous language in order to understand each other and what better way to do that than the *correct* way? – Jimbo Nov 03 '16 at 19:33
0

The way this was solved in ASP.Net MVC is that a request is always directed to a method on a controller (not the controller itself).

The App from your example would look at that method's arguments and invoke specific model binders for each argument's type.

This might prove tricky in a language which is not type safe :P

Axel Wilczek
  • 195
  • 2
  • 9