Multiple views in MVC-like PHP Frameworks

Fair enough. So let’s leave the term “MVC” out of it, agree to disagree about exactly where the db queries should be made, and examine sub-requests a bit more closely in a request/response framework…

The browser issues a GET /products main request. The router calls the products controller which in turn loads the product entities and passes them on to the product view. The view generates the html for the products. All pretty straight forward.

But where does the siderbar come in ? Does the router need to know that the products page will have a sidebar? Seems unlikely. How about the products controller? Should it also query for the news items that the sidebar needs? Again, does not seem reasonable. Should the product view be concerned about displaying news items? Should the view for every page that needs a sidebar also have the code to fetch the latest (possibly cached) sidebar information?

I’m thinking no. Instead, imagine the sidebar is implemented such that a GET /sidebar sub-request will kickoff a sidebar controller which does the querying and then passes the data onto a sidebar view which in turn generates your html.

Then, as Jeff pointed out, you have a bit of logic in your layout template which allows the product view to add the product content and the sidebar view to add the siderbar content. The product component and the sidebar component remain blissfully unaware of each other and of course it’s easy to add the sidebar to whichever page that needs it.

Independent testable components which use the same routing infrastructure (including caching and security). What’s not to like about that?

If it works, great. I am thinking MVC can be done differently, possibly better. Maybe not. Call it MVCVM. LOL! :blush:

Since the view is putting a page together for any request, it would know the sub-template for the side bar needs some extra model data and would retrieve it accordingly. In fact, ALL of the necessary data would be gathered by the view, through the requirements set forth by the request and the associated templates needed to build the final page. If the request was for a write, the controller would do its modifying of the model and then send the message to the view that it is done. The view then calls up the data it needs. Or, since this process inherently serial, it just happens one after the other.

About caching of template output, where should that responsibility really be? In the controller? What happened to SRP? Isn’t the controller now becoming an almighty god class, controlling everything that has anything to do with the output of a page?

The decision to pull a cached version or get a new version of the template (and retrieve fresh data from the model) should be in the view IMHO. The logic, as to what to query, comes from the templates, the request and some sort of metadata about TTL timing and whatnot. And the metadata is not at all a part of the model. I keep thinking about a viewmodel and thus, why I am thinking MVCVM. Or, MVVMC.

One could argue a viewmodel is just another form of controller. In a way, it is. But, it only helps the view build the response, so it only has this single responsibility. The controller is then only responsible for manipulating the model. Another single responsibility.

It seems to me, most frameworks are trying to fit the architecture of the old-school page controller pattern of yesteryear. 1 page = 1 controller (or page of PHP). Maybe they did that, because it was a familiar pattern at the time, when frameworks were springing out of the ground like weeds.

Now we have the issue of needing more data in a page and thus we now call up a new controller, a sub-request controller. That just sounds like cludging to me. It is the way things are, so it can’t be done any other way. I still believe we can do better or maybe just differently.

And no, I am still not certain about that either. :smile:

Scott

Nope. A view is responsible for it’s content, not the entire html page. What else besides a side bar can go on a page? Headers, footers, login widgets, menus, etc and etc. I’m fairly certain you are not saying that every view needs to have full knowledge of every possible element on the html page. Let the ProductView take care of rendering the product content and let something else worry about stitching all the parts together.

Of course not. When did anybody imply the controller should do the caching? The application is in charge of dealing with caching on a per request basis. A sub-request merely takes advantage of it. Being able to cache portions of a page is a powerful capability.

Falling back into semantics again.

Always room for improvement. I know you have you have your own proof of concept framework. Consider adding a side bar using your proposed approach. I’ll be glad to implement the same app using sub-requests and we can do a nice side by side comparison with actual code.

By the way, no one is proposing “sub-request controllers”. They are just controllers processing a request. The controller neither knows nor cares if it is processing a sub-request.

Interesting point of view. (hahaha! pun not intended.)

I see where my point of view maybe different now. I am thinking of a view as an object, which is responsible for rendering the output. What the view actually ends up rendering can be any set of templates, or JSON or PDF. It doesn’t matter. It gets what it needs to render from the type of request and then goes to do its job of building a response. How would different outputs be taken care of in current frameworks? A controller for each type of output? Or conditional logic in each controller to get the different outputs?

Hmm…ok. I was reading something into what you wrote, that you didn’t say.

Actually, I do have a navigation template, which calls on a secondary object in sort of the manner I want a view to work. It isn’t exactly the same as what I now have in mind though. I’ll need to think about it some more and get back to you.

Well, that is also sort of getting into semantics too, isn’t it? I mean, a controller built to formulate a response that only fills in a sidebar for a parent template would only be used for that single (sub-)request. So, although it still is built like any other controller, it will only respond to a certain sub-requests. I highly doubt anyone would route a request to it, to get just the sidebar as a response, right?

Scott

Being able to render different types of output is of course one of the main reasons to keep controllers/views isolated. It’s doubtful that a request for product json would care much about sidebar information.

A common approach to specifying output format is to append a query parameter to the request. GET /products?_format=pdf. You can also do it with request headers.

Since controllers generally have access to the request then a controller can indeed take care of passing the product information into a format specific view.

Or you can divorce view processing from the controller completely. In Symfony for example, you can define view handlers which will take care of routing a request to a specific view. Lot’s of possibilities.

