SitePoint Sponsor

User Tag List

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

Hybrid View

  1. #1
    SitePoint Zealot Overunner's Avatar
    Join Date
    Mar 2004
    Location
    Sweden
    Posts
    180
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [MVC] Implementation issues

    Hi!

    I have a few fundamental questions regarding...pretty much everything that has to do with developing a successfull MVC application. Ok, lets start with probably the easiest one concerning Front Controller and Page Controller.

    If you implement the Front Controller, you let your index.php be your single entrypoint to the application, and conversely, with the Page Controller you implement a Controller for every page, thus you'll get multiple entrypoints.
    However, with the Page Controller you don't have to be concered with the Action Mapping since it will be hardcoded(?) in the controllers. This is not the case with the Front Controller, and my question is, how should I implement the Action Mapping for the Front Controller? (I may have misunderstood the whole concept of Action Mapping, but isn't its purpose to restrict the FrontController from executing an arbitrary action by altering the appropriate $_GET variable manually? For example, if the client is at your index page, he shouldn't be able to execute the...say ListMostActiveUsersOnTheForum Action just by manipulating the URL from index.php to index.php?action=ListMostActiveUsersOnTheForum), right?)

    How can a ActionChain / Composite View pattern help me when I want to generate a complex page? I'm mainly interested in code examples regarding this issue.

    What is the best way to transfer data from the Model to the View? Or should I let the View fetch the data it needs?

    Hmm, that's about it...for now

  2. #2
    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 Overunner
    if the client is at your index page, he shouldn't be able to execute the...say ListMostActiveUsersOnTheForum Action just by manipulating the URL from index.php to index.php?action=ListMostActiveUsersOnTheForum), right?)
    Very often, FrontControllers map the request to something that can handle it by including a file. It's more efficient than a huge switch-case, for example. If the file doesn't exist (eg query string tampering) a 404 error can be triggered.

    How can a ActionChain / Composite View pattern help me when I want to generate a complex page? I'm mainly interested in code examples regarding this issue.
    You could make actions as a composite structure if you need to rollback. If any one action fails, you can issue a rollback command which will trickle down the composite structure. If you need to.

    I'm not so sure about composite views: I don't like lots of template fragments, preferring a single template file per page.

    What is the best way to transfer data from the Model to the View? Or should I let the View fetch the data it needs?
    I was discussing this recently but we didn't reach a conclusion. In MVC, the presentation layer is separated into view and controller. To my mind, fetching data for a view is the responsibility of the view. The controller simply fires the starter pistol. If the controller fetches data then hands it over to the view, I'd argue that controller and view are not separated and it's not MVC. Not that you have to write apps in MVC, of course.

  3. #3
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    For the framework I've been developing, I went with what seemed to me to be the simplest system. I have a front controller that calls a second, domain specific controller; sort of like a command object, except that all the commands for a given domain are part of the same class. Therefore, a request such as index.php?section=news&action=view calls the exec_view function of the news_controller. The authentication system takes care of security issues i.e. a user can't arbitrarily execute a command he doesn't have the right to execute.

    For transfering data to the view, I simply have the controller pass the model to the view object for the latter to do it's thing. Getting the controller more involved means you risk having to modify the controller when you change views, which I wanted to avoid.

    As for the ActionChain / Composite View issue, that's something I'm still working out for myself; most of the work I've done to date on my framework has been in the orm department

  4. #4
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    how should I implement the Action Mapping for the Front Controller?
    There are really two main directions to go here. Either translate a parameter value into file/class names, or lookup the file/class names in a map using the parameter value. The former has the advantage of simplicity and eliminates the need to load or maintain a map, but requires rigid naming and does not allow finer control, remapping or additional data that the latter does. For most PHP sites that is an ok trade-off and you don't need a map.
    What is the best way to transfer data from the Model to the View? Or should I let the View fetch the data it needs?
    If you let the View fetch the data it needs then it is not MVC. It is often said that the Controller should manage creating and connecting the Model and View, otherwise it is just a dispatcher. Passing the Model to the View is the simplest way to keep the dependency going the right direction.
    Christopher

  5. #5
    SitePoint Zealot Overunner's Avatar
    Join Date
    Mar 2004
    Location
    Sweden
    Posts
    180
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I have a front controller that calls a second, domain specific controller; sort of like a command object, except that all the commands for a given domain are part of the same class. Therefore, a request such as index.php?section=news&action=view calls the exec_view function of the news_controller.
    So basically, you have a Front Controller which fetches an appropriate Page Controller (by examining the section-variable in the URL) which in turn executes the Action the user has requested.
    Is your authentication system implemented as Intercepting filters or...something else? I remember I had some difficulties implementing it as filters, so I put it in the Page Controllers. However, it would be interesting to hear your solution.

    Either translate a parameter value into file/class names, or lookup the file/class names in a map using the parameter value.
    I'm interested in how the second method looks like implementationwise. How is the map maintained etc?

    Now regarding chaining actions, I think the main problem is that there is a 1 -> many relation between a user request and the number of actions which get executed. For example, say the user has requests your Top10 page, index.php?action=top10 (1 request), where the most active users, most popular downloads etc. (many actions) will be displayed. The problem is, how do I know when several actions gonna be executed (and how do I store the result of each action, since each action will return a template fragment)? I've thought about two ways to tackle this.

    You could for instance have 1 large Action e.g ListMostActiveUsersAndMostPopularDownloadsAndKitchenSinks which executes several actions. But as you can see, it will probably result in an explosion of classes.

    The other approach requires to have a Front Controller + Page Controllers / Application Controllers. E.g the user requests the Top10 page, index.php?section=top10&action=. The Front Controller creates a Top10 PageController (or App. Controller, not sure about the difference) which in turn examines the action the user has request and uses conditional logic to build the action chain. E.g
    PHP Code:
      class Top10Controller extends PageController
      
    {
        function 
    execute()
        {
          
    $this->actionChain = new ActionChain();

          switch (
    Request :: getAction())
          {
            default:
            case 
    'ListTop10s':
              
    $this->actionChain->register('ListMostActiveUsers');
              
    $this->actionChain->register('ListMostPopularDownloads');
              
    // ...
              
    break;

            case 
    'blabla':
          }

          return 
    $this->actionChain->execute();
        }
      } 
    But I don't fancy this method either since I don't know how I can replace the switch-statement (bad code smell) + there are other issues as well.

    This is where the Composite View patterns comes in I guess? This method involves building a tree structure of components (actions) and then let a Visitor visit each node and execute it and display its content...somehow. Anyhow I'm very interested in how others have solved this problem.

    Cheers.

  6. #6
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Overunner
    So basically, you have a Front Controller which fetches an appropriate Page Controller (by examining the section-variable in the URL) which in turn executes the Action the user has requested.
    Is your authentication system implemented as Intercepting filters or...something else? I remember I had some difficulties implementing it as filters, so I put it in the Page Controllers. However, it would be interesting to hear your solution.
    Nothing so complicated as a filter; it's simply a method of the controller that is called by the controller's 'main' method; it takes the current user (who is assigned a role) and looks up that user's rights for the given action in a database. There's a flag in the config that I set to bypass the authentication, if need be.

    Quote Originally Posted by Overunner
    This is where the Composite View patterns comes in I guess? This method involves building a tree structure of components (actions) and then let a Visitor visit each node and execute it and display its content...somehow. Anyhow I'm very interested in how others have solved this problem.
    I've been spending quite a bit of time thinking about this; and this is the simplest system I've come up with.

    1. Front controller receives request
    2. Front controller looks up an entry in a data source of some kind to find the actions for that request, along with a template to use for the final layout.
    3. The controller executes each action by calling the sub controllers in turn, and the output for each view is placed in the template.
    4. The completed template is then returned to the browser.


    I plan on adding a default mapping system featuring wildcards to obviate the need for creating entries in the mapping for each possible request that is recieved. As for the mapping data, I'm currently planning on storing it in a database and then caching it for quick access (maybe as a serialized array?).

    Ultimately, I see my framework as having two layers; a lower layer of MVC triads for each type of data, and an upper layer consisting of the Front Controller, the mapping data, and the Composite Views. I realise that this may be exactly how a lot of existing MVC frameworks work, I haven't done a whole lot of research into existing solutions...

    Quote Originally Posted by arborint
    I think the general goal of MVC is that the View is not dependent on the Controller, but often it makes sense to have some dependecy the other way.
    My take on this is that the controller should be view agnostic, meaning that you can use the same controller with any number of different views. To me this is where the real benefit of using MVC lies.

  7. #7
    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 33degrees
    My take on this is that the controller should be view agnostic, meaning that you can use the same controller with any number of different views. To me this is where the real benefit of using MVC lies.
    Well that would be nice, wouldn't it ? There will always be some dependency between View and Controller - The Controller makes assumptions about witch Model the View needs, or the View makes assumpsions about witch Model the Controller supplies. On a code-level I can appreciate to have markup in one file (View), and php-code in another (Controller), but to try removing the logical dependency between the two isn't something I would want to spend time on. As far as I get it, it is pointless to try to seperate the two with completely. (At least if we're talking web-applications in php).
    I'm not really sure if that was what you meant, but nevertheless.

    Quote Originally Posted by aborint
    OK, sorry. I meant that if you break View/Model separation it's not MVC. I think the Model should fetch the data and the View shoud access the data through the Model.
    Affirmative. Model-Presentation seperation is fundamental, I think our use of the word "data" is imprecise (Or at least mine is). Sometimes I refer to data and what I really mean is the Model. At other times by data I mean the information witch the Model contains.

  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
    I was discussing this recently but we didn't reach a conclusion. In MVC, the presentation layer is separated into view and controller. To my mind, fetching data for a view is the responsibility of the view. The controller simply fires the starter pistol. If the controller fetches data then hands it over to the view, I'd argue that controller and view are not separated and it's not MVC. Not that you have to write apps in MVC, of course.
    Quote Originally Posted by arborint
    If you let the View fetch the data it needs then it is not MVC. It is often said that the Controller should manage creating and connecting the Model and View, otherwise it is just a dispatcher. Passing the Model to the View is the simplest way to keep the dependency going the right direction.
    I respectfully disagree. The degree of seperation between Controller and View is (as McGruff hinted) an oppinionated size.
    If the Controller pass the Model to the View, the Controller becomes dependent on the View. On the other hand, if the View access the Model directly, the seperation between Controller and View is blurred out - in the extreme you have DispatcherView, witch is really a combination of Controller and View. Still - there is no problem in combining FrontController with DispatcherView, witch I have found a good compromise in the world of PHP.

    I think a source of confusion surrounding MVC is that FrontController and PageController doesn't really have anything directly to do with the MVC pattern - they are related, but they are dealing with different problemdomains. PageController and FrontController is about mapping request to controller, while MVC is about seperating Model, View and Controller. Keep that in mind.

  9. #9
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm a little confused about what you "respectfully disagree" about.

    I'm also unclear about what "fetch the data" means in this context. I think of the Model or some layer below as fetching the data. I'm not sure I've ever heard "the View fetched the data from the Model" used before, but maybe that is what was meant.
    Christopher

  10. #10
    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 arborint
    I'm a little confused about what you "respectfully disagree" about.
    I meant that "If you let the View fetch the data it needs then it is not MVC." was a very absolute way to put it.
    If a DispatcherView uses a ViewHelper to access the Model, you have the View as the active part of the action, in contrast to having a Controller assign values to the View (template-style).

  11. #11
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    OK, sorry. I meant that if you break View/Model separation it's not MVC. I think the Model should fetch the data and the View shoud access the data through the Model.

    I agree that View/Controller separation is secondary. I think the general goal of MVC is that the View is not dependent on the Controller, but often it makes sense to have some dependecy the other way.
    Christopher

  12. #12
    SitePoint Wizard
    Join Date
    May 2003
    Location
    Berlin, Germany
    Posts
    1,829
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I go the way of storing all the actions/commands my front controller need to handle in a CommanDicitionary object, which then gets passed to the FrontController. Passing the Request to the FrontController it can then execute the appropriate action/command. If the requested command is not registered with the FC, I display an error page.

    Now there are a few implementation issues with this: Doing it the dictionary way one can build other dictionaries at run time, which can be send via a network. Often, with our websites this is not needed, but I have a Java background.
    Also whether you simply register the name of the action/command with the FC and then let it load the required class or whether you store the Action object in the dictionary is pretty much down to taste isn't it? The latter of course may result in performance issues once the dictionary gets really big or whether some of the loaded classes are really big. In most projects however, this should not play any role.

    Well, what are the advantages of this? It's closer to the problem...i.e. the FC reading from a book and translating the Request into a Response/Execution of a Command. Secondly, everything is well encapsulated from each other. The FC need not know whether an Action is a simple one or a Composite one with many sub actions.

    About the MVC implementation: Actually I firstly did it the way what McGruff stands for: The model needs to pull the data from the sources it needs, i.e. data fetching is done by the model. The Views simply access the model. That means, that the dispatcher/controller selects a view and passes the model to it. The View tells the model to fetch some data it will need and then access that data via the model.
    But then again if you have a PDFView and a HtmlView of some text that is stored in the database, both Views would include the same code for telling the model to fetch the data. Isn't that Code Repition?

    My 2 bits.

  13. #13
    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 DarkAngelBGE
    But then again if you have a PDFView and a HtmlView of some text that is stored in the database, both Views would include the same code for telling the model to fetch the data. Isn't that Code Repition?
    It is, but with the kind of applications most people build with php, this is a rare occurrence. I think the best solution is to base the framework around this NOT happening, and then have special-cases for thoose rare situations. As mentioned, a ViewHelper could be created as a mediator between Controller and View, witch would hold this duplicate code. I wouldn't create a ViewHelper untill I actually have the need for it, however.

  14. #14
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DarkAngelBGE
    About the MVC implementation: Actually I firstly did it the way what McGruff stands for: The model needs to pull the data from the sources it needs, i.e. data fetching is done by the model. The Views simply access the model. That means, that the dispatcher/controller selects a view and passes the model to it. The View tells the model to fetch some data it will need and then access that data via the model.
    But then again if you have a PDFView and a HtmlView of some text that is stored in the database, both Views would include the same code for telling the model to fetch the data. Isn't that Code Repition?
    This seems wrong to me; shouldn't it be the controller telling the model what data to load, and the view simply accessing the data it wants to display? This would solve the code repetition issue you mention...

  15. #15
    SitePoint Enthusiast
    Join Date
    Oct 2004
    Posts
    88
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Why not let the view figure out which model(s) it needs?


    The controller loads the demanded view.
    |
    The view fetchs data from the model(s).
    |
    The view assign template variables.
    |
    The controller loads the related template and output its result content

  16. #16
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by atu
    Why not let the view figure out which model(s) it needs?


    The controller loads the demanded view.
    |
    The view fetchs data from the model(s).
    |
    The view assign template variables.
    |
    The controller loads the related template and output its result content
    What exactly do you mean by 'figure out'? I'd say that a model is generally picked based, in some way, on the request, which makes it the controller's domain.

  17. #17
    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 atu
    The view fetchs data from the model(s).
    |
    The view assign template variables.
    Here is definately some confusion going on. The View can't "assign template variables". If you use TemplateView, the Template is the View, and the code witch assigns data to the Template is the Controller (commonly represented by a class called Action or Command or even just Controller).

    Allow me to recap on TemplateView vs. DispatcherView:

    If you use DispatherView, the View pulls from the Model, whereas in the TemplateView the Model is pushed to the View (~Template) by the Controller (~Action). You may then argue that the DispatcherView isn't "true" MVC, since Controller and View are intertwined. This can be dealt with by introducing the ViewHelper witch is an object that pulls data from the Model. This gives you back your VC seperation, since the controller-logic is now in the ViewHelper.
    So in the DispatcherView you have the Controller represented by the ViewHelper, while in the TemplateView you have the Controller represented by the Action.
    The benefit of using DispatherView over TemplateView is that if you have little to nothing going on in the Controller, you don't need to create an object. In the TemplateView, you will allways have an Action - even if it does nothing but echo out the View. The dark side of the DispatcherView is that it requires discipline since you could easily be tempted to stuff controller-logic into your View.

  18. #18
    SitePoint Wizard
    Join Date
    May 2003
    Location
    Berlin, Germany
    Posts
    1,829
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by 33degrees
    This seems wrong to me; shouldn't it be the controller telling the model what data to load, and the view simply accessing the data it wants to display? This would solve the code repetition issue you mention...
    This is exactly what we are debating. As McGruff said, we had a discussion about this a few days or weeks ago and didn't come to a result. It probably doesn't matter much, since both way have disadvantages. The code repetition problem can easily be adressed with a ViewHelper.

    Then again I come to believe that MVC really means only separation of concerns. How everybody implements this separation is not part of MVC.

    Just for the purpose of receiving comments, here is my current set up:

    -FC is created and populated with a CommandDictionary that holds the Command objects and a string to identify them.
    -The Request is passed to the FC...the $_GET['command'] variable is matched to the CmdDictionary. If there is a command for it, execute it (or if it is a Composite Command, execute all childs as well), else execute a default Command.

    -Each Command holds a controller, which is executed when the command is executed. Based on the Request, the Controller loads a View and populates it with a model, which belongs to the controller.
    - The View accesses the model and tells it to fetch some data. The View accesses this data and loads a template based on criteria that is met by the data (i.e. there me a default error template and then some).
    -The FC fetches the output from the command, which fetches it from its controller, which fetches it from the view it loaded.

    So the last line of all my applications is always:
    PHP Code:
    $fc->getCommand()->getController()->getView()->display(); 
    Comments, ideas?

  19. #19
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DarkAngelBGE
    - The View accesses the model and tells it to fetch some data. The View accesses this data and loads a template based on criteria that is met by the data (i.e. there me a default error template and then some).
    You see, telling a model to fetch data isn't, to me, presentation logic, which is why it should be done by the controller. Also, a benefit of having the controller load the data is that the controller could pick the view to use based on a value the model returns; like a success and an error page, for example.

  20. #20
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm getting a bit behind in this topic but...

    Quote Originally Posted by DarkAngelBGE
    But then again if you have a PDFView and a HtmlView of some text that is stored in the database, both Views would include the same code for telling the model to fetch the data. Isn't that Code Repition?
    Actually it's just the reverse. The same data-collection code is re-usable with any kind of template.

  21. #21
    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)
    As for the FC, I have a ChainOfResposibility with one or more RequestMappers. Each RequestMapper may have different strategies for selecting a proper Controller, or it may fall thru to the next in the chain, if it doesn't find a match.

    PHP Code:
    $ac =& InputController::getInstance();
    $ac->addMapper(new RequestMapper_ActionRequestMapper()); // maps to a command (action)
    $ac->addMapper(new RequestMapper_ServerPageRequestMapper()); // maps directly to a serverpage (dispatcherview)
    $ac->addMapper(new RequestMapper_DefaultRequestMapper('404.php')); // default sink
    $ac->execute(); 
    As DarkAngelBGE points out, it doesn't matter much, but I could have substituted each mapper with a handle (WACT-style Handle). I like it without though, since it makes the code more clear, and it's a matter of very few clockcycles anyway.

  22. #22
    SitePoint Wizard
    Join Date
    May 2003
    Location
    Berlin, Germany
    Posts
    1,829
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here is some code example of mine..the way I deal with controller and views.

    Here the controller:

    PHP Code:
    <?php
    /**
     * Author: Tim Koschützki
     * Date Started: April 7th, 2005
    */
    require_once('IssueController.php');

    class 
    DeleteIssueController extends IssueController {
        public function 
    DeleteIssueController (&$dao,$input=null) {
            
    parent::__construct($dao$input);
        }
        public function 
    execute() {    
            if(!isset(
    $this->input['submit'])) {
                require_once(
    ISSUE_VIEW_PATH.'DeleteIssueItemView.php');
                
    $this->setView(new DeleteIssueItemView($this->model$this->lang$this->input['id']));
            } else {
                
    $success=0;
                if(
    $this->model->deleteIssue($this->input['id'])) {
                    
    $success=1;
                } 
                
                require_once(
    ISSUE_VIEW_PATH.'IssueItemHasBeenDeletedView.php');
                
    $this->setView(new IssueItemHasBeenDeletedView($this->model$this->lang$success));
            }
        }
    }

    ?>
    And here both views used:

    PHP Code:
    <?php
    /**
     * Author: Tim Koschützki
     * Date Started: April 7th, 2005
    */
    require_once(LIB_PATH.'Template.php');
    require_once(
    'IssueView.php');

    class 
    IssueHasBeenDeletedView extends IssueView {
        
    /**
        * Private
        * $success Did the deleting work alright?
        */
        
    private $success;
        
        
    //! A constructor.
        /**
        * Constucts a new IssueItemView object
        * @param $model an instance of the IssueModel class
        */
        
    public function __construct(&$model,&$lang,$success) {
            
    parent::__construct(&$model,&$lang);
            
    $this->success=$success;
        }

        
    //! A manipulator
        /**
        * Renders a single issue
        * @return void
        */
        
    private function deleteIssueItem() {   
            if(
    $this->success)) {
                
    $tmp =& new Template('issue_deleted');
                
    $tmp->setValue('{TITLE}',$this->lang->$deleteSuccessHeading);
                
    $tmp->setValue('{CONTENT}',$this->lang->$deleteSuccessText); 
            } else {
                
    $tmp =& new Template('error_page');
                
    $tmp->setValue('{TITLE}',$this->lang->$deleteFailureHeading);
                
    $tmp->setValue('{CONTENT}',$this->lang->$deleteFailureText); 
            }
                    
            
    $tmp->parse();
            return 
    $tmp->fetch();
        }

        public function 
    display () {
            
    $tmp =& new Template('standard');    
            
    $tmp->setValue('{HEADER}',$this->header());
            
    $tmp->setValue('{FOOTER}',$this->footer());
            
    $tmp->setValue('{NAVBAR}',$this->navbar());
            
    $tmp->setValue('{CONTENT}',$this->deleteIssueItem());
            
    $tmp->parse();
            return 
    $tmp->fetch();
        }
    }

    ?>
    PHP Code:
    <?php
    /**
     * Author: Tim Koschützki
     * Date Started: April 7th, 2005
    */
    require_once(LIB_PATH.'Template.php');
    require_once(
    'IssueView.php');

    class 
    DeleteIssueView extends IssueView {
        
    /**
        * Private
        * $issueID ID of issue to delete
        */
        
    private $issueID;

        
    //! A constructor.
        /**
        * Constucts a new IssueItemView object
        * @param $model an instance of the IssueModel class
        */
        
    public function __construct(&$model,&$lang,$issueID) {
            
    parent::__construct(&$model,&$lang);
            
    $this->issueID=$issueID;
        }

        
    //! A manipulator
        /**
        * Renders a single issue
        * @return void
        */
        
    pruvate function deleteIssueItem() {   
            
    $this->model->listIssue($this->issueID);               
            
    $issue=$this->model->getIssue();

            
    $tmp =& new Template('delete_issue_confirm');        
            
    $tmp->setValue('{ISSUE_ID}',$this->issueID);
            
    $tmp->setValue('{ISSUE_TITLE}' => $issue['title']);
            
            
    $tmp->parse();
            return 
    $issueTemplate->fetch();
        }

        public function 
    display () {
            
    $tmp =& new Template('standard');    
            
    $tmp->setValue('{HEADER}',$this->header());
            
    $tmp->setValue('{FOOTER}',$this->footer());
            
    $tmp->setValue('{NAVBAR}',$this->navbar());
            
    $tmp->setValue('{CONTENT}',$this->deleteIssueItem()); 
            
    $tmp->parse();
            return 
    $tmp->fetch();
        }
    }

    ?>

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

    Not being negative, but I can remember in one thread, that you posted your Dictionary, and one or more members referred to it as being bloated?

    I don't use a Dictionary, so I didn't comment at the time as I wasn't in the position to do so, but I'd be interested in knowing if you've refactored it since then?

  24. #24
    SitePoint Wizard
    Join Date
    May 2003
    Location
    Berlin, Germany
    Posts
    1,829
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well, didn't follow that thread anymore for some unknown reason. However, I didn't refactor it yet. Probably the comments were due to me storing the actual objects in it already, instead of storing only some sort of identifying strings and leave it to the FC to require the necessary class and instantiate it.

    Well I might refactor it. Here it is again, for others to comment as well:

    PHP Code:
    <?php
    /**
     * Author: Tim Koschützki
     * Date Started: April 14th, 2005
    */
    class CommandDictionary {
        private 
    $commands;
        
        public function 
    isListed($name) {
            foreach(
    $this->commands as $command) {
                if(
    $name == $command->getName()) {
                    return 
    true;
                }
            }
            
            return 
    false;
        }
        
        public function 
    addCommand(&$command) {
            
    $this->commands[] = &$command;
        }
        
        public function 
    getCommand($name) {
            foreach(
    $this->commands as $command) {
                if(
    $name == $command->getName()) {
                    return 
    $command;
                }
            }
            
            return 
    null;
        }
    }
    ?>
    Before loading the FC, populated the Dic:

    PHP Code:
    // parse input data
    require_once(LIB_PATH.'class.Request.php');
    $request =& new Request();
    $INPUT $request->parse();

    // get a Command Dictionary
    require_once(LIB_PATH.'class.CommandDictionary.php');
    $cmdDic =& new CommandDictionary;

    // declare our commands and insert them into our command directory
    require_once(LIB_PATH.'class.Command.php');

    // start a front controller
    require_once(LIB_PATH.'class.FrontController.php');
    $fc=& new FrontController($INPUT['action']);

    // Populate our Command Dictionary based on whether we are viewing the admin panel or not
    if( isset($INPUT['admin']) && $INPUT['admin'] == ) {
        
    $cmd =& new Command('insert_issue');
        require_once(
    ISSUE_CONTROLLER_PATH.'class.InsertIssueController.php');
        
    $cmd->addController(new InsertIssueController($dao$INPUT));
        
    $cmdDic->addCommand($cmd);


        
    $cmd =& new Command('edit_issue');
        require_once(
    ISSUE_CONTROLLER_PATH.'class.EditIssueController.php');
        
    $cmd->addController(new EditIssueController($dao$INPUT));
        
    $cmdDic->addCommand($cmd);


        
    $cmd =& new Command('delete_issue');
        require_once(
    ISSUE_CONTROLLER_PATH.'class.DeleteIssueController.php');
        
    $cmd->addController(new DeleteIssueController($dao$INPUT));
        
    $cmdDic->addCommand($cmd);

        
    // default page is insert issue page
        
    if(!isset($INPUT['action'])) {
            
    $INPUT['action'] = 'insert_issue';
        }
        
        
    // add the user authentication filter to the FC
        
    require_once(FILTER_PATH.'class.UserAuthenticationFilter.php');
        
    $fc->addFilter(new UserAuthenticationFilter());
    } else { 
    // Public Interface
        
    $cmd =& new Command('view_issue');
        require_once(
    ISSUE_CONTROLLER_PATH.'class.ViewIssueController.php');
        
    $cmd->addController(new ViewIssueController($dao$INPUT));
        
    $cmdDic->addCommand($cmd);

        
    $cmd =& new Command('view_archive');
        require_once(
    ISSUE_CONTROLLER_PATH.'class.ViewArchiveController.php');
        
    $cmd->addController(new ViewArchiveController($dao$INPUT));
        
    $cmdDic->addCommand($cmd);


        
    // default page is view archive page
        
    if(!isset($INPUT['action'])) {
            
    $INPUT['action'] = 'view_archive';
        }
    }

    // pass our command directory to the fc
    $fc->addCmdDic($cmdDic);
    $fc->run();
    $output=$fc->fetchOutput(); 
    Here one sees that I populate the Dictionary differently depending on whether the Admin Panel is wanted to be seen or not.

  25. #25
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DarkAngelBGE
    Degrees, did you look at the code samples I posted above? What do you think of them?
    Yes, here's what I would do:

    In the controller

    PHP Code:
    <?php
    /**
    * Author: Tim Koschützki
    * Date Started: April 7th, 2005
    */
    require_once('IssueController.php');

    class 
    DeleteIssueController extends IssueController {
        public function 
    DeleteIssueController (&$dao,$input=null) {
            
    parent::__construct($dao$input);
        }
        public function 
    execute() {    
            if(!isset(
    $this->input['submit'])) {
                require_once(
    ISSUE_VIEW_PATH.'DeleteIssueItemView.php');
                
    $this->model->listIssue($this->input['id']);
                
    $this->setView(new DeleteIssueItemView($this->model$this->lang));
            } else {
                
    $success=0;
                if(
    $this->model->deleteIssue($this->input['id'])) {
                    
    $success=1;
                }
                
                require_once(
    ISSUE_VIEW_PATH.'IssueItemHasBeenDeletedView.php');
                
    $this->setView(new IssueItemHasBeenDeletedView($this->model$this->lang$success));
            }
        }
    }

    ?>
    And for the view

    PHP Code:
    <?php
    /**
    * Author: Tim Koschützki
    * Date Started: April 7th, 2005
    */
    require_once(LIB_PATH.'Template.php');
    require_once(
    'IssueView.php');

    class 
    DeleteIssueView extends IssueView {

        
    //! A constructor.
        /**
        * Constucts a new IssueItemView object
        * @param $model an instance of the IssueModel class
        */
        
    public function __construct(&$model,&$lang) {
            
    parent::__construct(&$model,&$lang);

        }

        
    //! A manipulator
        /**
        * Renders a single issue
        * @return void
        */
        
    private function deleteIssueItem() {   
            
    $tmp =& new Template('delete_issue_confirm');        
            
    $tmp->setValue('{ISSUE_ID}',$this->model->ID);
            
    $tmp->setValue('{ISSUE_TITLE}' => $issue['title']);
            
            
    $tmp->parse();
            return 
    $issueTemplate->fetch();
        }

        public function 
    display () {
            
    $tmp =& new Template('standard');    
            
    $tmp->setValue('{HEADER}',$this->header());
            
    $tmp->setValue('{FOOTER}',$this->footer());
            
    $tmp->setValue('{NAVBAR}',$this->navbar());
            
    $tmp->setValue('{CONTENT}',$this->deleteIssueItem());
            
    $tmp->parse();
            return 
    $tmp->fetch();
        }
    }

    ?>
    The model->listIssue() command is now in the controller, which is where I feel it belongs, and which is incidentally where you had placed the model->deleteIssue(); both commands manipulate the model in some way, and that's why they belong the controller.

    Also, since the model already contains the data the ID of the item to be deleted, there's no longer any need for the controller to pass it seperately and for the view to store it.

    Other than that, it looks good to me!


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
  •