SitePoint Sponsor

User Tag List

Page 1 of 6 12345 ... LastLast
Results 1 to 25 of 138
  1. #1
    SitePoint Member
    Join Date
    Aug 2004
    Location
    Germany
    Posts
    21
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Exclamation Captain Protons MVC Advanced Example

    Hello together!

    I implemented Captain Protons MVC example, because I think it is the easiest way to understand and implement a MVC application. But I have a lot of problems if it comes to complex pages:

    Think about a page like www.sitepoint.com, the page has a complex layout structure. You have got a page header with a main navigation bar. The body uses a three column design, with 2 side bars which contain a lot of boxes (search, navigation, advertisement ...). And at the bottom of the page you have a footer with links and copyright information. Most of the page components stay the same if you navigate through the site. Most times only the middle column with the page content change.

    My question is, how could I implement a complex page like sitepoint.com with Captain Protons MVC model?

    Please take a look at that, especially at the comments:
    PHP Code:
    <?php
    class FrontController
    {
        function 
    run()
        {
            switch (
    $_GET['page'])
            {
                case 
    'add':
                    
    $command = new UserAddCommand;
                    break;

                case 
    'edit':
                    
    $command = new UserEditCommand;
                    break;

                case 
    'list':
                    
    $command = new UserListCommand;
                    break;
            }

            
    $command->execute();
            
    $view $command->getView();
            
    $view->render();
        }
    }

    class 
    UserEditCommand extends BaseCommand
    {
        function 
    execute()
        {
            
    /*
            A Data Transfer Object in order to transfer the data 
            collected by the 
            command object to the view object. 

            Is this a good way? It is something like a push (data)
            approach?! I use a transfer object in order to 
            encapsulate many parameters, which I need to get
            into the view! I think it is a common pattern 
            (DTO or Value Object) ? 
            
            But such a transfer object could become very 
            complex, if I have to transfer a great amount
            of data to the view…. 

            I have to transfer all the data for the content
            column, for the boxes in the sidebar, 
            for the header, the footer … Is it the right way 
            to collect those data in the command class
            (by invoking business objects in order to keep 
            the command class small …)? 
            I think of separating content from design … 

            Another approach could be that only the data
            for the content column is transferred to the view, 
            and the view class collects the data for the header, 
            sidebars and footer by invoking business objects? 
            (Something like a pull approach …) 
            But that is not a good way to separate content 
            from design?
            */
            
    $dto = new Dto(); 
            
            
    // Common data
            
    $dto->__set("pageTitle""User Tasks");
            
    $dto->__set("copyright""Copyright by me!");
            
    // ...
            
            
    if ($userIsNotFoundInDatabase)
            {

            
    $dto->__set("pageTitle""News");

                
    $this->view = new UserNotFoundView($dto);
                return;
            }

            if (!
    $formHasBeenSubmitted)
            {
                
    $dto->__set("message""Well done ...");
                
    $this->view = new UserAddView($dto);
                return;
            }

            if (
    $formIsValid)
            {
                
    $user;
                
    $user->username $_POST['username'];
                
    $user->password $_POST['password'];
                
    $user->email $_POST['email'];

                
    $user->save(); // could be $userDAO->save($user) or whatever

                
    $this->view = new UserHasBeenEditedView($dto);
            }
            else
            {
                
    // Redisplay the form
                
    $dto->__set("post"$_POST); 
                
    $dto->__set("errormessage"$formErrorMessages);
                
    $this->view = new UserEditView($dto);
            }
        }
    }


    // Views 

    // ...

    class UserHasBeenAddedView
    {
        function 
    render()
        {
            
    /*
            This view is only an example which does 
            not fit to the UserHasBeenAddedView!
            
            The Problem with this view is, e.g. to construct
            a header, footer, sidebar view ...
            is a common task, which I nearly need in every 
            view object. To put that in every view object is 
            not a good approach, if you think about 
            reusability or maintanance?!

            Perhaps a pattern helps here? Something like the 
            façade pattern
           (http://www.dofactory.com/Patterns/PatternFacade.aspx), 
            a view helper?? I have no idea, any suggestions? ;-)
            */
            
            
    $dto $this->getDto();
            
            
    $pageTpl = new Template(DIR_TEMPLATES_APPLICATION.'page.tpl.php');
            
            
    $pageTpl->setVar('pageTitle'$dto->__get('pageTitle'));
            
    $pageTpl->setVar('stylesheetPath'DIR_REL_TEMPLATES_APPLICATION);
            
            
            
    /**********************************************/
            /* Page Header:
            /*********************************************/
            
    $headerTpl = new Template(DIR_TEMPLATES_APPLICATION.'header.tpl.php');
            
    $pageTpl->setVar('pageHeader'$headerTpl->parse());
            
    /**********************************************/
            
            
    $loginTpl = new Template(DIR_TEMPLATES_APPLICATION.'login.tpl.php');
            
    $loginTpl->setVar('loginUrl'$dto->__get('loginUrl'));
            
    $login $loginTpl->parse();
            
            
    $column1  '';
            
    $column1 .= $login;
            
    $pageTpl->setVar('pageColumn1'$column1);        

            
            
    $pageTpl->setVar('pageColumn2'$dto->__get('pageContent'));
            
            
    $pageTpl->setVar('pageColumn3''');
            
            
    /**********************************************/
            /* Page Footer:
            /*********************************************/
            
    $footerTpl = new Template(DIR_TEMPLATES_APPLICATION.'footer.tpl.php');
            
    $pageTpl->setVar('pageFooter'$footerTpl->parse());
            
    /**********************************************/

            
    $pageTpl->display();    
        }
    }

    ?>
    I took a look a the
    “java petstore example”
    , but that example is very complex and difficult to understand. They visualized the mvc pattern for a complex site like that:



    They use patters like value object, view helper, composite view etc. in order to implement a complex mvc application. Let's transfer that into a simple Captain Proton example :-) A example how to use the proton mvc code with a complex page would be really nice ...

    Greetings from Germany
    (Excuse my bad English!)

  2. #2
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You're right - this is where mvc get's complex. The keywords you should be looking into are ActionChain/ControllerChain and perhaps CompositeView.
    We had a pretty lengthy discussion recently here witch might help you.

  3. #3
    SitePoint Member
    Join Date
    Aug 2004
    Location
    Germany
    Posts
    21
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @kyberfabrikken

    thanks for your fast answer, I take a look at your keywords ;-)
    I although hope that we could aasemble a "Captain Proton" example here.
    I think that could help many people here.
    -----------------
    http://www.xbox-profis.de :: The german Xbox Community

  4. #4
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    A very stripped down excerpt from the setup, I'm currently using :
    PHP Code:
    class ActionChain extends ListIterator
    {
        function 
    ActionChain()
        {
            
    $this->ListIterator($a = array());
        }

        function 
    push(&$action)
        {
            if (!
    is_a($action'ACTION')) {
                
    trigger_error("argument is not a valid action"E_USER_ERROR);
            }
            
    parent::push($action);
            
    $outer =& $action->getOuterAction();
            if (!
    is_null($outer)) {
                
    $this->push($outer);
            }
        }

        function & 
    execute()
        {
            
    $response null;
            if (
    $this->count() > 0) do {
                
    $action =& $this->current();
                if (
    is_a($response'COMPONENT')) {
                    
    $action->innerView =& $response;
                }
                
    $response =& $action->execute();
                if (
    is_a($response'FORWARD')) {
                    return 
    $response;
                }
            } while (
    $this->advance());
            return 
    $response;
        }

    PHP Code:
    class Action
    {
        
    /**
          * The view to display. May be a Component (Most likely an instance of
          * Template) or a Forward.
          * @var mixed
          * @access private
          */
        
    var $view=null;
        
    /**
          * If the Action wraps an inner action, this variable will hold the response of it.
          * @var Component
          */
        
    var $innerView=null;

        
    /**
          * Executes the action, and returns a Component or Forward
          * You shouldn't override execute() - override bind() instead
          * @protected
          */
        
    function & execute()
        {
            
    $this->bind();
            return 
    $this->view;
        }

        
    /**
          * Fetches data from the model and applies it to the view.
          * The method is invoked by execute()
          * This method is only relevant for Actions's that returns a Component
          * @abstract
          */
        
    function bind() { }

        
    /**
          * If the action needs a wrap, it can return it from here.
          * You may override this.
          * @see ActionChain
          */
        
    function & getOuterAction()
        {
            return 
    null;
        }

    PHP Code:
    class Component
    {
        function 
    render() { }
    }

    class 
    Forward
    {
        var 
    $url;

        function 
    Forward($url)
        {
            
    $this->url $url;
        }

        function 
    execute()
        {
            
    header("Location: " $this->url);
            exit(
    0);
        }

    The frontcontroller will select an Action, and setup an ActionChain. It will then add the Action to the Chain with push(), witch allows the Action to apply outer actions as needed.
    Something like the following :
    PHP Code:
    class DisplayArticleAction extends Action
    {
        function 
    bind()
        {
            
    $this->view =& new Template("article.tmpl");
            
    $this->view->setValue("title""Title of the Article");
            
    $this->view->setValue("body""Lorem Ipsum ...");
        }

        function & 
    getOuterAction()
        {
            return new 
    MainSectionAction();
        }
    }

    class 
    MainSectionAction extends Action
    {
        function 
    bind()
        {
            
    $this->view =& new Template("mainsection.tmpl");
            
    $menu =& new MainMenuAction();
            
    $this->view->setValue("menu"$menu->render());
            
    $this->view->setValue("content"$this->innerView->render());
        }
    }

    class 
    MainMenuAction extends Action
    {
        function 
    bind()
        {
            
    $this->view =& new Template("mainmenu.tmpl");
        }

    PHP Code:
    $actionChain =& new ActionChain();
    $primaryAction =& new DisplayArticleAction();
    $actionChain->push($primaryAction);
    $response =& $actionChain->execute();
    if (
    is_a($response'COMPONENT')) {
        echo 
    $response->render();
    }
    if (
    is_a($response'FORWARD')) {
        
    $response->execute();


  5. #5
    SitePoint Guru
    Join Date
    Oct 2001
    Posts
    656
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You're right - this is where mvc get's complex. The keywords you should be looking into are ActionChain/ControllerChain and perhaps CompositeView.
    I'd say that is where your making mvc more complex than it is

    The thing is, mvc doesn't say anything about how you should implement things like that. What I do know is that you don't need things like ActionChaining and Composite Views. I've never found the use for ActionChaining anyway.

    There are two approaches you can take to data gathering for the View. You can choose to only gather 'model data' (which in practice means data from your db) in the Command classes and pass all of it to the View. Or you can choose to let the View load data it needs by itself. There have been some discussions about this before on this forum, I think.

    My personal approach is the latter: if a View needs some data, I usually let it load that data itself. Of course this doesn't mean that you have to give your view direct database access, the loading of data can go through a DAO or mapper or something like that.

    The only model data I pass directly to the View are things like a User object in the UserEditCommand. I've already loaded that object in the Command to see if the userID is valid, so there's no point in having the view load it again.

    // Common data
    $dto->__set("pageTitle", "User Tasks");
    $dto->__set("copyright", "Copyright by me!");
    // ...
    You shouldn't be doing that in the Command class if you ask me. That data is View-related, simply define it one of your View subclasses.

    I hope I've given some useful advice

  6. #6
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The thing is, mvc doesn't say anything about how you should implement things like that.
    Point taken - but it's the next step, and it's a big one.

    I honestly don't like the idea of the View pulling data, but I admit it's an option.

  7. #7
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The only option, surely? Code which collects data for display is by definition part of the view.

  8. #8
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by McGruff
    The only option, surely? Code which collects data for display is by definition part of the view.
    I disagree. I believe the gathering of data is the responsibility of the controller. The view is just supposed to display it.
    The thing is - there is a very thin line between pulling content from within the view or pushing it from the controller. The latter strategy may feel awkard at times, but I think that for a bullet-proof seperation it's worth it. Once you allowed the view to pull data, you're moving into a slippery slope. It takes discipline from the template-developers - something you may not be able to count on.

  9. #9
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If the Controller were to get involved in the View that's not MVC. That doesn't mean it's a bad design. The most important thing is to separate presentation from domain but the point about MVC is to separate Controller and View within the presentation layer. With a passive model, the controller tells the view to update itself but that's all. With an active model, it doesn't even do that. The model notifies the view when it has "changed".

    http://wact.sourceforge.net/index.ph...ViewController

  10. #10
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If the Controller were to get involved in the View that's not MVC.
    In my opinion, yours is an extreme view of MVC. Many writers rightly note that the MV separation is the priority and that the VC and CM separations have varied in strictness depending on the implementation. Even pure MV separation is difficult because there is often a direct correlation between what is in the model and the view. Changes to one require corresponding changes to the other.
    Christopher

  11. #11
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by arborint
    In my opinion, yours is an extreme view of MVC. Many writers rightly note that the MV separation is the priority and that the VC and CM separations have varied in strictness depending on the implementation.
    That's news to me. Which authors are you referring to?

    Let's say I announce a new sex-segregated school where boys and girls will be taught separately. Next I say that boys and girls will be in the same classes. Clearly, I have a problem. I can either come clean and admit everyone is mixed up together or I can separate the classes. I can't do both.

    Quote Originally Posted by arborint
    Even pure MV separation is difficult because there is often a direct correlation between what is in the model and the view. Changes to one require corresponding changes to the other.
    What difficulties are you experiencing? A change in page design - such as a new theme - shouldn't affect the model in any way. Adding a new page element which requires additional data, or a whole new view, may require some new model classes but the view and model remain in separate layers - or at least they should.

    The key is that model objects supply raw, unformatted data. The view adds all the formatting and "prints" the data to browser, email, file or whatever.

  12. #12
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That's news to me. Which authors are you referring to?
    Matrin Fowler PoEAA page 331-2 for one. It is often recommended in these forums if you haven't read it.
    What difficulties are you experiencing?
    No difficulties. It also noted (also by Fowler) for example that when you add a field to your database you have to modify your presentation to display that field, and vice-versa. Separation can mean many things from conceptual through concrete. Likewise "separate layers" can refer to varying degrees and types of separation.
    Christopher

  13. #13
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It's good that you've discovered PoEEA but I think you ought to read that again.

  14. #14
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You mean the part where he says "The second division, the separation of of view and controller, is less important." or where he says, "In practice most systems have only one controller per view, however, so this separation is usually not done." Perhaps you should discover the PoEAA as well.
    Christopher

  15. #15
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If the separation is not made it's not MVC.

  16. #16
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Still reading folks, but this point made by the Captain,

    Of course this doesn't mean that you have to give your view direct database access, the loading of data can go through a DAO or mapper or something like that.
    This is where the View Helper comes into it, mentioned from the Pet Shop example I might add that for building a page dynamically in segments, the Composite View pattern is essential

    Kyber has implemented the Composite View of sorts but it remains static from what I can see?

  17. #17
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Back to the original question, the way I'd handle that would be more Dreamweaver than php. In a designer-friendly templating system, you'd probably want to let them use Dreamweaver libraries for shared layout elements. From the php end you just have to match model data to template tags. The controller selects a view, the view gets the data and combines this with the template. A DataTransferObject can sometimes be useful.

    Also, have a look at how WACT does it.

  18. #18
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Still pondering over McGruffs claim.

    In the original MVC pattern, the Controller updates the Model, and the Model then notifies the View.
    I accept Fowlers authority in the field, but I still can't help feeling the seperation between Controller and View is artificial (for a web-application). Maybe it stems from the word Controller - It makes me believe that it should stay in control - keep the initiative. Allowing the View to pull from the Model inverts this flow.

    Kyber has implemented the Composite View of sorts but it remains static from what I can see?
    Actually it's both static and dynamic. The DisplayArticleAction is loosely coupled to MainSectionAction, while MainMenuAction is tightly coupled to MainSectionAction. I find use for both (The above example should illustrate that).

  19. #19
    SitePoint Member
    Join Date
    Aug 2004
    Location
    Germany
    Posts
    21
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks a lot to all your replies. The discussion is getting very interesting! :-)
    I took a look at Apache Struts, I think they use a kind of action mapping in order to assemble a complex page. But they although offer an approach like Captain Protons suggestion:

    Apache Tiles

    The problem is the java world is very complex (but the solutions are often very good!). I search the perfect solution for PHP with following thinks in mind:

    • so simple as possible (Protons MVC is a very good start for that ;-) But now a bit more advanced please => a real world example ;-), A PHP approach!
    • So reusable as possible, easy to maintain
    • good to expand
    • separation of content from design => clear separation of the tiers


    I know there exist some PHP solutions (frameworks), like wact, mojavi, prado etc. … but I want to be able to develop my own solution or at least to be able to understand the magic behind the advanced mvc concepts … and for that there are easy examples necessary! Not like the java petstore ;-)

    By the way, thank you kyberfabrikken for posting your solution!
    -----------------
    http://www.xbox-profis.de :: The german Xbox Community

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

    There is an element of dynamicism there? Sorry, didn't pay enough attention but I'll take another look at it

    As for the discussion on MVC on PoEAA Fowler suggests the separation of the View and Controller to a degree to be pointless in regards to the Web. This I cannot understand, as the point of the pattern is to separate, so why not go the whole way huh?

    Why just settle separating the View and Model and nothing more...

  21. #21
    SitePoint Member
    Join Date
    Aug 2004
    Location
    Germany
    Posts
    21
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @Dr Livingston

    perhaps a complete separation is to complex? Please take a look at my first post (the code), there I tried to do that. I collect all the data in the command object and then I transfer it with a Data Transfer Object (DTO) to the View. The problem is, the DTO gets fast huge and complex. If I understand Kyber right, he suggests to split a action / command into subactions (a actionChain):

    action (userEdit) {
    useredit .... => usereditView
    subaction (login) => loginview
    subaction (pageheader) => pageView
    ....
    }

    ...?
    -----------------
    http://www.xbox-profis.de :: The german Xbox Community

  22. #22
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think there must be some kind of Fowler-mis-quoting virus doing the rounds. This is what he says:

    [MVC] has come back into vogue with Web interfaces where it becomes useful for separating the controller and view again.

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

    As for the discussion on MVC on PoEAA Fowler suggests the separation of the View and Controller to a degree to be pointless in regards to the Web.
    Looks like I got it wrong, after reading it again now. In my defence though, I was in a bit of a hurry at the time...

  24. #24
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    My problem with many MVC conversations here is that they churn on the definition. I hadn't read the PoEAA in over a year but went back to it because chapter and verse seems to be necessary in some discussions. In rereading it, my take on Fowler is that MVC is all about the separation and very little about how the M, V, and C actually function. He promotes the M-V separation as the most important; the V-C separation as important, but less so; and barely mentions the C-M separation. I seems, from my reading of it, that he understands that separation can done in many ways and to varying degrees.

    But real MVC implementation conversations are about how to implement the M, V and C while keeping the goal of separation in mind. The degree and type of separation is in may ways dictated by the goals and requirements of the parts.
    Christopher

  25. #25
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    kyberfabrikken, can you post your ListIterator code so I can try you code out?
    Christopher


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
  •