2

I have been researching so many times, asking experts on stackoverflow for the best practice, but I still could not find the solution, I might have got told the correct answer, but I didn't get it.

I always wanted to create a 'proper' MVC pattern to work on my projects, I have been researching for example this http://www.phpro.org/tutorials/Model-View-Controller-MVC.html but I got told that this is awful design, and I should not use the registery pattern anymore.

So I looked at teresko's answer, even though it's very old, can be seen here How should a model be structured in MVC? and I got the idea there, to use a global factory, which will create other factories

The idea I got from there, is to have a big factory, called ServiceFactory which will create instances of other factories like ModelFactory which will create instances of classes that are serving the model layer, and a ViewFactory, which will serve the view (Pretty useless at the moment I think).

But got something like this:

namespace library\application;

use library\application\exceptions\ClassNotFoundException;
use library\application\exceptions\PackageNotFoundException;

class ServiceFactory {

    private $mapper;
    private $package;
    private $services = array();

    public function __construct(DataMapper $mapper) {
        $this->mapper = $mapper;
    }

    /**
     * Setting a default package
     * @param $package  string  Package path
     * @throws exceptions\PackageNotFoundException
     */

    public function setDefaultPackage($package) {
        if (is_dir('library' . $package)) {
            $this->package = 'library' . $package;
            return;
        }
        throw new PackageNotFoundException("The package: " . $package . " was not found.");
    }

    /**
     * @param $name string  Class name
     * @param null $constructor IF the class needs constructor parameters, use it.
     * @return Factory
     * @throws exceptions\ClassNotFoundException
     */

    public function create($name, $constructor = null) {
        $path = $this->package . "\\" . $name;
        if (file_exists($path)) {
            if ($constructor) {
                return new $path($constructor);
            }
            return new $path;
        }
        throw new ClassNotFoundException("The requested class was not found: " . $path);
    }

    /**
     * @param $name     string  Class name
     * @param $object   object  Object to register
     */

    public function register($name, $object) {
        $this->services[$name] = $object;
    }

    /**
     * @param $name string Class name
     * @return Factory
     */

    public function get($name) {
        if (isset($this->services[$name])) {
            return $this->services[$name];
        }
        return null;
    }
}

This is awesome actually, but in my opinion, OO-wise, it's totally wrong, because it's not object-oriented friendly, since the returning object of S ServiceFactory::create() is anonymous, well fine, It's no longer anonymous, because the purpose of the class is to create instances of factories, sure, just added the interface of the factories in return.

But now the next problem, when I want to use the factories to create objects, that should not have the same interface, will cause problems to my IDE, since it doesn't know what is the object I am going to return, it can be Foo, can be Car and one day it can be HelloWorld.

So I always will have to declare a variable with the object when using it in the controller:

    /**
     * @var $items  Items
     * @var $categories CategoryModel
     */

    $items = parent::getModelFactory()->create('Items');
    $items->setDb(parent::getDatabase());
    $categories = parent::getModelFactory()->create('Categories');
    $categories->setDb(parent::getDatabase());

Now in one of Teresko's answer(s), it says the following rule: A controller can not create instances of the Model layer

So I assume he means like $foo = new Foo(); $foo->method($db); in the controller, but why not? how should a controller actually communicate the model layer?

The main purpose of me creating that god factory class, is to prevent doing new Object() in the controller class, but since it's calling the factory, which creates the instance, it's still considered as I am creating an instance of a model layer in a controller (I think).

I also could cache objects, using ServiceFactory::register() method, but that doesn't change the situation.

So is the ServiceFactory and factories idea fine ? What is the correct way communcating between the controller and the model layer?

Community
  • 1
  • 1
Artemkller545
  • 979
  • 3
  • 21
  • 55

1 Answers1

0

Not really, but there aren't any rules in how to implement MVC as long as you have M V C clearly defined and C acts as a coordinator for M and V.

A factory of factories is clearly over engineering, if you don't need it don't implement it. What you need to understand in order to be easy for you to apply MVC is that 1) MVC is part of the UI layer and 2) Model refers to the bits of other layers (like, for example, Business, Persistence or Application/Service) which are used by the UI.

The controller always communicates directly to the Model, but depending on the use case, the Model means that bits of layers mentioned above. In a 'normal' app, it usually is like this: the controller uses an application service (the MVC Model) to update the business model. The service should be injected in the controller constructor.

