3

I've created a simple ServiceFactory class, which runs other Service classes, stores and gets instances. The same ServiceFactory object is shared between both the View object and Controller object.

The Controller changes the state of the Service:

class User extends Controller
{
    public function index($user)
    {
        $userService = $this->service->run('User');

        $userService->index($user);
    }
}

The View gets data from the Service and decides which template to use:

class User extends View
{
    public function index()
    {
        $userService = $this->service->get('User');

        $this->data = $userService->data;

        $this->template = 'user/index'; // render
    }
}

Am I doing it correctly?

In this answer tereško said that: "Controller is responsible for changing the state of both View and Model." My Controller has nothing to do with the View. I would like to see some examples of how Controller and View should work (Model2 MVC).

Community
  • 1
  • 1
5079787
  • 33
  • 6

2 Answers2

2

Am I doing it right?

Sort of.

Let's start with extends. When you use extends, you're implying an is-a relationship, so when you say User extends Controller, you're saying that a User is-a Controller. Is that the case? No. Perhaps you could rename to UserController and that would make more sense contextually.

$userService = $this->service->get('User');

This is called a service locator, and it's well known as an anti-pattern. Why is it an anti-pattern? Because in object oriented programming, each object's public methods are an API to it's usage, and you should be able to see an objects requirements entirely from it's constructor and method signatures.

With your code, a developer has to read through the whole thing to see "oh, so here's where I'm using another object" and further down "here's where I'm using another".

Your code should read like this:

public function index(UserService $userService)
{
    $user = $userService->getData();
}

With that code change, developers can see what external objects your object requires to function - and now this is testable (not that you would test your controllers that contain no logic - they're just the 'glue' for your code that is already tested).

You should be injecting your components and the View into the Controller:

class UserController extends Controller
{
    public function index(UserService $userService, View $view)
    {
        /** This or something similar **/
        return $view->render($userService->getData());
    }
}

Some people inject a View, some people inject a TemplateEngine like twig, and called render on that with the data. It's up to you, you can delve more into the specifics given your current scenario.

If you're wondering how you would inject your user service into the index action, that's the job of a dependency injector like Auryn that uses reflection to read object constructor or method signatures to determine what to create before injecting them automatically in your controllers.

Laravel stole the idea and now has that implemented for their controllers, hopefully Symfony will follow along soon.

Closing note: Don't try and strictly adhere to 'MVC' - it's not possible in the classical sense for PHP with the request -> response -> dead cycle. Instead, focus on the separation of concerns associated with it and make your code maintainable, testable and easy to read.

Jimbo
  • 25,790
  • 15
  • 86
  • 131
0

In a client-server architectures there is a problem to implement the "original" idea of MVC. In theory the Controller should modify the Model. Than the Model should be liked by e.g. an event with the View to update it.

Example: I change the state of a user e.g. the firstname by clicking some button. This leads to a action in a controller which updates the User-Model ( a domain model living in the model-layer). Now the Model should "imform" the View to update the firstname of the user. You could use "commet"-architecture ( https://en.wikipedia.org/wiki/Comet_%28programming%29 ) to link the Model to the View. So an update of the User-Model would couse an update of the View.

Gizzmo
  • 691
  • 8
  • 21
  • There is no such thing as a "user model". The model in mvc is a **layer**. You're likely referring to the user **Entity**? We need to be using the same (correct) terminology if we're going to help each other :-) – Jimbo Jul 08 '15 at 13:04
  • Sure Jimbo, but a entity is coupled to the database a generic domain-model not. In my explanation i ment one class from the model-layer, a domain-model, which can use a entity to crud DB or even other strategies.:-) – Gizzmo Jul 08 '15 at 13:16
  • @jimbo, btw you answer does not answer the question;-) – Gizzmo Jul 08 '15 at 13:19
  • An entity is not *at all* coupled to the database, unless you're using the active record pattern - where you should seriously consider using data mapper in that case. An entity is just a dumb object. Check out entity / repository, coupling any entities to their persistence is definitely a no-no. – Jimbo Jul 08 '15 at 13:20
  • OK, so you understand "entity" as that what i understand as "model". Coupling it to persistance is a no-go right. btw i use data mapper;-) – Gizzmo Jul 08 '15 at 13:30