SitePoint Sponsor

User Tag List

Page 2 of 3 FirstFirst 123 LastLast
Results 26 to 50 of 68
  1. #26
    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 rockit
    (...)do i pass Post Data or an Array???(...)
    Quote Originally Posted by rockit
    ok... so understand that this primary role is for the controller to handle the processing, where it is the responsibility to pass data to the model. otherwise, this data would be going straight to a model without formatting.
    MVC says nothing about how your model layer is structured. You'll have to look otherwhere for that. You can pass post-data directly to a model component or you can do some validation/filtering in the controller first.
    There are pros and cons to doing both things.

  2. #27
    SitePoint Guru rockit's Avatar
    Join Date
    Sep 2005
    Location
    Canada
    Posts
    636
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    what i'm working on now is a basic admin area of website that handles adding product categories into a db.

    i have it set up in such a way that a front controller handles the initial request and creates the appropriate page controller.

    PHP Code:
    $dao= new DataAccess ($localhost$user$pass$dbname); 

    switch (
    $_GET['page']) {
        case 
    "add":
            
    $controller = new AddCategoryController($dao$_GET);
        break;
        case 
    "edit":
            
    $controller = new EditCategoryController($dao$_GET);
        break;
        case 
    "delete":
            
    $controller = new DeleteCategoryController($dao$_GET);
        break;
        case 
    "view":
            
    $controller = new ViewCategoryController($dao$_GET); //handles a single record view
        
    default:
            
    $controller = new ListCategoryController($dao$_GET);  //handles a listing of all categories
        
    break;

    is this a good approach, or could there be a better way to suggest of doing things? also, should i have a seperate model for each one as well?

    here's an example of the AddCategoryController.

    in
    PHP Code:
    $this->model= new AddCategoryModel($CategoryDao); 
    should i have a seperate model for add, edit, delete, view? Should they extend a parent?

    PHP Code:
    class AddCategoryController {

        public function 
    __construct ($dao,$null) {
            
    $CategoryDao= new CategoryDao($dao); 
            
    $this->model= new AddCategoryModel($CategoryDao);
            
    $this->view= new AddCategoryView($this->model,$getvars);
        }
        
        public function 
    getView () {
            return 
    $this->view;
        }

    note i really haven't written the model entirely yet, as this has been blocking me a bit. i have my sql statement in a Dao class ie. CategoryDao.php which is basically a class with functions for each sql statement i would need.

  3. #28
    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)
    Your front controller is fine, although a bit low-tech. You might want to generalize it a bit as your application grows. A simple solution is to use an associative array with page => classname.
    You class named DataAccess looks more like a database connection than a dao ? Either way, it is clearly a model layer component. I'd create it from within the controller, rather than in the front controller.
    I wouldn't pass the model to the view, as you do it in AddCategoryController - let the view create it's own model(s), if it needs any.

    Quote Originally Posted by rockit
    also, should i have a seperate model for each one as well?
    No, there is no 1:1 relationship between model and controller (or model and view ... or controller and view). That's the whole point of MVC actually. So your current way of grouping you dao around a model layer concept (a "category") is fine. Passing the db connection into the dao is a good practice btw., so keep doing that.

  4. #29
    SitePoint Guru rockit's Avatar
    Join Date
    Sep 2005
    Location
    Canada
    Posts
    636
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    Your front controller is fine, although a bit low-tech. You might want to generalize it a bit as your application grows. A simple solution is to use an associative array with page => classname.
    you wouldn't happen to have a link to a good example would you? i learn best from seeing code, then applying it to my own. would i have something more setup in the url passed like http://localhost/index.php?page=addCategory&class=add ??? i got that set-up from a pretty basic tutorial on mvc.

    Quote Originally Posted by kyberfabrikken
    I wouldn't pass the model to the view, as you do it in AddCategoryController - let the view create it's own model(s), if it needs any.
    by doing so, am i losing scalability?

    No, there is no 1:1 relationship between model and controller (or model and view ... or controller and view)
    so instead of having a seperate model for each action, create more methods in a basemodel?

    ie.
    PHP Code:
    class CategoryModel {
         ...
         
         public function 
    add() {
              ...
         }

         public function 
    edit() {
              
    CategoryDao->editCategory(...);
         }

         public function 
    view() {
              ...
         }

         public function 
    delete() {
              ...
         }

    and each method calls the appropriate method from the dao? ie. method edit will call CategoryDao->editCategory(...);?

    i think this is it. btw, cheers on the assistance. you're a good person to have around here. thanks.

  5. #30
    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 rockit
    you wouldn't happen to have a link to a good example would you? i learn best from seeing code, then applying it to my own.
    Like this :
    PHP Code:
    $map = Array(
        
    'add' => 'AddCategoryController',
        
    'edit' => 'EditCategoryController',
        
    'delete' => 'DeleteCategoryController',
        
    'view' => 'ViewCategoryController',
        
    '' => 'ListCategoryController',
    );
    $name $map[$_GET['page']];
    $controller = new $name($_GET); 

    Quote Originally Posted by rockit
    so instead of having a seperate model for each action, create more methods in a basemodel?
    Yes, exactly.

    Quote Originally Posted by rockit
    and each method calls the appropriate method from the dao? ie. method edit will call CategoryDao->editCategory(...);
    I don't think you need both a CategoryModel and a CategoryDao. Most people let them merge together to form what is known as an active record. It mixes things up a little bit, but in reality this tends to be an acceptable tradeoff.

    Quote Originally Posted by rockit
    by doing so, am i losing scalability?
    If the controller passes the model to the view, it would mean that the controller needs to "know" which model(s) the view uses. This introduces a dependency, which makes both the controller and the view less re-usable.

  6. #31
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    If the controller passes the model to the view, it would mean that the controller needs to "know" which model(s) the view uses. This introduces a dependency, which makes both the controller and the view less re-usable.
    I would also add that doing so is not MVC. It is something; but not MVC because the Controller in MVC is not supposed to be a bridge between the View and Model.

    But I'm sure some people will want to argue that, so from a practical perspective, the View knows exactly which model it needs and is perfectly capable of fetching it, so why not let it.
    <.smarter.web.development.>
    PHP Stuff: Plexus | Chocolate (BDD Framework... coming soon)
    Graphite

  7. #32
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    > the View knows exactly which model it needs and is perfectly capable of fetching it, so why not let it.

    But of course

    There are a number of ways you can do this though, and still maintain a certain level of separation.

  8. #33
    SitePoint Guru rockit's Avatar
    Join Date
    Sep 2005
    Location
    Canada
    Posts
    636
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    If the controller passes the model to the view, it would mean that the controller needs to "know" which model(s) the view uses. This introduces a dependency, which makes both the controller and the view less re-usable.
    hhhmmm... i'm a bit confused now. how should it flow then? how would data from the model get to the view?

    also, from a view perspective... when rendering a template, is it best off to have a template object go along with it to render a template based view?

  9. #34
    SitePoint Evangelist
    Join Date
    Jun 2003
    Location
    Melbourne, Australia
    Posts
    440
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    Like this :
    PHP Code:
    $map = Array(
        
    'add' => 'AddCategoryController',
        
    'edit' => 'EditCategoryController',
        
    'delete' => 'DeleteCategoryController',
        
    'view' => 'ViewCategoryController',
        
    '' => 'ListCategoryController',
    ); 
    If the controller passes the model to the view, it would mean that the controller needs to "know" which model(s) the view uses. This introduces a dependency, which makes both the controller and the view less re-usable.
    Presumably, AddCategoryController extends a more 'generic' Controller class. Seems to me that AddCategoryController would perform (or oversee) a pretty specific task, so how re-usable is it going to be? Therefore, aside from it not being 'pure', what's the harm in having the controller decide what the model should be and passing it to the view?
    Zealotry is contingent upon 100 posts and addiction 200?

  10. #35
    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 auricle
    Seems to me that AddCategoryController would perform (or oversee) a pretty specific task, so how re-usable is it going to be?
    Let's take a concrete case. Say you want to extend your application to act as a http/rest web service. So if the client requests a content type of text/xml, you reply with an xml document, and if the client requests a content type of text/html, you reply with an html document. The xml document should only contain the minimal "raw" data, but the html document should have additional navigation and other stuff. So the html view needs more information (aka. model).
    If the controller has the task of assigning model to the view it would have to either A) pass all information to both views, even though it's only one of them that needs it all or B) treat the views differently. Taking A to the extreme, the controller would have to pass every conceivable model component to every view. B means that your controller and view are very hard coupled - You might as well merge them into one component. This isn't nescesarily a bad idea - for simple applications a 2-tier may be sufficient. It's not MVC though.

    Quote Originally Posted by auricle
    Therefore, aside from it not being 'pure', what's the harm in having the controller decide what the model should be and passing it to the view?
    Nothing at all - But it's not MVC.

  11. #36
    SitePoint Evangelist
    Join Date
    Jun 2003
    Location
    Melbourne, Australia
    Posts
    440
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    If the controller has the task of assigning model to the view it would have to either A) pass all information to both views, even though it's only one of them that needs it all or B) treat the views differently.
    Why would both views have been instantiated? Well, I suppose they might have been, but surely some sort of lazy loading mechanism could take care of that.
    Taking A to the extreme, the controller would have to pass every conceivable model component to every view. B means that your controller and view are very hard coupled - You might as well merge them into one component.
    I sort of see what you mean, although I'd prefer to keep them separate (a "separation of concerns issue" I think).

    There's a lot of talk about coupling and dependencies in this forum which veers between orthodoxy and practicalities. We're all making specific controllers, rather than generic ones, but we forget (or ignore) that, in a sense, the controller is 'coupled' to the request and that the extra information (as you put it) is probably going to specific to that request. (Hat tip to Dr Livingston: that may not be the case in a composite structure but then different parts of that will probably have different controllers handling them.) So having a controller which isn't going to be used for anything else know choose the model isn't bad ...it may be considered practical.

    Six of one, half a dozen of the other between:
    1. Controller chooses View
    2. View chooses Model
    and
    1. Controller chooses View
    2. Controller chooses Model

    Quote Originally Posted by kyberfabrikken
    But it's not MVC.
    So be it.
    Zealotry is contingent upon 100 posts and addiction 200?

  12. #37
    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 auricle
    Why would both views have been instantiated?
    I think you misunderstood me. They wouldn't both be instantiated on the same request. One would be instantiated on one request, the other on another request. Eg. :
    Code:
    Client1 request text/html => Server respond text/html (view1)
    ...
    Client2 request text/xml => Server respond text/xml (view2)
    Quote Originally Posted by auricle
    There's a lot of talk about coupling and dependencies in this forum which veers between orthodoxy and practicalities.
    Yes, coupling is a rather abstract concept. What I meant was that whenever you change the views requirements, you will need to add logic to the controller. Whenever you add a new view, you will need to add logic to the controller.

    Quote Originally Posted by auricle
    (...) but we forget (or ignore) that, in a sense, the controller is 'coupled' to the request and that the extra information (as you put it) is probably going to specific to that request.
    The controller is definitely coupled to the request. The whole point of the controller is to encapsulate the input (request) and shield the rest of the application from dealing with it. The view shouldn't be though.

  13. #38
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    > Well, I suppose they might have been, but surely some sort of lazy loading mechanism could take
    > care of that.

    That is beside the point, Kyber was talking about something else, all together, which I see he has cleared it up now?

  14. #39
    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 auricle
    There's a lot of talk about coupling and dependencies in this forum which veers between orthodoxy and practicalities.
    ...
    ...
    Six of one, half a dozen of the other
    It can appear that views and controllers are intimately bound together but it's not so. The two are fundamentally different and can have different rates of change. A controller receives input, decides what to do with it and manipulates the domain. A view has to fetch some data and display it. The only thing they have in common is that they deal with the same data.... or do they?

    The technical ability of the end user often influences what you want to display. A simple success/failure type of view with a note to contact a sysadmin when something fails might be best for relatively unskilled users. Apart from a simple boolean, the view does not need to gather any data from the domain at all. At the other extreme a longer, detailed report might be better for admin-level users. In contrast to the simple report, the detailed version will probably touch most of the domain objects involved in whatever is being done. Maybe you would have to provide both for different users: multiple views for the same underlying domain manipulation.

    I usually find myself facing this kind of problem if I'm writing a new app ie exactly what data do I want to pull out for display? Often I don't really know and it won't become clear until later. Suppose you were writing the first ever unit testing framework. There is a kind of standard where test runs produce a red or green bar - a simple boolean result with a brief note of the number of test cases and individual assertions. If you were exploring the territory for the first time it might take a few tries before you hit on this simple view type but none of the different views you might try out would affect the underlying domain action: "run a list of tests". Different views simply ask different objects for different kinds of data, and maybe add some presentation logic to interpret the data into a meaningful display. Separation between controller and view means that a controller - which orchestrates the domain manipulation - does not need to keep pace with changes to the view. It can be written, tested and put to one side while you play around with different display ideas.

    Another example: at the moment I'm writing a refactoring tool: what should I display for a "rename class" refactoring? This could be a simple "name changed successfully", a list of all edited files (the file containing the class and all files which include or instantiate it) or at the extreme end of the scale a bunch of diffs showing everything that happened in minute detail. Or something else - perhaps just a red/green bar from an "all tests" run to verify that the refactoring worked. I won't really know until I've played around with it myself and also get some feedback from others.

    Underlying these view options is the same "rename class" action. The controller will issue commands to domain objects to kick this off and, since they're ready at hand, it might be tempting simply to pass these on to the view (many "MVC" apps do just that). That's not necessarily bad design (although I wouldn't call it MVC). It could be that a view reads from the same list of objects manipulated by the controller. But not always. In the last example - show the results of an "all tests" run - the view doesn't read from any of them. The display would be created with a whole other app - SimpleTest - which has nothing to do with the rename class refactoring.

    OOP is all about choices and consequences. I think the key point about MVC is to allow controllers and views to vary independently. If that's not an issue, you don't have to follow an MVC architecture.
    Last edited by McGruff; Oct 19, 2006 at 08:37. Reason: clarifying some points

  15. #40
    SitePoint Guru rockit's Avatar
    Join Date
    Sep 2005
    Location
    Canada
    Posts
    636
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    I wouldn't pass the model to the view, as you do it in AddCategoryController - let the view create it's own model(s), if it needs any.
    hhhmmm... i missed this, how does a view create it's own model? i thought what you did was invoke your model & view instance from the controller? anyone have a good explanation of what i'm to do here?

  16. #41
    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 rockit
    i thought what you did was invoke your model & view instance from the controller? anyone have a good explanation of what i'm to do here?
    A lot of so-called MVC implementations do that. I believe it's violating the MVC principle, even though I realize that it is often more practical.
    The controllers task is to a) update the model and b) select the view. Nothing more. The controller is not a glue layer between model and view. The view on the other hand, is more than just a template. It's the logic that renders the output. The view can include complex logic (but often doesn't) and it can access the model. It just can't write to the model. Only the controller can do that.

  17. #42
    SitePoint Wizard bronze trophy devbanana's Avatar
    Join Date
    Apr 2006
    Location
    Pennsylvania
    Posts
    1,736
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I have a model factory that is passed to the view that allows the view to select a model.

    The following is in PHP4 since I'm currently programming a site in PHP4.

    PHP Code:
    $model =& $this->model_factory->get('model_name'); 
    The thing is, sometimes I want the same instance as the controller has so that the view can subscribe to notifications from this model. Yes I use the push model instead of pull.

    PHP Code:
    $this->handler->models['model_name']->subscribe('on_data_selected', array($this'dataSelected')); 
    PHP Code:
    function dataSelected(&$model$arguments)
    {
    $this->data $arguments['data'];

    Works for me. I have stopped worrying about what is "proper," and started just doing what works best for my situation.

  18. #43
    SitePoint Guru rockit's Avatar
    Join Date
    Sep 2005
    Location
    Canada
    Posts
    636
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    A lot of so-called MVC implementations do that. I believe it's violating the MVC principle, even though I realize that it is often more practical.
    The controllers task is to a) update the model and b) select the view. Nothing more. The controller is not a glue layer between model and view. The view on the other hand, is more than just a template. It's the logic that renders the output. The view can include complex logic (but often doesn't) and it can access the model. It just can't write to the model. Only the controller can do that.
    thanks kyber, but isn't that sort of the same thing. The controller updates the model with data, and then selects a view to use?

    Code:
    $model = new $model($db, $get);
    //... model functions if need be,
    
    $view = new $view($collection); //pass any data to the view in a collection?
    or is this creating too much of a dependancy on the controller to bond the 2 together. what confuses me is how to get everyone talking without dependancies? how would you do it?

  19. #44
    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 rockit
    or is this creating too much of a dependancy on the controller to bond the 2 together. what confuses me is how to get everyone talking without dependancies?
    The problem is that if the controller is to pass model components to the view, the controller needs to know which model components the view needs. This forms a dependency.

    Quote Originally Posted by rockit
    how would you do it?
    To be honest, I break the rules if it's the practical thing to do. But if you want MVC separation, it's perfectly possible to do. Here's a by-the-book example :

    Model layer :
    PHP Code:
    class MyModel
    {
      protected 
    $name "World";
      static protected 
    $instance;

      static function 
    getInstance() {
        if (!isset(
    self::$instance)) {
          
    self::$instance = new MyModel();
        }
        return 
    self::$instance;
      }

      function 
    getName() {
        return 
    $this->name;
      }

      function 
    setName($name) {
        
    $this->name $name;
      }

    View layer :
    PHP Code:
    class MyView
    {
      function 
    execute() {
        
    $m MyModel::getInstance();
        echo 
    "Hello ".$m->getName();
      }

    Controller layer :
    PHP Code:
    if ($_SERVER['HTTP_METHOD'] == "POST") {
      
    $m MyModel::getInstance();
      
    $m->setName("PostWorld");
    }
    $view = new MyView();
    $view->execute(); 
    Last edited by kyberfabrikken; Oct 24, 2006 at 05:41. Reason: fixed minor bugs, that prevented the example from working

  20. #45
    SitePoint Guru rockit's Avatar
    Join Date
    Sep 2005
    Location
    Canada
    Posts
    636
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    The problem is that if the controller is to pass model components to the view, the controller needs to know which model components the view needs. This forms a dependency.


    To be honest, I break the rules if it's the practical thing to do. But if you want MVC separation, it's perfectly possible to do. Here's a by-the-book example :

    Model layer :
    PHP Code:
    class MyModel
    {
      protected 
    $name "World";

      function 
    getName() {
        return 
    $this->name;
      }

      function 
    setName($name) {
        
    $this->name $name;
      }

    View layer :
    PHP Code:
    class MyView
    {
      function 
    execute() {
        
    $m = new MyModel();
        return 
    "Hello ".$m->getName();
      }

    Controller layer :
    PHP Code:
    if ($_SERVER['HTTP_METHOD'] == "POST") {
      
    $m = new MyModel();
      
    $m->setName("PostWorld");
    }
    $view = new MyView();
    $view->execute(); 

    ok, but you create a model from the view in your execute command?

  21. #46
    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 rockit
    ok, but you create a model from the view in your execute command?
    You can name it render, if that suits you better than execute. The point is that the view creates the model - it's not given the model from the controller.

    This raises another problem - namely about shared objects. You'd normally want to avoid creating the same model twice, so you'd have to deal with this somehow. That problem is unrelated to the MVC strategy though. You'd eventually get the problem anyway.

    Off Topic:


    I can see that I missed an echo somewhere in the example above. You can replace return in the view class with echo to make the example actually work.

  22. #47
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Actually kyberfabrikken, your "by the book" example does not work. Well it does work on GET and would print "Hello World", but it does not work on POST and would print "Hello World" again whereas it should print "Hello PostWorld".
    <.smarter.web.development.>
    PHP Stuff: Plexus | Chocolate (BDD Framework... coming soon)
    Graphite

  23. #48
    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 dreamscape
    Actually kyberfabrikken, your "by the book" example does not work. Well it does work on GET and would print "Hello World", but it does not work on POST and would print "Hello World" again whereas it should print "Hello PostWorld".
    You're right ... That's the shared objects problem kicking in ... Make MyModel global, and the problem is solved. (Oh - there are much better solutions than globals, but that's another topic).

    Off Topic:


    well .. i edited the post now, so it'll actually work .. sorry for not testing before posting

  24. #49
    SitePoint Guru rockit's Avatar
    Join Date
    Sep 2005
    Location
    Canada
    Posts
    636
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    ok... so as a rule of thumb...???

    Model - Domain Logic. doesn't concern itself with anyone else besides itself processing data?

    View - Creates a model & Responsible for read only access to the model to output data?

    Controller - Updates the Model? and of course many other things ie. Intercepting filters, session handling...

    is this a correct understanding of MVC?

  25. #50
    SitePoint Guru rockit's Avatar
    Join Date
    Sep 2005
    Location
    Canada
    Posts
    636
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    what confused me is tutorials i found online that contradict some discussions around here.

    http://www.phppatterns.com/docs/desi...roller_pattern

    Code:
    <?php
    /**
     *  Fetches "products" from the database
     */
    class ProductModel {
        /**
        * Private
        * $dao an instance of the DataAccess class
        */
        var $dao;
    
        //! A constructor.
        /**
        * Constucts a new ProductModel object
        * @param $dbobject an instance of the DataAccess class
        */
        function ProductModel (&$dao) {
            $this->dao=& $dao;
        }
    
        //! A manipulator
        /**
        * Tells the $dboject to store this query as a resource
        * @param $start the row to start from
        * @param $rows the number of rows to fetch
        * @return void
        */
        function listProducts($start=1,$rows=50) {
            $this->dao->fetch("SELECT * FROM products LIMIT ".$start.", ".$rows);
        }
    
        //! A manipulator
        /**
        * Tells the $dboject to store this query as a resource
        * @param $id a primary key for a row
        * @return void
        */
        function listProduct($id) {
            $this->dao->fetch("SELECT * FROM products WHERE PRODUCTID='".$id."'");
        }
    
        //! A manipulator
        /**
        * Fetches a product as an associative array from the $dbobject
        * @return mixed
        */
        function getProduct() {
            if ( $product=$this->dao->getRow() )
                return $product;
            else
                return false;
        }
    }
    ?>
    Code:
    <?php
    /**
     *  Binds product data to HTML rendering
     */
    class ProductView {
        /**
        * Private
        * $model an instance of the ProductModel class
        */
        var $model;
    
        /**
        * Private
        * $output rendered HTML is stored here for display
        */
        var $output;
    
        //! A constructor.
        /**
        * Constucts a new ProductView object
        * @param $model an instance of the ProductModel class
        */
        function ProductView (&$model) {
            $this->model=& $model;
        }
    
        //! A manipulator
        /**
        * Builds the top of an HTML page
        * @return void
        */
        function header () {
            $this->output=<<<EOD
    <!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
    <head>
    <title> Our Products </title>
    <style>
    body { font-size: 13.75px; font-family: verdana }
    td { font-size: 13.75px; font-family: verdana }
    .title { font-size: 15.75px; font-weight: bold; font-family: verdana }
    .heading {
        font-size: 13.75px; font-weight: bold;
        font-family: verdana; background-color: #f7f8f9 }
    .nav { background-color: #f7f8f9 }
    </style>
    </head>
    <body>
    <div align="center" class="title">Our Products</div>
    EOD;
            $this->output.="\n<div align=\"right\"><a href=\"".
                $_SERVER['PHP_SELF']."\">Start Over</a></div>\n";
    
        }
    
        //! A manipulator
        /**
        * Builds the bottom of an HTML page
        * @return void
        */
        function footer () {
            $this->output.="</body>\n</html>";
        }
    }
    
    class ProductItemView extends ProductView {
        /**
        * Private
        * $productID ID of product to render
        */
        var $productID;
    
        //! A constructor.
        /**
        * Constucts a new ProductView object
        * @param $model an instance of the ProductModel class
        */
        function ProductItemView (&$model,$productID) {
            ProductView::ProductView($model);
            $this->productID=$productID;
        }
    
        //! A manipulator
        /**
        * Renders a single product
        * @return void
        */
        function productItem() {
            $this->model->listProduct($this->productID);
            while ( $product=$this->model->getProduct() ) {
                $this->output.="<p><b>Name</b>:".$product['PRODUCTNAME']."</p>".
                    "<p><b>Price</b>:".$product['UNITPRICE']."</p>".
                    "<p><b># In Stock</b>:".$product['UNITSINSTOCK']."</p>";
                if ( $product['DISCONTINUED']==1 ) {
                    $this->output.="<p>This product has been discontinued.</p>";
                }
            }
        }
    
        //! An accessor
        /**
        * Returns the rendered HTML
        * @return string
        */
        function display () {
            $this->header();
            $this->productItem();
            $this->footer();
            return $this->output;
        }
    }
    
    class ProductTableView extends ProductView {
        /**
        * Private
        * $rowsperpage number of results per page
        */
        var $rowsPerPage;
        /**
        * Private
        * $rownum begin display of rows at this ID
        */
        var $rowNum;
    
        //! A constructor.
        /**
        * Constucts a new ProductView object
        * @param $model an instance of the ProductModel class
        */
        function ProductTableView (&$model,$rowsPerPage=20,$rowNum=1) {
            ProductView::ProductView($model);
            $this->rowsPerPage=$rowsPerPage;
            $this->rowNum=$rowNum;
        }
    
        //! A manipulator
        /**
        * Renders a product table
        * @return void
        */
        function productTable() {
            $this->model->listProducts($this->rowNum,$this->rowsPerPage);
            $this->output.="<table width=\"600\" align=\"center\">\n<tr>\n".
                    "<td class=\"heading\">Name</td>\n".
                    "<td class=\"heading\">Price</td>\n</tr>\n";
            while ( $product=$this->model->getProduct() ) {
                $lastID=$product['PRODUCTID'];
                $this->output.="<tr>\n<td><a href=\"".$_SERVER['PHP_SELF'].
                    "?view=product&id=".$product['PRODUCTID']."\">".
                    $product['PRODUCTNAME']."</a></td>".
                    "<td>".$product['UNITPRICE']."</td>\n</tr>\n";
            }
            $this->output.="<tr class=\"nav\">\n";
            if ( $this->rowNum > 0 && $this->rowNum > $this->rowsPerPage ) {
                $this->output.="<td><a href=\"".$_SERVER['PHP_SELF'].
                    "?view=table&rownum=".($this->rowNum-$this->rowsPerPage).
                    "\"><< Prev</a></td>";
            } else {
                $this->output.="<td>&nbsp;</td>";            
            }
            if ( $this->rowsPerPage <= ( $lastID - $this->rowNum ) ) {
                $this->output.="<td><a href=\"".$_SERVER['PHP_SELF'].
                    "?view=table&rownum=".($this->rowNum+$this->rowsPerPage).
                    "\">Next >></a></td>";
            } else {
                $this->output.="<td>&nbsp;</td>\n";            
            }
            $this->output.="</tr>\n</table>\n";
        }
    
        //! An accessor
        /**
        * Returns the rendered HTML
        * @return string
        */
        function display () {
            $this->header();
            $this->productTable();
            $this->footer();
            return $this->output;
        }
    }
    ?>
    Code:
    <?php
    /**
     *  Controls the application
     */
    class ProductController {
        var $model;
        var $view;
    
        //! A constructor.
        /**
        * Constucts a new ProductController object
        * @param $model an instance of the ProductModel class
        * @param $getvars the incoming HTTP GET method variables
        */
        function ProductController (& $dao) {
            $this->model=& new ProductModel($dao);
        }
    }
    
    class ProductItemController extends ProductController {
       //! A constructor.
        /**
        * Constucts a new ProductItemController object
        * @param $model an instance of the ProductModel class
        * @param $getvars the incoming HTTP GET method variables
        */
        function ProductItemController (& $dao,$getvars=null) {
            ProductController::ProductController($dao);
            $this->view=& new ProductItemView($this->model,$getvars['id']);
        }
    
        function & getView () {
            return $this->view;
        }
    }
    
    class ProductTableController extends ProductController {
       //! A constructor.
        /**
        * Constucts a new ProductTableController object
        * @param $model an instance of the ProductModel class
        * @param $getvars the incoming HTTP GET method variables
        */
        function ProductTableController (& $dao,$getvars=null) {
            ProductController::ProductController($dao);
            if ( !isset ($getvars['rowsperpage']) )
                $rowsperpage=20;
            if ( !isset ($getvars['rownum']) )
                $getvars['rownum']=1;
            $this->view=& new ProductTableView($this->model,
                                        $rowsperpage,
                                        $getvars['rownum']);
        }
    
        function & getView () {
            return $this->view;
        }
    }
    ?>
    Code:
    <?php
    require_once('lib/DataAccess.php');
    require_once('lib/ProductModel.php');
    require_once('lib/ProductView.php');
    require_once('lib/ProductController.php');
    
    $dao=& new DataAccess ('localhost','user','pass','dbname');
    switch ( $_GET['view'] ) {
        case "product":
            $controller=& new ProductItemController($dao,$_GET);
            break;
        default:
            $controller=& new ProductTableController($dao,$_GET);
            break;
    }
    $view=$controller->getView();
    echo ("<pre>" );
    // print_r($controller);
    echo ("</pre>" );
    echo ($view->display());
    ?>
    as you can see, the ProductModel is being instantiated from the controller. As it's listed in advanced resources, i had trusted that this was correct, but what's being said here is the opposite, and that this example has the implementation wrong. the controller is passing the model to the view...??? so if i'm correct in saying that this example has errors in it, then how many others is this possibly confusing?

    it just doesn't seem to be a true MVC example. who knows, maybe i'm wrong.


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
  •