For querying purposes, the controller can use a "querying service" or a query only repository so that it won't contain persistence logic (like writing sql). It still the same approach like above, only this time, the Model represents Persistence bits.

So you see, the Mvc Model is actually a facade for other layers used by UI and you want the controller not to have direct access to the business layer for example, because the controller should really just coordinate what model to change and what view model to be rendered. In contrast, an application service will implement an application use case using business/persistence objects.

Everything is really about respecting Separation of Concerns and Single Responsibility Principle

MikeSW
  • 16,140
  • 3
  • 39
  • 53
  • So when you say I need to inject the application service to the controller, what would the application service be like? Where should it be created? Should it be created by the service factory? – Artemkller545 May 05 '14 at 13:53
  • Forget about factories. An application service is created by the app developer and it's specific to that app. Usually, the MVC framework should use a DI Container to create the controller and this takes care of the injecting part. Btw, there are a lot of Mvc frameworks, learn at least one of them and create your own only _after_ you hit some limitations. Don't reinvent the wheel unless it's a much better wheel. – MikeSW May 05 '14 at 14:04
  • `Not really, but there aren't any rules in how to implement MVC as long as you have M V C clearly defined and C acts as a coordinator for M and V.` this is incorrect. `because the controller should really just coordinate what model to change and what view model to be rendered.` completely wrong.. – Ronni Skansing May 08 '14 at 11:20
  • @RonniSkansing And what is _correct_? Also feel free to provide a code example, I want to see how a _correct_ controller is implemented – MikeSW May 08 '14 at 12:26
  • @MikeSW just try the wikipedia article. Rails, CI, php framework do not implement a even near mvc scerio. Sorry you have been mislead. Take a look http://stackoverflow.com/questions/3066590/gui-not-working-after-rewriting-to-mvc/3072979#3072979 to understand that mvc is not just a 3 seperate concerns and folder structure. – Ronni Skansing May 08 '14 at 12:29
  • Lol, rails and CI are your example? OK. Don't be sorry, I wasn't mislead besides, MVC is about separating the 3 (UI) concerns regardless of folder structure. Your example is a java desktop app, things work differently in a _web_ app. – MikeSW May 08 '14 at 12:42
  • @MikeSW =] lol no, CI, rails are examples of stuff that does not implement a MVC scenerio. (see the sentence, "do not"). My example is a java desktop app because that is a place where MVC makes sense. In webapp people treat the View as the response, which it isnt, also the controller is not a mediator. The example shows you that the *model notifies the view (or the view polls the model). * So you post is completely off – Ronni Skansing May 08 '14 at 13:58
  • Feel free to join the php chat if you want to talk some more =] http://chat.stackoverflow.com/rooms/11/php – Ronni Skansing May 08 '14 at 14:06
  • Yeah, MVC appeared long before web existed. As long as you have a Model View Controller with clear responsibilities, it is MVC regardless of the true and holy form. That being said, my Controller will select the proper model to issue an update/query then will push a view model which used by a view. Clean, achieves its purpose. We should care about utility and benefits not dogmatic implementation details. – MikeSW May 08 '14 at 14:07
  • @MikeSW Seems you are just taking the M V C chars and putting your own idea into them.. A model does not have to do anything with persistence ( it can! but does not have to). Things should not extend from a model... Just because you know the 3 words, put a meaning it in, does not make it a MVC. Like calling $integer = 10.1; does not make it a int, it is still a float. – Ronni Skansing May 08 '14 at 14:09
  • You clearly haven't read my answer properly. Read it again, in the mean time I'll go write some more incorrect controller code – MikeSW May 08 '14 at 14:15
  • @MikeSW =] I think we can leave it at disagreement. But I still encourage you to come and share you "MVC" in the chat room and see what other people with decades of experience think – Ronni Skansing May 08 '14 at 14:18
  • I'm one of those people btw (12 years web exp). And amazing how ALL the mvc web frameworks are wrong. I'm actually using asp.net mvc, I don't do php anymore. So regardless of platform (php, ruby, .net) everyone uses the incorrect definition. Everyone but people coding desktop apps, right? – MikeSW May 08 '14 at 14:25
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/52317/discussion-between-ronni-skansing-and-mikesw) – Ronni Skansing May 08 '14 at 14:26