SitePoint Sponsor

User Tag List

Page 1 of 3 123 LastLast
Results 1 to 25 of 56

Thread: MVC confusion

  1. #1
    SitePoint Enthusiast
    Join Date
    Jan 2005
    Location
    Amersfoort, the Netherlands
    Posts
    50
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Real-world MVC website co-op project!

    After having read every single post in this thread this afternoon, it became clear to me that there's quite a few people out there in dire need for well-structured, pattern-based code for developing a real-world website. Apparantly, an abundance of code snippets from various projects by different members doesn't seem to help much in coming to a concrete solution.

    Now, since the world's best PHP coders reside here anyway, I think it would be cool (if not awesome) to combine our knowledge and experience to create something that will change the way people code their websites. Thus, the project should have some common website features and functionalities. Here's a blueprint of what I have in mind:



    Now, the topic I linked to above resulted in the desire for "components", or "sub-MVC's". I believe this is the way to go. Delegate the rendering of each element (i.e. header, clickpath, navigation) to its designated component, and have each component's View output, based on a sub-template, returned to some sort of "master View", which ultimately parses a master template and outputs the result. Thus, the first actions that should occur is registering each components with some master entity, by providing an object and the template placeholder for this element. I.e.:

    PHP Code:
    $Genesis = &new Genesis// the object that starts it all ;)
    $Genesis->registerComponent("HeaderController""header");
    ... 
    Where the output of the HeaderController would replace the {header} placeholder in the master template. That's as far as my logic goes, really. I (and probably many others) hope we can pick this up and create a solid foundation for building any real-world website.

    On the site itself...

    Let's say we're creating a CMS (to get some form handling going on) and the navigation contains links such as "Pages", "Users", "Images", and so on. The URLs would be like: /index.php?view=users&action=list

    Now... what would be the first step?
    Last edited by oscar alexander; May 22, 2005 at 09:25.

  2. #2
    SitePoint Zealot
    Join Date
    Jul 2003
    Location
    Los Angeles
    Posts
    199
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by oscar alexander
    I thought I had it all figured out, but the more I read about MVC, the more confused I get. Is there any tutorial that explains how mappings and intercepting filters work, or some example (psuedo) code I could learn from?
    It's easier explaining this in Java with a small example in Spring.

    Let's say you want all urls in the form of www.example.com/reports/*.html to be dispatched to one controller. So reports/summary.html and reports/details.html both are redirected to one controller class.

    Here is the flow for a request to www.example.com/reports/summary.html

    Request->Controller-->Model-->View

    The classes:

    ReportController.java
    =================
    Code:
    public class ReportController extends MultiActionController {
    
        public ModelAndView summary(HttpServletRequest request, HttpServletResponse response)
    		throws ServletException {
    		
            Map model = new HashMap();
            model.put("testString", "This is a test");
    	
            return new ModelAndView("summaryView", model);
        }
    }
    All this simple example is doing is putting a string into the model and that model is returned to the view. The view is html with some form of expression tags which may be JSTL, velocity, freemarker, etc that is used to print out any model data we passed from the controller. A small example using freemarker:

    summaryView.ftl (freemarker view)
    =============
    Test: ${testString}

    That's as simple as it gets, the main complexity lies in the model. In a typical database-driven website the model is a collection of rows from the result of an sql query. In the PHP world this is usually an array but in the Java world it's a collection of either (1) JavaBeans (2)HashMaps. I'll show you this in the next example but first let's address an issue.

    The first mistake people make is putting the business logic in the controller causing a tight coupling between the two. Instead put the business logic in a separate class which in the Java world is usually a facade to the underlying DAOs. For this example to keep it simple I'll leave out the DAOs. Ok, so let's look at the controller again only this time we get our model data from a database. This time the url is specified as: www.example.com/reports/details.html?groupId=10

    ReportManagerIF.java
    ==================
    Code:
    public interface ReportManagerIF {
        public List findAllUsersInGroup(long groupId);
    }
    ReportController.java
    =================
    Code:
    public class ReportController extends MultiActionController {
    
        private ReportManagerIF reportManager; 
    
        public void setReportManager(ReportManagerIF reportManager) {
            this.reportManager = reportManager;
        }
    
        public ModelAndView summary(HttpServletRequest request, HttpServletResponse response)
    		throws ServletException {
    		
            Map model = new HashMap();
            model.put("testString", "This is a test");
    	
            return new ModelAndView("summaryView", model);
        }
    
        public ModelAndView details(HttpServletRequest request, HttpServletResponse response)
    		throws ServletException {
    		
            Map model = new HashMap();
            long groupId = RequestUtils.getLongParameter(request, "groupId");
            model.put("userList", this.reportManager.findAllUsersInGroup(groupId);
    	
            return new ModelAndView("detailsView", model);
        }
    }
    detailsView.ftl (freemarker again
    ===========
    <#list userList as user>
    Username: ${user.userName}
    Email: ${user.email}
    </#list>

    Notice now we are declaring an instance variable reportManager which implements the ReportMangerIF interface. So where does the actual implementation of ReportManager come from? The Spring container injects a single instance of ReportManager(not to be confused with a Singleton) into to the ReportController via the setter we defined and is one of the beauties of Depenency Injection. This dependency is specified in an XML file but I'll leave out the details of that

    The neat thing about using a collection of JavaBeans or HashMaps is that we can use the dot notation in our view to access the members, i.e the call to user.userName in the view really means user.getUserName();

  3. #3
    SitePoint Zealot
    Join Date
    Jul 2003
    Location
    Los Angeles
    Posts
    199
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Wow you sure changed your original post quite a bit You originally asked for an explanation MVC so that's what I replied to. After I replied I see your entire post changed drastically so just in case anyone is confused as to why I repsoned as I did it's because of that

  4. #4
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    and have each component's View output, based on a sub-template, returned to some sort of "master View", which ultimately parses a master template and outputs the result.
    Why a master template or view though? In recent months, I've taken a different view to how to build a web page dynamically. You have a number of child template fragments yes? These child template fragments have a parent fragment, in that regards that given parent fragment too can have it's own parent, etc etc.

    You see, each template fragment or view is treated just like any other template fragment or view, all are one, and one are all the same if you understand...

    You have no master template or view in that case, do you?

    PHP Code:
    $Genesis->registerComponent("HeaderController""header"); 
    That is cool if you have a parent template, and the template has a linear number of child template fragments but it becomes more complex if a child template fragment has it's own fragments as well. I have labeled the above approach the 'Smarty way', and it has some obvious limitations.

    Have you noticed them yet? I did a while back and have since spent a great amount of time in scripting a viable solution. I've taken it further in other regards, than what I had originally designed for.

    If your interested, you are looking for two design patterns, the Composite and the Visitor. If your interested in integrating a selective partition of the actual web page to be displayed at run time, then you'd need to look at the Observer, which is used in conjunction with the Visitor

    This part is actually, really cool in what you can do with it. Hope this gives you some ideas anyways, but I don't think

    PHP Code:
    $Genesis->registerComponent("HeaderController""header"); 
    Is in todays world is a solution that deserves any more thought put into it, the world has moved on from those days
    Last edited by Dr Livingston; May 22, 2005 at 10:04. Reason: clarification I suppose

  5. #5
    SitePoint Enthusiast
    Join Date
    Jan 2005
    Location
    Amersfoort, the Netherlands
    Posts
    50
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kuato
    Wow you sure changed your original post quite a bit You originally asked for an explanation MVC so that's what I replied to. After I replied I see your entire post changed drastically so just in case anyone is confused as to why I repsoned as I did it's because of that
    Ah, sorry about that! I thought the topic still hadn't been replied to when changed it into something entirely different. I have saved your first reply locally, so perhaps it's better to remove the reponse for the sake of clarity?

    Quote Originally Posted by Dr Livingston
    That is cool if you have a parent template, and the template has a linear number of child template fragments but it becomes more complex if a child template fragment has it's own fragments as well.
    Wouldn't recursion be the solution to that? I can imagine the "page content" component might sport a "subnavigation" component, so you definitely have a point here. As long a each Component subclass has an array of child Components, it shouldn't be too hard to gather the composite, right?

  6. #6
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Exactly, the Composite pattern resolves any recursion issues that you'll have, so your spot on there

  7. #7
    SitePoint Enthusiast
    Join Date
    Jan 2005
    Location
    Amersfoort, the Netherlands
    Posts
    50
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Okay So let's assume the basic set of Components (as displayed in my blueprint) are required at all times. Then each Component in turn should check (according to request variables and possibly mappings) if it requires other Components. I.e. the "page content" Controller could require the "subnavigation" Component if the current page has subpages.

    What's also unclear to me is how each of these components communicates with the "genesis" Component, in order to inform the "page title" Component of the current page's title, and so on... Would that be where the Observer comes in?

  8. #8
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Would that be where the Observer comes in?
    No, no, no...

    Remeber the part where I said each template fragment or view are all treated in the same way yes? Well, it's this premise that allows one fragment or view to know of other, child fragments or views, likewise it's this approach that you can easily locate a child fragments or views parent.

    That is the Composite pattern for you. If you can manage to understand this pattern, most of the battle has been won. I've never liked recursion, never have, and never will as it just kills my brain. But not anymore, as I've now got a firm grounding in the Composite pattern, which I can now related this to recursion so no more burnt out brain cells

    Then each Component in turn should check (according to request variables and possibly mappings) if it requires other Components.
    I posted script in that past, the *Adapter class(es) which will take care of this part for you, if you care to look back over my postings? (But in my case, the Request has nothing to do with it, can't understand why you've assumed this?) I spent 3 days working on this part in it's self, testing and testing, and more testing just to be sure it actually worked as it should.

    It does

  9. #9
    SitePoint Zealot johno's Avatar
    Join Date
    Sep 2003
    Location
    Bratislava, Slovakia
    Posts
    184
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by oscar alexander
    What's also unclear to me is how each of these components communicates with the "genesis" Component, in order to inform the "page title" Component of the current page's title, and so on... Would that be where the Observer comes in?
    That's exactly the problem I am dealing with now. I would appreciate any help (example) solving this in an elegant way.
    Annotations support for PHP5
    TC/OPT™ Group Leader

  10. #10
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    In recent months, I've taken a different view to how to build a web page dynamically. You have a number of child template fragments yes? These child template fragments have a parent fragment, in that regards that given parent fragment too can have it's own parent, etc etc.

    You see, each template fragment or view is treated just like any other template fragment or view, all are one, and one are all the same if you understand...
    How do you have your Views know what to display? Each should have at least a separate Model (with possibly some reuse) if going for active View approach, and also a Controller if going for passive Views.

    This means that there is a whole MVC triad for each subview, which might become quite a large tree on complex pages... Just a thought.

  11. #11
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Okay, for the document TITLE you have two options,

    1) Treat it as a template fragment in it's self, or
    2) Pass the title variable to the Visitor, which is therefore visited by each template fragment/view and inserted if the title tag is present.

    I choose the second version if you want to know.

    and also a Controller if going for passive Views.

    This means that there is a whole MVC triad for each subview, which might become quite a large tree on complex pages... Just a thought.
    That is true, you need to implement MVC for each template fragment/view, but in all honesty, most of the MVCs are reusable, and you really (for me anyways) only have the one MVC per page request anyways, such as listing all products, adding a new product, etc.

    When I say most of those MVCs are reusable, I mean that the bulk of the template fragments/views are really modules, such as displaying hierarchacal folder structure, navigation breadcrumbs, search box, etc.

    There is a lot of reuse in that regards, for example you can use the same module easily more than once in the same page, and they all act independently of each other. For example, imagine displaying 3 separate monthly calendars, previous, current, and future? So simple...

    One (seriously helpful) advantage of using Composite is cacheing. Think I've mentioned this before, as you can cache the whole page, or just portions of it, but it doesn't make much difference to the actual process it's self, and that is to generate the page.

  12. #12
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by oscar alexander
    What if you want a standalone login page?
    Hello World

  13. #13
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    Why a master template or view though? In recent months, I've taken a different view to how to build a web page dynamically. You have a number of child template fragments yes? These child template fragments have a parent fragment, in that regards that given parent fragment too can have it's own parent, etc etc.

    You see, each template fragment or view is treated just like any other template fragment or view, all are one, and one are all the same if you understand...

    You have no master template or view in that case, do you?
    I've been doing a lot of thinking about this issue, and the way I see it is that you have no choice but to have two types of views; normal Views, that displays data from a model, and Composite Views, which are made up of regular Views and/or other Composites. Is my thinking correct?

    I have a pretty vague idea about how to implement this at the moment, possibly due to my imperfect understanding of the Composite, Visitor, and Observer patterns you mention. Anybody care to explain these or point me somwhere with more info? I have the GoF book but I find it a bit dry at times...

  14. #14
    SitePoint Enthusiast
    Join Date
    Jan 2005
    Location
    Amersfoort, the Netherlands
    Posts
    50
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    I posted script in that past, the *Adapter class(es) which will take care of this part for you, if you care to look back over my postings? (But in my case, the Request has nothing to do with it, can't understand why you've assumed this?) I spent 3 days working on this part in it's self, testing and testing, and more testing just to be sure it actually worked as it should.

    It does
    Thanks, I'll try and dig it up tomorrow! It's bedtime for now, busy week next week. Also, I've heard about SO many patterns these past couple of days in regard to solving similar problems, that I kind of lost track of which pattern does what. I'm sure most of us have, at some point Composite (View) and Visitor are two I've heard you mention a couple of times, are there any resources you recommend? Mind you, I'm pretty bad at figuring out implementations myself, so any resource with some sample (pseudo) code would be highly appreciated

    Thanks again for responding so often! I'm sure it will all be clear to us one day

    One more thing, for this concept, would it make sense to determine a single Model based on request parameter (i.e. ?view=users) and have each component access that?

  15. #15
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    the way I see it is that you have no choice but to have two types of views;
    I generate the Composite structure on the fly, and it's this Composite structure that determines which View(s) are used via a Controller (and it's Model) that are given for each Composite.

    To some extent, the Request has something to do with the desicion making, but not directly, the disicion making is from within the Controller, ie The Controller (CoR) executes a given action based on a Request, if that helps?

    In my case, it's a template fragment that is returned from a Handler, to the Composite, then the Visitor visits the Composite and does what it is required of the template fragment, such as appending it to the parent Composite's template fragment, caches the template fragment if needs be, etc.

    To answer another question, the Request is accessable via all Controllers, and their Handlers, but each Controller can have their own Model(s)... All are independable, and are unaware of each other.

    I intend to fix this, as there are advantages (and disadvantages) of one Composite being aware of other Composites, regardless of they're position in the heirarchacal structure

  16. #16
    SitePoint Zealot
    Join Date
    Oct 2004
    Location
    naperville
    Posts
    189
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I really feel like all this discussion of patterns (yes, MVC) included as a precursor to building a website is all wrong. (Not directed at the doc, whose explaining them, but sort of at the topic post. Wouldn't you just TDD and switch to MVC with alreadye stablished code when it becomes convienient?

    Maybe I'm missing something. I know layer seperation should be taken in consideration (to an extent) from the start, but I was under the impression that MVC was a specific pattern that enforces layers?

    Perhaps an issue is that everyone tries to "get" MVC or use it without having an application to work with. That's a lot of framework when you have no dry wall.

    Anywyas, in my experience patterns almost always work better when tuned to a specific application. In this aspect, how much would a super generic MVC framework actually help? In fact, I find it very restricting when I start a site thinking MVC, MVC, MVC. It hurts my productivity - I find myself thinking more about what goes where rather than actually getting any application code.

    Then again, I haven't tried MVC-first since I started TDDing.

    Just my thoughts - I would love any responses.

  17. #17
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Off Topic:

    Phil, I think people are waiting for a killer PHP MVC framework, but IMO the PHP community is too fragmented for that to happen. So, people will find MVC and build it themselves again and again, like they build template engines again and again. It's the PHP way

    Douglas
    Hello World

  18. #18
    SitePoint Enthusiast
    Join Date
    Jan 2005
    Location
    Amersfoort, the Netherlands
    Posts
    50
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Super Phil
    <snip> Wouldn't you just TDD and switch to MVC with alreadye stablished code when it becomes convienient? <snip>
    I think separation is a good thing in any application. I'm also a huge proponent of XHTML, so I don't see why MVC should be avoided in any case

  19. #19
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I am also of the opinion that MVC is overrated in Web development in general and PHP in praticular. Firstly, MVC was not originally intended for the inherently stateless Web UI, but for stateful desktop GUIs where you have the Controller update Model and View as soon as its state is changed (e.g. when you push a button). In Web approach, each action calls for a complete request-response procedure before the View can be displayed.

    Secondly, PHP is not Java -- it was originally nothing more than a templating engine, and it still works perfectly as such. When creating MVC framework, I find the biggest problem being the View part -- what template to use, how to make it universal etc. But with PHP, something the following approach is starting to seem more and more natural:

    PHP Code:
    <?php

    include('Controller.php');
    include(
    'WhateverModelINeed.php');

    $controller = new Controller();
    $model = new WhateverModelINeed();

    ?>

    <html>
    <head>
    <title><?= $model->getApplicationTitle() ?></title>
    </head>
    <body>
    <h1><?= $model->getPageTitle() ?></h1>
    <?= $model->getPageBody() ?>
    </body>
    </html>

  20. #20
    SitePoint Enthusiast
    Join Date
    Jan 2005
    Location
    Amersfoort, the Netherlands
    Posts
    50
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by BerislavLopac
    PHP Code:
    <?php

    include('Controller.php');
    include(
    'WhateverModelINeed.php');

    $controller = new Controller();
    $model = new WhateverModelINeed();

    ?>

    <html>
    <head>
    <title><?= $model->getApplicationTitle() ?></title>
    </head>
    <body>
    <h1><?= $model->getPageTitle() ?></h1>
    <?= $model->getPageBody() ?>
    </body>
    </html>
    What would the purpose of you controller be in this scenario, as there is no connection to the Model?

  21. #21
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by oscar alexander
    What would the purpose of you controller be in this scenario, as there is no connection to the Model?
    This exactly occured to me just after I posted, but I didn't get around to editing it. There is even an inherent PageController pattern in PHP, like this:

    PHP Code:
    <?php
    require_once('Model.php');
    $model = new Model();
    require(
    'thisPageTemplate.php');
    ?>
    Where this file is the controller itself.

    Or even easier for the HTML designer:

    PHP Code:
    <?php
    require_once('Model.php');
    $model = new Model();
    extract($model->getArray());
    require(
    'thisPageTemplate.php');
    ?>
    Then individual templates can easily have stuff like:

    PHP Code:
    <div id="navigation">
         <?php include('navigation.php'); ?>
    </div>

  22. #22
    SitePoint Enthusiast
    Join Date
    Jan 2005
    Location
    Amersfoort, the Netherlands
    Posts
    50
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ehm... it actually so simple it's nice I'm curious what would handle form submissions though, any thoughts on that?

  23. #23
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If your form returns some output (e.g. a thankyou page), there is absolutely no difference. Otherwise, just end your form page controller with include('pageToDisplay.php').

    Essentially, this is your plain vanilla PageController pattern. In PHP it is much more appropriate than FrontController, as the source is executed as it is loaded.

    I especially like it when used with Apache's Multiview prameter, which allows you to do things like www.example.com/aboutus to call www.example.com/aboutus.php without having trouble with mod_rewrite.

  24. #24
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In Web approach, each action calls for a complete request-response procedure before the View can be displayed.
    True, true though that is all going to change in the not so distant future. I agree 100 percent though that PHP does not have something like Ruby on Rails and so everyone justs plumps for writing their own version.

    This in it's self isn't a bad thing, as the topic is then open for discussion nearly all the time, and everyone has their own ideas, etc to contribute, so who knows, maybe eventually, PHP will have something solid based on MVC?

    But the confusion I think which I've noticed before, is that MVC is about separating layering, and nothing more. The feeling I get is that a lot of people new to MVC take the idea that MVC is a complete solution, in regards to how an interactive web page is put together from start to finish.

    It isn't

  25. #25
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    True, true though that is all going to change in the not so distant future.
    No, it's not.

    Unless you already have data on the client (which had to be donwloaded in the first place), you still need to send a request and wait for a response to obtain it from the server. What is changing is that we more often see an approach that it doesn't require a complete reload of a page but just a tiny xmlhttprequest object.

    The stateless nature of the HTTP protocol isn't bound to change anytime soon.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •