SitePoint Sponsor

User Tag List

Page 3 of 4 FirstFirst 1234 LastLast
Results 51 to 75 of 83
  1. #51
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    > simply select the product view class and let my view class decide?

    Leave it to the view to make that decision; Conditional validations are okay in the template as the logic is simple. Anything heavier than this, then you need to push it out of the template.

  2. #52
    SitePoint Enthusiast
    Join Date
    Oct 2006
    Posts
    85
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston View Post
    Conditional validations are okay in the template as the logic is simple.
    Not to be a nitpick, but the wording should be that it is in fact presentation logic, not that the logic itself is simple.

  3. #53
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That is what I meant but yes, I could have been clearer

  4. #54
    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 crabby80 View Post
    $view->NoData(); or would my controller simply select the product view class and let my view class decide?
    You can certainly do both things, but if you want to maintain MVC separation (In particular separation of V and C), you can only pick the second choice.

  5. #55
    SitePoint Addict crabby80's Avatar
    Join Date
    May 2007
    Posts
    387
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thank you for the reponse guys

  6. #56
    SitePoint Addict crabby80's Avatar
    Join Date
    May 2007
    Posts
    387
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi Blueyon

    Did you have any joy incorporating composite into your MVC example?

    Also in your example do you skip the view layer and push model data from the controller to the template?

    Thanks

    Crabby

  7. #57
    SitePoint Addict
    Join Date
    Feb 2006
    Posts
    281
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by crabby80 View Post
    Hi Blueyon

    Did you have any joy incorporating composite into your MVC example?
    I haven't added the composite to the Framework yet. To be honest it doesn't need to to do this. The only difference between how its done now and using the composite pattern is that one is automatically generating the HTML and passing and the other is done manually. I will add the composite pattern though

    Also in your example do you skip the view layer and push model data from the controller to the template?
    It depends if the data needs altering before it goes into the view. You might need to create an array of links so you would get the data from the model and use the the url class to create the links and then push the data into the view.

    Try taking a look at my opencart project. If you go to the development section and use subversion to download the latest release. You will see how I set applications up.
    Last edited by blueyon; Jul 25, 2007 at 06:19.

  8. #58
    SitePoint Addict crabby80's Avatar
    Join Date
    May 2007
    Posts
    387
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks blueyon I'll check it out

  9. #59
    Grumpy Minimalist
    Join Date
    Jul 2006
    Location
    Ontario, Canada
    Posts
    424
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Firstly, let me say that three weeks ago I had never even looked at MVC before

    After reading this thread several times, I tried to visualize what kyberfabrikken and honeymonster were talking about. I came up with this:


    What do you guys think of it (besides the fact that I'm terrible with Visio )?

    In a nutshell:
    • Web requests always go to the Front Controller, which sets up the server to deal with the code.
    • The Front Controller always calls the default Controller.
    • Controllers look at the web request, and decide which View to use.
    • Views have access to any Models that they need.
    • Views extract information that they need from the Models in order to display the results.
    • Models perform the logic and calculations which they need to return meaningful data to the views.
    • Models do not need to know about Views, and are not bound to any single View.
    • Models have access to any Data streams they need.
    • Data streams are responsible only for formating and returning data from their respective sources.
    • Data streams access low level sources such as files or sessions.
    • Views spit their results directly into the output stream.
    • Views can decide that they need to load sub-Controllers in order to display themselves.
    • Sub-Controllers are the same as regular Controllers (they're all peers).


    Does that make sense, or did I completely kill the concept?

  10. #60
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Two points...

    > Data streams access low level sources such as files or sessions.

    No in regards to SESSIONs, which are part of the request and only your Controller(s) should be aware of them. The Model(s) shouldn't be aware of them, and...

    > Views can decide that they need to load sub-Controllers in order to display themselves.

    No to this as well; A decision to fetch a lower (child) Controller should be based around the request. A given Controller only selects a View and leaves it that.

    That is my take on MVC for the web but apart from those two points, I think you've got it about right.

  11. #61
    Grumpy Minimalist
    Join Date
    Jul 2006
    Location
    Ontario, Canada
    Posts
    424
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston View Post
    > Data streams access low level sources such as files or sessions.

    No in regards to SESSIONs, which are part of the request and only your Controller(s) should be aware of them. The Model(s) shouldn't be aware of them, and...
    Alright, that makes sense.

    Quote Originally Posted by Dr Livingston View Post
    > Views can decide that they need to load sub-Controllers in order to display themselves.

    No to this as well; A decision to fetch a lower (child) Controller should be based around the request. A given Controller only selects a View and leaves it that.
    I'm not sure if I follow this. This system is a composite system, where the child Controllers are not really children (in terms of inheritance), but pieces of the composition. My understanding is that the decision to merge a sub-View into the current View (through the sub-Controller) should be made by the current View.

    Ex.
    • Controller for the main page loads a View.
    • View outputs some data.
    • View decides that there should be a sub-View for the left-hand navigation on the site.
    • View loads the Controller for the navigation View as a child.
    • Controller for the navigation loads a View.
    • Navigation View outputs some data.
    • Control is returned to the main page View.
    • View outputs some data, etc...


    Is my understanding of composites incorrect?

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

    Your understanding of Composite is correct I think but your implementation details are wrong, but you have your implementation methods and I have mine.

    For example,

    > View decides that there should be a sub-View for the left-hand navigation on the site.

    To me, it's not the Views responsibility to make that decision, but the Controllers. Imagine that based on one request, you would want to display some navigation, but based on another request (a different user for example) you may well not want to display that navigation.

    That falls under the Controllers responsibility.

    > View loads the Controller for the navigation View as a child.

    View shouldn't have any knowledge of a Controller either...

  13. #63
    Grumpy Minimalist
    Join Date
    Jul 2006
    Location
    Ontario, Canada
    Posts
    424
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston View Post
    To me, it's not the Views responsibility to make that decision, but the Controllers. Imagine that based on one request, you would want to display some navigation, but based on another request (a different user for example) you may well not want to display that navigation.

    That falls under the Controllers responsibility.

    <snip>

    View shouldn't have any knowledge of a Controller either...
    Alright, I guess I'm still a little confused then. I didn't realize that Views weren't supposed to know about Controllers. What I had in mind to solve the above was:

    • Main page Controller makes main page View.
    • Main page View calls Navigation Controller.
    • Navigation Controller determines which navigation View to show based on user information.
    • Navigation Controller creates the proper View.
    • Navigation View picks the proper Model(s) and renders.
    • Output of navigation View returns to main page View.
    • Main page View renders itself with embedded navigation View (and others, if needed).


    ...but that requires a View to know about the Controller of any children it wants, so I guess that's not correct.

    The only problem I see with putting that information into the Controller is that a given Controller would need to know about what children a given View needs. Is that correct?

    Quote Originally Posted by Dr Livingston View Post
    but you have your implementation methods and I have mine.
    Haha, no worries -- I still have no idea what I'm doing

  14. #64
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    > is that a given Controller would need to know about what children a given View needs.

    I leave it to the Controller to select their own View, including any child Controllers if any. So any given Controller is only aware of it's own View. To generate the complete template, I leave that task to the response, so again a View is only aware of it's own scope.

    I've found that it makes things more flexible from the View side of things but pushes any complexity towards the response instead.

    Implementation details of course differ however you should observe the directions of how the 3 different layers communicate,

    Code:
    Controller --> Selects A View --> View --> Selects A Model <-- Model Data Goes To View <-- Model
    So, it's appropriate that the View knows about a Model, but not the other way around; It's appropriate the View is aware of the request, but not the Model. A View may need to be aware of the request to make decisions on presentation for example...

  15. #65
    Grumpy Minimalist
    Join Date
    Jul 2006
    Location
    Ontario, Canada
    Posts
    424
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston View Post
    I leave that task to the response

    <snip>

    A View may need to be aware of the request
    Just a few things which I still don't understand which aren't made very clear in the example framework here:
    1) You mention a "request"; does that just refer to the data coming through the Controller, or is it some other object?
    2) You mention a "response"; is that a different object as well?
    3) Where do templates fit into all of this? I thought that Views simply spit out the HTML themselves?

    Here's my current understanding of the complete system (minus the Controller for now):
    Code PHP:
    abstract class View
    {
    	protected $myModel = null;
    	public abstract function render();
    }
     
    abstract class Model
    {
    }
     
    class MainModel extends Model
    {
    	public function getTitle()
    	{
    		return "My Site";
    	}
    }
     
    class MainView extends View
    {
    	public function __construct()
    	{
    		//Would use a locator (or similar) here
    		$this->myModel = new MainModel();
    	}
     
    	public function render()
    	{
    		?>
    			<html>
    				<head>
    					<title><?php echo($this->myModel->getTitle()); ?></title>
    				</head>
    				<body>
    					<p>Stuff</p>
    				</body>
    			</html>
    		<?php
    	}
    }

  16. #66
    SitePoint Addict Jasper Bekkers's Avatar
    Join Date
    May 2007
    Location
    The Netherlands
    Posts
    282
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Tarh View Post
    3) Where do templates fit into all of this? I thought that Views simply spit out the HTML themselves?
    Views are just a representation of a Model, wether that is through a PDF, RSS, MP3 or HTML. If any of those file formats would require some external libraries they are free to use it.
    Design patterns: trying to do Smalltalk in Java.
    I blog too, you know.

  17. #67
    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 Dr Livingston View Post
    Two points...

    > Data streams access low level sources such as files or sessions.

    No in regards to SESSIONs, which are part of the request and only your Controller(s) should be aware of them. The Model(s) shouldn't be aware of them, and...
    The request is a complex issue. Conceptually, I would identify it as a model component -- Certainly the session is. The special case about the request is, that it's almost exclusively used by the controller (The session excluded).

  18. #68
    SitePoint Member
    Join Date
    Oct 2007
    Posts
    21
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi everyone.

    Thanks for Push Model example. How about Pull Model?

  19. #69
    SitePoint Enthusiast
    Join Date
    Jul 2008
    Posts
    53
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston View Post
    > View loads the Controller for the navigation View as a child.

    View shouldn't have any knowledge of a Controller either...
    Interesting.
    I was working with a project where the template files created new controllers all over the place.. something which I did not like, but: In some way, the views need to get access to distant resources.. For instance, if I want to display personal messages on the start page. How can this happen?

  20. #70
    SitePoint Addict
    Join Date
    Feb 2007
    Posts
    251
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @lemon.head:

    Potential sticking point: a view and a template are not necessarily the same thing.

    Let's put some code down real quick...

    PHP Code:
    class StartPageHtmlView extends HtmlView {
        function 
    __construct($session$messageFinder) {
            
    $this->session $session;
            
    $this->messageFinder $messageFinder;
        }
        function 
    exec() {
            
    $messages $this->messageFinder->findByUserId($this->session->getUserId());
            echo 
    $this->renderTemplate('messages'$messages)
        }
    }

    $view = new StartPageHtmlView(new Session(), new MessageFinder());
    $view->exec(); 
    In this particular case, the only thing a controller should have to do is instantiate the view we've defined. And since Apache already maps particular URLs to particular PHP files, we really don't need to define a controller at all. It's already there.

    We might want to move the view's class definition into another file, but that's a matter of taste.

    Views can and should use models directly. They don't need to ask the controller to pull data for them.

    There's no need to instantiate controllers from within the view. The only time the controller should get involved is when the model needs to change, but then that should never happen inside of the view.

    You can generate a link or a form to enact a change in the model from an HTML view of course, but that's not really the same thing, since the browser has to send a new request before any of those changes will be made. A controller on the opposite end of the link or form will be responsible for updating the model.

  21. #71
    SitePoint Enthusiast
    Join Date
    Jul 2008
    Posts
    53
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The point is that on the startpage I may want to display any kind of content from anywhere in the application. Maybe at one time I decide that in addition to messages, I want to show the latest blog or forum posts.

    Now there are different possibilities:
    • controller gives a forum object and a messages object to the view. This means, I have to change the signature of the view class, and the controller needs to know which components the view wants to show. This can happen
      1. give a rendered string. In this case the controller needs to take care of calling a view component from somewhere else..
      2. give a view component with a render() method (I'd call this a "widget"). One for messages, one for forum, one for blog.
      3. give a model component, and let the startpage view do the layout.
    • view class takes these resources from "global scope" by creating new view or model classes (here, by global scope I mean the classnames defined in global scope).
    • controller gives a biig factory/container to the view, that has creation methods for all the possible model or view components.


    Next question will be, where does the controller take the stuff from? Again, a big factory, or global scope class construction?

    In this particular case, the only thing a controller should have to do is instantiate the view we've defined. And since Apache already maps particular URLs to particular PHP files, we really don't need to define a controller at all. It's already there.
    Yeah, but in a bigger project I prefer nice URLs and single entry point..

    Views can and should use models directly. They don't need to ask the controller to pull data for them.
    Ok, so.. class construction inside the view, or big access object / factory?
    In your example you have a MessageFinder, which is an access object, but can only fetch messages, not other things. If you want to allow the view to use all different kinds of resources, you need to give it either all possible access objects, or one big factory.

  22. #72
    SitePoint Addict
    Join Date
    Feb 2007
    Posts
    251
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The point is that on the startpage I may want to display any kind of content from anywhere in the application. Maybe at one time I decide that in addition to messages, I want to show the latest blog or forum posts.
    The controller doesn't need to be involved here either. The deciding factor would be what is ultimately influencing the display of the page.

    Why would you decide to show the latest blog or forum posts? Does it have to do with user input? If so, a controller will be needed, otherwise the view can handle everything by itself.

    For instance, let's say you decide to show forum posts only if the user has posted to a forum, and then only to those topics they've participated in. Do we need a controller here? Why? All of the information is available in the model, and the only thing required is read access, so why can't the view carry the full burden?

    Next question will be, where does the controller take the stuff from? Again, a big factory, or global scope class construction?
    I'd go for the factory, i.e., service locator, or dependency injection. Either will eliminate the need to work with globals.

    Ok, so.. class construction inside the view, or big access object / factory?
    In your example you have a MessageFinder, which is an access object, but can only fetch messages, not other things. If you want to allow the view to use all different kinds of resources, you need to give it either all possible access objects, or one big factory.
    If I went with a service locator, it would look something like this...

    PHP Code:
    class ServiceLocator {
        
    /**
         * @return MessageFinder
         */
        
    function messageFinder() {
            return new 
    MessageFinder();
        }
    }

    class 
    MessageFinder {
        function 
    findByUserId($userId) {
        }

    I'd be sure to use PHPdoc annotations and avoid __call magic or instantiating objects using variable class names in the interest of code completion. This way PDT can remind me of the various elements inside the locator.

    As for the view, I'd change the admittedly oversimplified code in my previous post. Perhaps something more like this...

    PHP Code:
    $view = new PageView();
    $view->addChild(new WelcomeMessagesView(), 'welcomeMessages');
    // ForumPostsView might not return output, but it's still a part of this view
    $view->addChild(new ForumPostsView(), 'forumPosts');
    $view->accept($renderer = new HtmlPageRenderer());
    echo 
    $renderer->render($locator); 
    However, I'd do some extra work to make the code a little cleaner when it comes to nesting views, i.e., create a fluent API.

    In any case, the renderer would visit each node, passing the locator into each view's execute() method. The execute() method would then return an array of outputs keyed by slot name, e.g., array('main' => 'main content', 'welcomeMessages' => '<p>Welcome!</p>'). The renderer would then explode() the output array, include a template, and return the HTML to the calling context.

  23. #73
    SitePoint Enthusiast
    Join Date
    Jul 2008
    Posts
    53
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'd be sure to use PHPdoc annotations and avoid __call magic or instantiating objects using variable class names in the interest of code completion.
    Hehe, that is almost worth a new discussion..
    I generally love magic methods, so I imagine a factory to look like this,

    PHP Code:
    new FruitStore('banana');  // without factory
    $new->FruitStore('banana');  // with factory 
    In the factory, the __call method would just create a new FruitStore, if it does not find any dedicated methods. Maybe it would have a mechanism to call $this->init_FruitStore('banana') if such a method exists, or it would look if it has such a method for one of the base classes. Well, I have not yet implemented such a factory myself.

    I agree, this will totally break code completion (autocomplete).
    But, code completion does already break if the editor doesn't know about the type of the factory.

    A problem with hardcoding all the methods is that it will be a pain to change the factory interface.

    So you have to balance two things:
    • as an experienced and/or conservative programmer you know what you are doing, and the interface of your classes will remain as-is for some time.
    • As a less experienced and more playful programmer you often get the idea of changing your interfaces. This happens a lot to me.
      Then it's nicer if you don't have all the hard-coded redundancy methods like setters, getters and factory methods, which by default do nothing but "return new $classname(...)" or "return $this->$key".
    • The bigger the classes (often you can't change that, because they were written by other people), the more I feel annoyed by the extra lines of code consumed by getters and setters.


    Ok, but this would rather fit in a different topic.

  24. #74
    SitePoint Enthusiast
    Join Date
    Jul 2008
    Posts
    53
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Another problem is that the ServiceLocator will grow to a painful big class.

    With magic "__call($classname, $args)", or a method "create($classname)", you can delegate the creation to specialized factories, which are registered to deal with only one type of objects each. And the consumer won't have to care which factory does what.

    Again, autocomplete remains broken

  25. #75
    SitePoint Addict
    Join Date
    Feb 2007
    Posts
    251
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmm. Not sure I follow you. What's wrong with doing this?

    PHP Code:
    class ServiceLocator {
        
    /**
         * @return ThingAFactory
         */
        
    function thingAFactory() {
            return new 
    ThingAFactory();
        }
        
    /**
         * @return ThingBFactory
         */
        
    function thingBFactory() {
            return new 
    ThingBFactory();
        }

    You still get to delegate to your factories and you don't lose any code completion features.

    As for the editor not knowing about the types, you just have to make sure you have your project's include path set to the proper location.

    And regarding the size of the classes and the maintenance burden, if it turns out your application is really huge and the interfaces are still in flux, you could always resort to reflection/code generation. Not the funnest thing in the world, but perhaps a happy medium.

    There are refactoring tools available for PHP too. They might address this problem on some level. I haven't tried to use them though, so I don't know how sophisticated they are.


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
  •