Reading your posts, I came up with an idea. The View in traditional MVC is not – or at least not only – a View, in terms of the presentation of an application. Maybe it should rather be called the „Interface“. On the one hand it is the part the user views at, on the other hand it is the pattern’s component where one houses the interaction code (on('click') { …). In the following I will use these terms: Interface (formerly known as View), contains View an Interaction.

In web applications we receive the calls of the Interaction (the Request) but we don’t know anything about the current View. The Interface exists in the user’s browser – although it was there before our application booted. Therefore we can not update the current Interface, respectively the Interface can’t update itself observing the Model. So, as a workaround, we don’t update the Interface but always replace it by a new one.

And here comes the crucial point. The above in mind, in web applications we have an abstract Interface. Even though this Interface quasi exists, the common way in current frameworks is to let a Controller create new Views. Is that a Controller’s task? I think it’s not. A Controller should be a collection of services associated to the application logic, handling calls from the Interface. The Interface should rather be instantiated by the application (by which i mean something outside the mvc pattern). On the one hand this Interface is equipped with its real live twin’s Interaction (which can be derived by the Request), on the other hand with it’s base template given. This Interface can call Controllers, based on it’s templates and subtemplates and subsubtemplates … almost like in desktop applications.

So, how could a lifecycle look like? Let me explain that by our above example website. A Request /news is received by a Router. A Route is defined with a target of App\Interface\News::list_news. In this method we create a new View with our template engine of choice which later gets delivered as the body of the Response. The template and subtemplates – as a part of the Interface – can access Controllers whenever they need data to get this data from the Models.

Another example. A POST Request /news/edit/3 gets received by a Router. A Route is defined with a target of App\ Interface\News::edit_post. In this method the Interface directly calls App\Controllers\Blog::edit_post() and then sends a response to initiate a HTTP redirect.

Routers create Interfaces, Interfaces contain logic associated to Interaction, Controllers contain the application logic, Models contain the business logic. A clean implementation of SRP, isn’t it?

So far … good night from Germany.

Actually, this is one of the things that makes a web application such a challenge. The challenge is to decide where the components that make the application work should all lie and how they are composed. The on('click') you mentioned is interface behavior handled strictly within the browser. Though, where was the HTML that holds that event “built” in the end? On the server or the client?

Let’s go a step higher. If you break the server down into its smallest roles, then I believe it only has two. One, it is the gateway to the data to show or manipulate through user interaction on a device (the real interface MMI). And the other, the server is the holder of the actual code needed to give the user the ability to interact.

Let’s concentrate on these two roles.

Frameworks like Symfony were originally built just before or during the start of the mobile paradigm shift we saw the past decade. So, they were built to serve “normal” web pages, which held both the code and the data and with the ability to be dynamic with both. This is all really cool stuff too.

Though again, these frameworks were created only at the start of the mobile paradigm shift. Now that we have this paradigm, developers want the client to do more and the server less. And still, it doesn’t matter. The code and data always originate from the/ a server. Think about this. Even an iOS or Android app must come from a server. And, in this scenario, the roles have been split between two servers. Apple and Google holding the code, and you as the app dev, you have a server holding the data.

So, where am I going with this?

I think, from a framework standpoint, we need to get away from the controller being the strong armed middle man and coordinator it currently is. We don’t necessarily have “pages” anymore, or rather, we are moving slowly but surely away from multiple web page applications. So, in that respect, we don’t need the page controller type of architecture we see in most frameworks. It ties our hands to that “old way” of composing the logic and thinking. All the “extra steps” of getting code and content together is still the norm. And, everything we do has to “fit” this methodology. Even worse, we even call it smart, if what we do works with it too, like when it also works for subrequests or REST APIs. Yippee, we made it fit!

If you will, we need a smarter dumb server, since the clients are getting smarter and smarter. And to me, that means the view needs to take over the role of the “getter” of data, no matter if it should bundle it in HTML or send out JSON or whatever else the client wants.

And, making this shift means, that would leave the controller with the role of only manipulating the model, as it was intended to do. Yes, it complicates the view and simplifies the controller. But, to change to be more proficient for a smart client/ dumb server paradigm, I think it makes sense. And yes…it is all theoretical. I wish I were a better programmer to make it all a reality faster to test. :frowning:

But, let’s go with this line of logic. Why do we need to turn a GET into any “Action” in a controller, assuming we are follow the HTTP standard and the GET is used for the retrieval of a resource only? We know what is being requested. Why do we even need the controller? The view can be (and should be IMHO) responsible for pulling the required data from the model. And, it has all it needs to “figure out” what to do. The request.

Now, probably one of the more experienced devs will chime in and say, but you are going to have to push the logic you need from the router into the view. Well, let’s let the router route to the view on GETS. We only need the logic (or convention) of “is this a read or a write request”? Read, go to the view. Write, go to a controller. And, once the controller is done with its changes, go automatically back to the view. Since the model is already built and modified by the controller, the view only has to get the data and output it, and in accordance with what was requested. The format can be conventionalized. (Is that a real word? LOL! :smile: ) Putting the data in HTML is only one convention.

So, in this scenario, if there is a subtemplate, the view knows (is told prior/ during template creation) to also request the data it needs to send out that HTML and data too. No controller has any idea (nor should it) that the view needed this data.

I feel this more direct routing of GET requests is simpler for the smarter clients we are moving more and more towards. And again, I may be wrong too. I still need to find that out. I am just coming into this world of frameworks looking for solutions and going “WTF?”. Like, why do I need an additional bundle to do REST in Symfony? To me, REST is now the standard, and putting a page together with HTML is just a nice-to-have fallback, which I also question should even be needed in this day and age.

Needless to say, that “WTF” reaction could also be the same reaction from someone else, if ever my contemplations became a reality too. :smile: I don’t know. I am just a rambling idiot myself. :blush:

Scott

I totally agree with you.

From a wide angle view, in modern web apps with their frontend frameworks on client side, the server may appear as a dumb butler for data. However, although it may act as a simple RESTful api, it’s still an application. In my eyes, interactions in the mvc universe are sent to the View – may it be a click on a button in a desktop application, may it be a Request sent to the server. Above all the View should know what to do.

This is, where i have a different opinion. As I tried to explain in my last post, if we try to apply the mvc paradigm, we always already have an abstract View – or better to be called virtual View – we receive its interaction. And we always have to deliver a View, may it just be a Response with a 2xx HTTP status code in reaction of a POST/PUT/DELETE Request. So also POST, PUT, and DELETE Requests should be routed to a View, which then decides what to do.

Again. The View in web application should IMHO not be seen as the visible representation of our application (e.g. the HTML, the JSON-formatted data) but rather as the Interface to a Router. It consists of the Interaction (Request) and the View (Response).

Let me just add another acronym to the soup: Command Query Responsibility Segregation(CQRS). http://martinfowler.com/bliki/CQRS.html

At its heart is the notion that you can use a different model to update information than the model you use to read information.

I think it’s sort of what is being talked about in that GET requests can have a completely different flow path than your POST.PUT.DELETE requests. Even to the point of operating from completely different databases.

The other thing I would suggest is to invest some time on getting comfortable with components. Take a framework like silex out for a drive: http://www.sitepoint.com/introduction-silex-symfony-micro-framework/

But focus on seeing how to, for example, install and configure the independent router component. So now if you want to experiment with completely different routing bases on GET/POST verbs, you can do so without getting hung up on the details.

This is also worth a read: http://symfony.com/blog/create-your-own-framework-on-top-of-the-symfony-components And if you really just don’t like Symfony then there are a number of other libraries out there as well.

It’s the practical use of components (thanks largely due to composer) over the last 5 years or so that has really revolutionized php application development.

You say the “interaction” is the request. I see the request just a bit differently. The request is simply a call for data, a “resource”. The actual interaction with the user alway happens on the client’s device (browser or app). So, a request might be a request for data in JSON. Or it might be a request for data, which is in the form of completed HTML. Or, it could be in the form of a file. It is always just data.

@ahundiak - interesting you mentioned Silex. I was just watching an introductory video about it this morning. I also read that “create your own framework” article too and I like the direction Symfony is going with it being more modular. The number of components/ libraries in the PHP world is amazing.

Scott

So let me get this straight. You have never even used Symfony so were dismissing it solely on academic reasoning. I would advise you to at least get familiar with things before dismissing them so quickly. Especially something which a fair majority of the php ecosystem embraces like Symfony which is used in countless projects big and small.

Now now. Play nice. There is still a possibility that someone might be able to convince him that not all controllers are thousand line monsters. No need to scare him off.

This is an interesting thing you are saying this - I think we should agree it’s obvious that we are not talking about issuing database queries from HTML but about querying the model for data. Of course, the model may issue database queries under the hood but we are not dealing with that in a template, because these things are abstracted, e.g. behind an interface of a model object.

Now if you think about what Symfony does - it is the same thing plus more - it does not query the model directly but it does query the controller, which in turns queries the model, so in essence you could as well say that in Symfony you are doing “database queries from HTML” but you are doing it via a controller so in effect you are basically instantiating the whole application stack from the template to load a module.

Let me clarify that I’m not arguing this is bad approach, it has been tested in the wild and works. But I’ve also tried the alternative way of having the view request data from the model and it also worked fine. I don’t know how many people do it this way but I think TomB does that in some of his projects - but then he advises adding view helpers to help make the templates more reusable.

Where did you get that from? :flushed: I’ve never used Silex. I’ve learned Symfony and have used it, but only have done one major project with it (to be honest). I’ve studied it the past year or so. I’ve also helped a very good programmer write two books on two components of Symfony, Security and Console. So, I know Symfony fairly well. Silex isn’t Symfony. It uses its components yes, and I knew about Silex and the fact it was a “slimmed down Symfony”. I just never looked into it. And the video was just something I ran into and decided to watch and mention here, because of the coincidence of ahundiak suggesting we look into it. I think I know why ahundiak mentioned it too. The dev who introduced Silex in the video said Silex is like a over glorified router. And routing is a concern of mine.

Actually, I also know about the “thin controller, thick model” correct way of thinking and programming using Symfony too. And that isn’t my concern really. My concern is that I need to build a controller for every single action, even for sub-requests. I simply believe a GET (and sub-templates) has (should have) enough information for the view to do its job and build a response. All the decisions that need to be made should have been made up front. Like, how the application works. Who is allowed to see what. Or how the request should be “built” and routed, when it hits the server and what should happen because that request was made. Why should I build a controller, when everything the application should know about and need for a response should be already available? I think all I’d be doing is fulfilling someone else’s convention, nothing else. Let me put it another way. If you are adding any logic in the controller for a read request, your probably doing something wrong and even possibly not following DRY.

Yes, @TomB and I were discussing his new concept in Transphporm and I also came to the conclusion that for the view to be effective, it would also need some form of “helpers”. I called them viewmodels. You all might now be saying, so what is the difference between a helper or viewmodel and a controller? The simple answer is SRP. A controller shouldn’t know what the view needs, above and beyond the model it passes, for the view to build a response. If you are adding any logic for the view in the controller, you are breaking SRP. I’d even go so far as to say, if the controller is even determining the type of output the application should return, the controller is breaking SRP. And with Symfony, this is done.

Helpers or viewmodels (and not only the templates) can also be reusable. Something, which is very difficult for a controller to be (if even possible). And, something I never mentioned, but just realized, I also believe the premise that the view should always be responsible for the response, and never the controller. Once the controller is determining the response, it breaks SRP in my mind. It no longer only coordinates the model and the view.

Scott

Let’s take a use case for a GET scenario, which I just read from the Symfony docs, where the controller has logic in it, which I don’t think it should. Remember, in my mind, the view is always responsible for the response.

Controller B reads the slug parameter from the request to load a blog entry from the database and creates a Response object displaying that blog. If the slug can’t be found in the database, it creates and returns a Response object with a 404 status code.

So, here is what I read as the responsibilities of the controller. The controller must read a slug AND get the proper blog from the model AND if the blog is there, then return it to the view for the response AND if the blog is not there, about-face and make the command to respond with a 404 response.

God like. And not DRY, because the same logic has to be added to every controller for all the 404 “about-faces”.

How about this scenario?

The view asks the model for that same blog requested. The model gives back a 404 object, saying “You’re outta luck buddy. I don’t have any such blog here”. The view says,“Thanks model! I’ll just render the 404, cause I know what to do with that object too.” If the model returns the blog properly, the view responds accordingly.

Doesn’t that sound simpler and like a clearer set of responsibilities between the actors?

Scott

Let me ask this question too. Doesn’t the role(s) the controller plays make it way too easy for the dev to get carried away and make “thick” controllers? It actually encourages her to do so. To me, that is a problem with the architecture, and not the developer or something the developer should be really concerned about.

Scott

I’d also like to return to this point. In Twig, the request on the view from the controller is for a certain template with a certain set of data from the model. Like the blog in the scenario above. Correct? Then Twig starts compiling the whole page. The template “knows” that it must render any parent and included templates and if there are calls needed for data with another reusable template (through a sub-request), then Twig also gathers this “compiled template with data” and fills in all the rest of the page. So, the view is building the whole page. It has to. It is stitching the parts together, so the controller can return a response.

If the view is stichting the page together, does it really, honestly, need a controller?

Scott

How does the view know which blog entry to request? Does it have access to the request object?

If we go as far as getting the view to return the full http response then I think it’s more logical if the view itself decides on http status codes and the model should not deal with that - it should only respond that the requested object does not exist and it should be up to the view to decide what to do with it - issue a 404 status code or maybe display a different page.

Anyway, I think the major problem with this type of discussions is that the idea of the view fetching data from the model is not industry standard and few people use it and I don’t think we have any major frameworks designed that way, therefore few people are able to compare these different paradigms objectively simply because some experience is needed in both. I know TomB presented a bare-bones structure of such a framework and I’ve played with it a little but we would need some experience with using it in large projects to be able to build a real opinion based on practice.

If it is to respond to requests, yes, it must.

Yeah, the “it’s not here” being a “404” from the model is just a name. It could also be called the “SOL” object. :smile: I wouldn’t also go so far as to say the view should actually return the HTML response, but be responsible to judge what the response needs to be.

Well that sounds a whole lot better than, “You’re friggin crazy Scott and what your saying is totally ludicrous.” So, thanks for that! :+1: And you are right. Whether or not this concept has merit needs a practical and usable framework and a good bit of testing.

Scott