Multiple views in MVC-like PHP Frameworks

How about the original academic work? https://heim.ifi.uio.no/~trygver/1979/mvc-2/1979-12-MVC.pdf

A view is attached to its model (or model part) and gets the data necessary for the presentation
from the model by asking questions

Or the subsequent works in academia: http://www.math.rsu.ru/smalltalk/gui/mvc_krasner_and_pope.pdf

The standard interaction cycle in the Model-View-Controller metaphor, then, is that the user takes some input action and the active controller notifies the model to change itself accordingly. The model carries out the prescribed operations, possibly changing its state, and broadcasts to its dependents (views and controllers) that it has changed, possibly telling them the nature of the change. Views can then inquire of the model about its new state, and update their display if necessary.

http://www.dgp.toronto.edu/~dwigdor/teaching/csc2524/2012_F/papers/mvc.pdf

the view could then request the current state of the string from its model

Or outside academia, here’s an article from Oracle http://www.oracle.com/technetwork/java/mvc-detailed-136062.html

View -The view renders the contents of a model. It accesses enterprise data through the model and specifies how that data should be presented. It is the view’s responsibility to maintain consistency in its presentation when the model changes. This can be achieved by using a push model, where the view registers itself with the model for change notifications, or a pull model, where the view is responsible for calling the model when it needs to retrieve the most current data.

Controller as mediator MVC only became “MVC” when PHP and Ruby developers decided to label what they already had (A DAO, A template system and an entry point) MVC.

Honestly, it really should go without saying that in this topic, in this forum, we’re talking about the web industry. And the web adaptation of MVC has indeed been an industry standard for a very long time (longer than you think). And when the sources you quote talk about the view subscribing to the model for change notifications so the view can update itself, that should be a big red flag that the pattern you’re adhering to so religiously isn’t even applicable to the request/response nature of a server-side web program.

You don’t know your history as well as you think you do. Fowler’s description of web MVC in PoEAA pre-dates any of the PHP or Ruby MVC frameworks. And I know of at least one Java framework (Struts) that pre-dates PoEAA.

On the web, the view is automatically refreshed so it actually makes it easier to follow the original pattern, you don’t have to worry about triggering an update to the view, that’s done for you. The fact that people took the original concept and thought “that’s sort of like what we’re already doing with templates and database abstraction” doesn’t mean they were following mvc.

http://martinfowler.com/eaaCatalog/modelViewController.html

Oh look, the View has a dependency on the model… this page is linked from “web presentation patterns” here: http://martinfowler.com/eaaCatalog/index.html and he specifically mentions Trygve Reenskaug, who I quoted earlier who says… “A view is attached to its model”

On the page here: http://martinfowler.com/eaaDev/uiArchs.html#ModelViewController he says:

MVC does it by making updates on the model and then relying of the observer relationship to update the views that are observing that model.

edit: this is straight from PoEAA figure 4.1 in the chapter “Web presentation”

See how the view gets data from the model?

Definitions aside, there is zero advantage to the “web mvc” approach as discussed in the other thread.

Yep. But the important point here is that it is the LayoutView that is responsible for rendering the entire html page. The ProductView and the SidebarView only need to worry about their own stuff.

The LayoutView is then shared with all your different ContentViews such as the ProductView, ServiceView, ProfileView etc. The views are all independent. No need for additional routing information etc. The only link between the ProductView and the LayoutView is that ProductView extends the LayoutView. And of course you could avoid this link if you really wanted to.

If only Fowler had continued with more detailed descriptions and even code examples of how he would apply the concepts of MVC to the web.

Oh… he did. :wink:



If you read past the pictures, you would know that the kind of model object in that diagram is what we would call an entity object. The controller forwards business logic to a model object, the model object talks to the data source and gathers information, and the controller passes that information to the view. All our modern frameworks do indeed pass entity objects straight to the view, and in that sense, the view is using a model object. But what you’re suggesting people do isn’t just the view using a value object, you’re talking about the view interacting with a repository / data store.

We clearly have very different memories of that discussion. :wink:

