SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 50
  1. #1
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    MVC - How to handle big pages with many different parts?

    This is a sidetrack that sprung from the discussion in this thread http://www.sitepoint.com/forums/showthread.php?t=231314.

    How do different frameworks/aproaches handle bigger sites? If we take this picture as our base idea on how the application flows.

    How do you handle big sites with many dynamic elements on them, for example the mainpage on sitepoint.com that lists the latest news, latest blogs, latest articles, etc. How is this page filled up from an MVC point of view? Should one create a big action/command that's name like "Main" and associate a view with it that takes care of the whole page in an instance?

    Or can you go with the more modulelar plug-in/out aproach where you have several actions(LatestNews,LatestBlog and LatestArticles for example) and then associated a view with those parts and then pull it all together thru some Stack/Chain of Responsibility?

    I've seen several sandbox example on how to display a name or a single page - but where do you go from that, when you need to display huge sites with many different dynamic parts that arent aware of eachother - not on any level? How does the big frameworks like WACT, Pharme, Mojavi (and Struts ofcourse, but this is php) solve it?

  2. #2
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    On the point of WACT, this uses the Composite pattern with Visitor. Exactly how the two work in tandem I'm not sure yet as I spent a good few hours looking at the templating and got lost in a few places a few weeks ago

    Still to find the time to get back to it. On another point, I think it makes sense (at some level) for one dynamic part to know of another dynamic part, as one part I suppose could depend on another?

    Trying to imagine completeing a form where you select an option (checkbox) which then offers more options/questions to complete yes? Not sure if that's a good example though.

    As to how to construct the Composite I think McGruff hit the nail on the head in the earlier thread by mentioning the Observer pattern. I think this'd be a cleaner method of implementation rather than a CoR.

    To use a CoR would mean to have all the handlers for the dynamic parts even though you know nowt of which dynamic parts are required, from the point of view of the CoR, if I explained clearly enough?

    Waiting for some more input myself now

  3. #3
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If was thinking about something like a Parent>Child relationship. But where the child is totaly unaware of it being called from another Action instead of from the application-controller itself. This would be done thru some kind of mapping, for example:

    Action: Main
    ^
    |-- > Action: LatestNews
    |-- > Action: LatestArticles
    |-- > Action: LatestBlogs


    Now thru mapping you could allow Main to call LatestNews, LatestArticles, LatestBlogs and retriver thier result(instead of passing it on the view - which we would've done if the action to be request would've been any of those instead of Main). The three child-actions called from Main are totaly unaware of the fact that they are called by another action instead of the ApplicationController itself.
    This is just an idea I've been throwing around for a couple of hours right now, good one? don't know.

    I need to do some reading on the Composite and Visitor Patterns, anyone got some good links/recomendations?

  4. #4
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I agree, but I don't think calling them Actions. Though it is an overused and misused term they are really Components, meaning that the have a defined interface and do a defined task. Perhaps:

    Action: Main (PageController)
    ^
    |-> Model -> Component: LatestNews -> View
    |-> Model -> Component: LatestArticles -> View
    |-> Model -> Component: LatestBlogs -> View
    Christopher

  5. #5
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    arborint: Well, yeah - that's probably a route to take name-wise. Other then that I realy do like the idea of child-elements, you could even create a heriarchy (spelling? =p) of with child components calling other childs to themselves(this might be a bit overkill tho).

    Anyone with a good deal of experience in some of the more widely used MVC Frameworks care to comment on this?

  6. #6
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Looking at your example of what you want to do, WACT has something simular now so that'd be the first place to have a dig around?

    As for the Composite and Visitor patterns, I'll attach a PDF which I have, sadly it's the only one I have at the moment

    I had others but the CDs have grown a pair of feet and walked (some bas... has lifted them in other words)

    Btw, this thread has some script I was working on, and has the said PDF attached

    http://www.sitepoint.com/forums/showthread.php?t=221179

    Hope this helps you.

  7. #7
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks Livingston, I'll check out the PDF right away. I'll have to look into WACT, are there any live examples/test so I dont have to teach myself the whole framework first?

  8. #8
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Examples on the WACT site are a bit thin just now, and non too adventurous either in my view, but some folks are using WACT so maybe they'll notice this thread and help out with more indepth examples huh?

    EDIT:

    LIMB (do a search in these forums as I don't have the link sorry) uses WACTs templateing as well if I remember, I think they have some examples as well which may help you

  9. #9
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    One question I have is what is specific and what is generic. For example to list news records I might do something like this:

    Action: news/list (file action/news/list.php)
    ^
    |-> Model (file model/news.php)
    -> Component: Lister (file component/lister.php)
    -> News List View (file view/news/list.php)
    Christopher

  10. #10
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by arborint
    One question I have is what is specific and what is generic. For example to list news records I might do something like this:

    Action: news/list (file action/news/list.php)
    ^
    |-> Model (file model/news.php)
    -> Component: Lister (file component/lister.php)
    -> News List View (file view/news/list.php)
    There are two possible aproaches as I see it:


    • Let every action/component be able to call all other actions from itself
    • Specify in the mapping what type an action/component is and if it an be called or not

  11. #11
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You could probably do both. Everything equal on a lower level, but you could add a mapping layer that could put a structure you wanted on things. They might just be different types of controllers so it could change on an action by action basis as needed.
    Christopher

  12. #12
    SitePoint Enthusiast
    Join Date
    Sep 2004
    Location
    S. Florida, USA
    Posts
    60
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Been thinking about this all evening.
    My chain of thought was heading down the path of using an
    Observer pattern.
    Then I thought about KISS, and the few couple times, that
    I read that not everything needs to be a pattern,
    as the Observer route, doesn't seem to match the job description,
    of getting together blocks for a page.

    So I decided to put together a little UML (Im new to UML, so
    the class connections may be wrong).
    Using thr's description of a page with blocks, where blocks
    can be items like latest news, latest blogs, latest articles.

    Note: The naming strategy maybe off

    Edit Changed the UML (Noticed something), and description
    In the UML included, imagine these blocks as child views,
    renderLatestNews/renderLatestBlogs/renderLatestArticles.
    Which has access to zero or more model classes.
    These views are compiled into an object in the pageController,
    and passes this object to the pageView, which renders the appropriate child views where it needs to be in the page.

    Thats the idea. What do you think???
    Attached Images Attached Images
    Last edited by trini0; Feb 8, 2005 at 09:13. Reason: Updated Description/UML

  13. #13
    SitePoint Enthusiast
    Join Date
    Sep 2004
    Location
    S. Florida, USA
    Posts
    60
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here is some more info about the Composite Pattern that Dr. Livingston
    was talking about ->
    http://java.sun.com/blueprints/patte...ositeView.html
    I currently researching it...

  14. #14
    SitePoint Enthusiast
    Join Date
    Jan 2005
    Location
    Sydney
    Posts
    43
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I thought I might just post here for now unless my post deserves a new thread.

    But I am currently working on a cocoon-clone because I find Cocoons technique to handle pages is very similar to MVC, but it can be done in a nicer way. It also enables me to code my logic in XML too.

    I was wondering if anyone else is using this method?

    Also there is Popoon (popoon.org) available which is more of a true cocoon clone compared to mine I think, but the way I have done it is about the same, it might or might not be better.

  15. #15
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by trini0
    Here is some more info about the Composite Pattern that Dr. Livingston
    was talking about ->
    http://java.sun.com/blueprints/patte...ositeView.html
    I currently researching it...
    While the page you linked to was great, how do you actually implement this in an mvc ? And are the different parts of the composite view (the small "inner" templates) using push or pull for data retrieval? If they are using pull, how is thier resource handled? And if the data is pushed - how is the modell for it handled?

    My first thought was something like this:

    After all the actions are done and all the model-logic executed, you get the result in some type of container object and this container objects tells the Application controller if it should load a Composite View or a normal single View. Or should all the views returned be treated as composite ones?

  16. #16
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think the view should be treated as a Composite by default. As how to implement within the MVC mould I'd think the Controller could (sketchy?) build the Composite it's self, based on what the Model(s) do?

    But to my thinking of the road I'd take is that the Composite wouldn't actually hold anything about the view bar the templates, which leaving a template controller to build the view?

    Thus, the Composite is built up of Model objects which would eventually return a template fragment for the template controller to assign to tags - which match a specific node of the Composite if I make some sense?

    EDIT:

    1) Could the template controller be a View Helper I ask?
    2) Or could it be done with a 2 Step...

    One problem I have is how to tell the Composite what to build, ie Which Model(s) to use... I don't really want to use a configuration file of any sort for this as it's then a maintenance issue (for me anyways).

  17. #17
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    One problem I have is how to tell the Composite what to build, ie Which Model(s) to use...
    I agree with this, while configuration is one way to go I'm not convinced.

    This is what I got in mind now(url for this example is index.php?Action=Main, that displays the a frontpage like sitepoint.com):

    "Main" action has several sub-actions associated with it, all these actions are put in the action chain(including "Main") and then perform():ed. All of the actions returns an ActionResult, all of which are put in an ActionResultSet(could be ActionResultStack, ActionResultList, etc... naming not final) and returned from the ApplicationController to the flow-controller.

    At this stage the FrontController looks at the mapping for the "Main" action, and this says that the "MainCompositeView" should be used for assembling the view.

    The MainCompositeView and the ActionResultSet are passed into something called like a "ViewHandler" or whatever that takes the data form the MainCompositeView(ie: what indepenent views are needed, etc.) and the ActionResultSet and assembles it to one view that is printed to the user.

    Does this seem like a decent enough aproach?

  18. #18
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I posted a reply in the other thread that kind of is within this threads scope to, so here's a link: http://www.sitepoint.com/forums/show...2&postcount=65

  19. #19
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    "Main" action has several sub-actions associated with it, all these actions are put in the action chain(including "Main") and then perform():ed.
    I like this idea, so I could I suppose use a generalisation of the script I posted yersterday (CoR) along side the Composite Builder to designate which Model(s) to use aye?

    The (CoR) handlers are all reuseable anyways, ie they can be strung in any order... no?? I could live with using a class base for configuration rather than having to read in some sort of XML file, XML files aren't reuseable

    Need to think more on this now.

  20. #20
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Umm...

    Been searching for a more appropriate thread this last 20 minutes or so and not found the one I was looking for

    A few members may remember I was talking about the Composite Pattern in relation to building a web page, well been working on the script this week and here is what I currently have.

    At the moment the script is working and the concept can be reused easily in your own scripts, such as the recursion over the composite structure for example.

    There is more to come so keep an eye on this thread (which I've bookmarked now). The script is currently more of a proof of concept than anything else, but who knows where I can take it?

    PHP Code:
    <?php

        error_reporting
    E_ALL E_STRICT );
        
        
    /**
         * @author les quinn
         * @copyright copyright les quinn (c)2005 all rights reserved not for public domain
         * @contact les quinn <nukebaghdad@yahoo.co.uk>
         */
         
        
    interface IWalker {
            public function 
    __construct$children );
            public function 
    walkIAdapter $adapter );
        }

        interface 
    IAdapter {
            public function 
    __construct$fragment );
            public function 
    getRoot();
            public function 
    push$fragment );
        }
        
        class 
    FileIOException extends Exception {
            public function 
    __construct$message ) {
                
    parent::__construct$message );
            }
        }
        
        class 
    IllegalParameterException extends Exception {
            public function 
    __construct$message ) {
                
    parent::__construct$message );
            }
        }
        
        class 
    AdjacencyListWalker implements IWalker {
        }
        
        class 
    XmlWalker implements IWalker {
            private 
    $children;
            
            public function 
    __construct$children ) {
                if( !
    $children instance of DomNodeList ) {
                    throw new 
    IllegalParameterException'thrown exception on, expected parameter(s) not found.' );
                    break;
                }
                
    $this -> children $children;
            }
            
            public function 
    walkIAdapter $adapter ) {
                foreach( 
    $this -> children as $child ) {
                    if( 
    $child instanceof DomElement ) {
                        
    $adapter -> push$child );
                        try {
                            
    $walker = new XmlWalker$child -> childNodes );
                            
    $walker -> walk$adapter );
                        } catch( 
    IllegalParameterException $e ) {
                            die( 
    $e -> getMessage() );
                        }
                    }
                }
            }
        }
        
        class 
    RecursiveXmlAdaptor implements IAdapter {
            private 
    $fragment;
            
            public function 
    __construct$fragment ) {
                if( !
    $fragment instanceof DomElement ) {
                    throw new 
    IllegalParameterException'thrown exception on, expected parameter(s) not found.' );
                    break;
                }

    // change 1
    // missed the creation of root composite, added here now
    // fixed :)

                
    $this -> fragment = new Composite$fragment );
            }
            
            public function 
    getRoot() {
                return 
    $this -> fragment;
            }
            
            public function 
    push$fragment ) {
                
    $composite = new Composite$fragment );
                if( 
    $tmp $this -> traverse$this -> getRoot(), $fragment ) ) {
                    
    $tmp -> attach$composite );
                }
            }
            
            private function 
    traverseComponent $compositeDomElement $fragment ) {
                if( 
    $composite -> getId() == $fragment -> getAttribute'parent' ) ) {
                    return 
    $composite;
                } else {
                    if( 
    $composite -> hasChildren() ) {
                        
    $children $composite -> getChildren();
                        foreach( 
    $children as $child ) {
                            
    $c = new Composite$fragment );
                            if( 
    $tmp $this -> traverse$child$fragment ) ) {
                                
    $tmp -> attach$c );
                            }
                        }
                    }
                }
            }
        }
        
        abstract class 
    Component {
            protected 
    $id;
            protected 
    $fragment;
            protected 
    $children = array();
            
            public function 
    __construct$fragment ) {
                
    $this -> fragment $fragment;
                
    $this -> id $this -> getAttribute'id' );
            }
            
            public function 
    hasChildren() {
                return 
    count$this -> children );
            }
            
            public function 
    getChildren() {
                return 
    $this -> children;
            }
            
            public function 
    getAttribute$attribute ) {
                return 
    $this -> fragment -> getAttribute$attribute );
            }
            
            public function 
    getId() {
                return 
    $this -> id;
            }
            
    // change 2
    // missed out abstract parameters, now
    // fixed :)

            
    abstract public function attachComposite $composite );
        }
        
        class 
    Composite extends Component {
            public function 
    __construct$fragment ) {
                if( !
    $fragment instanceof DomElement ) {
                    throw new 
    IllegalParameterException'thrown exception on, expected parameter(s) not found.' );
                    break;
                }
                
    parent::__construct$fragment );
            }
            
            public function 
    attachComposite $composite ) {
                
    $this -> children[] = $composite;
            }        
        }
        
    // not neccassary to implement a leaf in some variants of composite
    // upto yourself ;)

        
    class Leaf extends Component {
        } 
    // not implemented,
        
        
    class CompositionFactory {
            private 
    $dom;
            
            public function 
    __construct$filename ) {
                if( !
    file_exists$filename ) ) {
                    throw new 
    FileIOException'thrown exception on, expected file not found.' );
                    break;
                }
                
    $this -> dom = new DomDocument;
                
    $this -> dom -> load$filename );
            }
            
            public function 
    create() {
                
    $fragment $this -> dom -> documentElement -> childNodes;
                try {

    // you may get an error with the class name 'recursivexmladapter'
    // if you do, rename the class to what you want, just a typo :eek:

                    
    $adapter = new RecursiveXmlAdapter$fragment -> item) );
                    
    $walker = new XmlWalker$fragment -> item) -> childNodes );
                    
    $walker -> walk$adapter );
                } catch( 
    IllegalParameterException $e ) {
                    die( 
    $e -> getMessage() );
                }
            }
        }
        
    ?>
    This is the refactored version of the original, such as I've now added interfaces etc. If you've any problems (and you shouldn't) let me know and I'll let you know what I've missed out

    Here is what you need to start with

    PHP Code:
    error_reportingE_ALL E_STRICT );

    try {
    $factory = new CompositionFactory'template-page-structure.xml' );
    $factory -> create();
    } catch( 
    FileIOException $e ) {
    die( 
    $e -> getMessage() );

    To realise the composite structure based on the XML you have, you need to look at the structure via the adapter, ie

    PHP Code:
    echo( '<pre>' ); print_r$adapter -> getRoot() ); echo( '</pre>' ); 
    A basic XML structure I developed with was something like this below

    Code:
    <?xml version="1.0" encoding="iso-8859-1"?>
    <templates>
    <template id="page" parent="">
    <template id="header" parent="page">
    <template id="search" parent="header" />
    </template><!-- close off header -->
    <template id="body" parent="page">
    <template id="navigation" parent="body" />
    <template id="document" parent="body">
    <template id="contents" parent="document" />
    </template><!-- close off document -->
    </template><!-- close off body -->
    <template id="footer" parent="page" />
    </templates>
    Pretty unexciting I know but the point is that each tag (node) represents a Model for any given page segment you have in your whole web page. For the recursion to work all you need is an ID and PARENT

    This has other implications such as the recursive algorithm will work easily with an Adjacency List as well for example.

    How you actually display each composite is your choice, the script works and is there to be used now. Or you can wait until I finish what I have in mind

    Enjoy anyways.
    Last edited by Dr Livingston; Mar 15, 2005 at 15:09. Reason: missed some transitional changes during refactoring...

  21. #21
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I don't really want to use a configuration file of any sort for this as it's then a maintenance issue (for me anyways).
    I believe that this is where the CoR comes into it? Reading up on this today, it appears that the CoR and Composite are a common match. If this is the case, then this could be an approach to handing a composite to a given CoR handler...

    Thoughts on this please, would be welcome

  22. #22
    SitePoint Enthusiast
    Join Date
    Jan 2005
    Location
    Sydney
    Posts
    43
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I recently came into this problem yesterday and I thought about where this should go and I put the solution in the CMS and not the backend framework. Each page would be specified in a "pages" table and there would be a blocks table and a blocks_pages table. Obviously a block would be certain parts on the page and the intersecting table would link the blocks to the pages because it's a m-m relationship.

    Because im using XML/XSL it made it a lot easier to do this. What I do is grab all of the blocks "actions" and run them and merge the results as they come in. This will create a big XML flie in a <page> node. Then I run each block to find their matching template and pull in and merge them together. This might be a bit tricky at first, but I think it would allow me to move blocks around on several pages without breaking too much of the design. Although with CSS it'll be a lot easier.

  23. #23
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The way I look at it, the actions/components and sub-actions are really just one action: a View.

    A View will instantiate whichever domain objects it needs to gather data for a particular page and will make these available to the page template. It probably doesn't need to get any more complicated than that.

    I'd deal with shared layout elements (blocks) by using Dreamweaver libraries (or the equivalent). If the same information is displayed in different views, the views can use the same domain objects. If the info is formatted in the same way in each page, that's a library item. Or different views can format the data in different ways.

  24. #24
    SitePoint Zealot
    Join Date
    May 2004
    Posts
    142
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by McGruff
    The way I look at it, the actions/components and sub-actions are really just one action: a View.

    A View will instantiate whichever domain objects it needs to gather data for a particular page and will make these available to the page template. It probably doesn't need to get any more complicated than that.
    So you could have some sort of SpecificActionView extends MainPageView for example, where MainPageView could instantiate certain domain objects (e.g. a Latest Poll or Who's Online block) and make their data available to whichever template's being used by the main action? (along with the data from SpecificAction, natch)
    Last edited by Warboss_Alex; Mar 17, 2005 at 12:08.

  25. #25
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think thats the general idea that McGruff is thinking anyways, though I am thinking the same, I'm thinking of using CoR instead of class Inheritance

    The implementation is still on the wall though


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
  •