Then his diagrams and his example code contradict each other. I’ve several issues with that approach, the controller contains display logic (which view should I display?) as well as domain logic (A classic album is different somehow to a normal object). As I’ve said before when you used that example, it’s a very good example of how web mvc blurs the concerns.

MVC is about reuse of components, this code makes it impossible to reuse any of the logic if I wanted to use a different template… and I have to change it and add a corresponding view each time I add a different type of album.

Not at all, it has access to the model which has a state, a model is not a repository (which seems to be the fundamental error made by web mvc proponents)

I’d love to have a look on that, as I’m as well currently putting together a rough prototype to give that concept of a mighty View a try.

And this is why I prefer discussing working code. You did a good job with your webMVC project. Hopefully, you will continue with it.

A request comes in and something gets kicked off. I don’t care what the something is called. Controller/View/Action/Trump. Call it whatever you want. Just show me the code.

I understand what you are saying, but to me, the view is only the view or at least it should be. A templating system and the templates it uses is just a subsystem of the view. So, when a controller says “render”, it is asking the view and its templating subsystem to build an output with the template and data it is given. Then the view returns a whole HTML page, because that is how the template is built, with navigation, sidebars and all, even though the controller only asked for one rendered template.

The same goes for the model. It is in the form of only a couple of entry points. We might say we have “models”, but in essence, we are making a request from one or two objects to either retrieve or manipulate data. It has to be this way too, because of the abstraction needed for reuse. In fact, as Tom mentions and I think I mentioned too, this is where controllers lose out. We don’t have a single “controller” with subsystems. We have page controllers, which are unique and rarely, if ever, reusable.

When I think about it, the “render” method in both the controllers and templates in Symfony couple the controller and view together pretty tightly too. Ok. That is the way Symfony is built. But, is it really necessary?

Scott

Thanks. These kinds of discussions offer the motivation to continue too. I’ve also learned some things in the relatively short time since I did that little bit of coding and from those learnings, I know I made some basic mistakes too (like poor encapsulation). That needs correcting. I also have no testing. I need to also get that in.

I also need to do something better with routing logic. It’s just that the finished router libraries I’ve seen, don’t do what I think they should. They say, “tell me what the URI should look like and where that kind of request should go?” Whereas, I want the router to say, “give me a pre-configured convention, which tells me how to break up the URI into usable and logical data for whomever needs it in the application”. I guess what I am looking for isn’t really a router. What could it be called…hmmm…URIConverter? :smile:

Scott

A fact important to repeat :wink:

That makes sense for computer-computer interaction. It’s another story when a human user requests an url. In that case the url rather describes the desired content but the technique used to deliver the content. Two examples: First, a multi-lingual website where /en/highway/cars and /de/autobahn/auto call the same application components, second, an search-engined-optimized website with an url like /reliable-cheap-products/for-craftsman-and-handyman/super-duper-chain-saw which in RESTful words could be translated into /products/12/837.

In my eyes, it is somehow applicable, if we quit regarding the browser’s user as the web application’s user and the browser’s content as the web application’s View. There is no human user communicating with the web app, in fact it’s an HTTP-Request. We don’t update the browser window, we update/fill an empty View, deliver that and than exit the application.

Hereof I have a question of understandin. In classical MVC, the View calls the Controller to get a Model, which then get’s observed by the View or updates the View, right? Or does the View directly call a Model?

This interesting. But, for both examples, I need some sort of logical convention to follow AND for the search engine URI, super-duper-chain-saw must be unique. Thus, it is the object of the URI. All the other stuff is possibly just SEO fluff.

Scott

Right, but for the purpose of User Experience this convention may differ throughout a website (= app). Then, in a way we have a frontend and a backend URL. And therefore we need a Router.

In MVC (non-web) the model is assigned to the view, either by the controller or earlier in the execution (a controller, model and view are instantiated all at once). The view has direct access to the model and calls methods on it.

Taking the example Jeff cited from Martin Fowler, it would look more like this:

class AlbumController {
	private AlbumModel model;

	//Java constructor
	public AlbumController(AlbumModel model) {
		this.model = model;
	}

   public void doGet(HttpServletRequest request, HttpServletResponse response) {
   		this.model.setId(request.getParameter("id"));
   }
}

And if we introduce a proper model

class AlbumModel {
	private int id;
	private Repository albumRepository;

	//Let's use DI instead of static methods for the repository, I'll explain why shortly.
	public AlbumModel(Repository albumRepository) {
		this.albumRepository = albumRepository;
	}


	public void setId(int id) {
		this.id = id;
	}

	public Album getRecord() {
		return this.albumRepository.find(this.id);
	}
}

The view would then contain the display logic to show a different set of HTML based on the type of object and it would call model.getRecord() to retrieve the loaded record.

So why is this better? Well this isn’t, it contains the exact same problem that the original code does: It’s not reusable and incredibly specific. However, with a couple of minor changes:

class LoadRecordController {
	private LoadRecordModel model;

	//Java constructor
	public LoadRecordController(LoadRecordModel model) {
		this.model = model;
	}

   public void doGet(HttpServletRequest request, HttpServletResponse response) {
   		this.model.setId(request.getParameter("id"));
   }
}

interface LoadRecordModel<E> {
	public void setId(int id);
	public E getRecord();
}


class RepositoryModel<E> implements LoadRecordModel {
	private int id;
	private Repository repository;

	//Let's use DI instead of static methods for the repository, I'll explain why shortly.
	public RepositoryModel(Repository repository) {
		this.repository = repository;
	}


	public void setId(int id) {
		this.id = id;
	}

	public E getRecord() {
		return this.repository.find(this.id);
	}
}

Now suddenly the advantage is obvious. Using Jeff’s example, I need to create incredibly similar controllers for loading a single blog/user/product/category/post/topic/etc into a view based on its primary key. Using the above code I can reuse the same model/controller with only a different view (by passing the required blog/user/product repository into the model). Not only that, I can use a different model e.g. load a twitter post by ID via the twitter API by writing a second model that implements LoadRecordModel… or one that reads data from an XML file/CSV rather than a repositry using the same controller and view.

Web MVC puts the application state and display logic (deciding which view to use) into the controller, heavily reducing reusability as well as coupling the controller to domain concepts (repositories and entities)

1 Like

I so much get this and like it.

Tom, it was mentioned above you had a working framework with possible similar logic in it. Is it true and if yes, can you point us to it?

Scott

I have a framework along these lines I’ve been using for a couple of years on various sites but it’s not quite where I want it to be, however from that I’ve been building a framework from the ground up. I’ll try to put up some code over the next couple of days after I’ve tidied it up a bit.

I had a bit of a stumbling block, I didn’t like the way the templates worked and have always been uneasy about having each route need two templates (one for the layout, one for the content and some way for a controller or something to select the layout) However, I’ve now solved that with transphporm so can get back on track :slight_smile:

No rush from my side. I was just interested in seeing what you have.

Scott

Let’s take a visit to the land of code with a simple example. We want to show the details of a single item.

public function showAction($request)
{
  $itemId = $request->getAttribute('id');

  $item = $this->itemRepository->find($itemId);

  $templateData = ['item' => $item];

  $html = $this->templating->render($this->templateName,$templateData);

  return new Response(200,$html);
}

So we inject a repository (for accessing the database), a templating engine for rendering(could be twig, coulld be php etc) and the name of the actual template file. For each type of item (product, email etc) we define a service and inject the specific dependencies. We then map each route, GET /product/:id:/show to a specific service.

The code seems reusable… Is it tightly coupled? I’ll let you answer that.

It’s also fairly easy to make a editAction in which we inject a form object to allow updating or creating items.

And of course this is a very simple case. Before we can really compare approaches we need to nail down actual use cases.

It’s probably worth having a read through the previous thread if you missed it at the time:

Thanks, @TomB! Based on the mentioned examples, I’d like to ask another question.

Again, in classical MVC, is there one view component per app, while there are many models with controllers? Or does an app consist of bundles, each packaging a model, a view and a controller? Do I misunderstand the concept by seeing the view as the visible user interface rather than a collection of templates that get rendered on demand?

In the context of this thread’s initial question: in $html, how would you access data from outside $this->itemRepository?