SitePoint Sponsor

User Tag List

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

    My take on MVC / Webapplication Pattern - Feedback

    After much reading, asking questions on forums and question marks, this is my conclusion of what MVC (or well, a version of MVC adopted for the web) is.

    This feels like a pretty decent design and I would just like your comments on it.
    (Now I'll stop posting more useless threads on this great, great, great forum - the best I've ever had the pleasure to write/read on)

    What have I done wrong/right? Am I an heretic for putting Interceptingfilters between the Controller and the Action(Model) ?

    Is it correct for one action upon failure "throw" another action at the Controller?
    Attached Images Attached Images

  2. #2
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Looks like a pretty good take on it to me.

    I consider Actions to be a part of the controller myself. In my mind, this is becuase the way I write them they are pretty much glue between the HTTP request and my Model.

    When I developed Phrame based applications, showing a view was just a particular Action where the response was HTTP containing HTML rather than and HTTP response containing a redirect. This did not accomodate filterers or action chains, which you appear to have in your diagram however.

    Looks good in concept, perhaps you would be willing to share some code one you have kicked the tires on it.

    Regards,
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  3. #3
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by sweatje
    I consider Actions to be a part of the controller myself. In my mind, this is becuase the way I write them they are pretty much glue between the HTTP request and my Model.
    Where is your model if it's not the actions executed by the controller?

    I like to have the seperation between action and view because that let's me plug different views(Flash,XHTML,etc) on the same action. (for example, running "UserListAction" which (if successfull ofc.) renders a UserListView that could either be an XHTML Table or a Flash Movie. I looked some at Phrame but I can't seem to get it to run under PHP5? It looks realy solid to me.

    With the Action chains, I got something like this in mind: One action, if it fails it doesn't redirect the user thru a new header('location: index.php?action=UserListFailed), it just "tells" the controller that the action was unsuccessfull and also sends the name of the Action to be tried next instead).

    What do you think about the Sitewide and the Action specific Intercepting Filters? Does this break the MVC by bleeding down for example _POST (for logins) or _SESSION (for authentication) from the controller down to the model? Or is it a good way to deal with a bleeding that is unavoidable?

  4. #4
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I like it as well but I'm pondering on #10 myself? Wouldn't the Controller part decide to carry out another action if the requested action is illegal (for example)... The action has only to decide the view (to me anyways?) based on the model, maybe your on the right tracks, I don't know without seeing some script

    it just "tells" the controller that the action was unsuccessfull and also sends the name of the Action to be tried next instead
    On this point you want nested (child) controllers/actions yes? WACT has implemented this I believe, but it's a Chain of Responsibility at the heart of it

    Has Phrame been upgraded to work with PHP5 yes? Been a while since I visited the web site, other than that I'd welcome some example script as well

  5. #5
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    I like it as well but I'm pondering on #10 myself? Wouldn't the Controller part decide to carry out another action if the requested action is illegal (for example)... The action has only to decide the view (to me anyways?) based on the model, maybe your on the right tracks, I don't know without seeing some script
    Well, #10 is basicly an "illustration" of what happends. If the action fails, another action is carried out. I have two ideas on how to solve this:

    * Specify it in the mapping(php array, like phrame does) what to do and let the controller look up what action to take instead
    * Let the action redirect a new request to the controller

    Quote Originally Posted by Dr Livingston
    On this point you want nested (child) controllers/actions yes? WACT has implemented this I believe, but it's a Chain of Responsibility at the heart of it
    Well, yes and no. The action fails because it can't preform the request operation for some reason, this leaves me with just doing die() - which is not realy what I want - or in some manner get another action to be performed. But it's not realy a Chain of Respnosibility - or am I wrong?

    Quote Originally Posted by Dr Livingston
    Has Phrame been upgraded to work with PHP5 yes? Been a while since I visited the web site, other than that I'd welcome some example script as well
    Nope, well.. I can't get it to work with PHP5, it tries to call a load of php4-specific stuff also(the old xml api for example)


    Edit: Just to clear one thing up, I'm not after the most perfect implementation of MVC that adhears(spelling?) to the pattern/paradigm perfectly - I wan't a version of MVC that seems to work good with the mechanics of how a webapplication with PHP is built.

    Edit #2: Sorry for my crappy spelling, I'm on a laptop and I keep hitting the wrong(or two at a time) keys all the time.

  6. #6
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    After some hasty codeing I got this very very very very(etc.) basic example of how I want it to work. Let me just say a couple of things about the code, that I want you to have in mind when you give suggestions/critizie it/comment it:

    * It was written in aprox ~2 hours (Try to write a working MVC implementation like Phrame in 2 hours =P)
    * I only wrote it to get a basic idea of what I wanted
    * I didn't care for anything except trying to get an extremely basic model out, so there are no constants for php-extensions,etc. There is no config file for the main application, all searchpaths are hardcoded in the "application"(almost a shame to call it that), etc.
    * I got no real idea on how to implement the Pre/Post Filters yet so I skipped those
    * Most of the methodnames, classnames, mappingnames, etc. are just put there to have something to refer to.. they are not and will not be final =p. If I ever go thru with the plan of acutally building something like Pharme i'll start from scratch.
    Attached Files Attached Files
    Last edited by thr; Feb 6, 2005 at 03:58.

  7. #7
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here is the way I look at it.
    Attached Images Attached Images

  8. #8
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Selkirk: How do you take care of, for example authentication that could go as intercepting filters but are only needed for specific pages?

    Isn't the Action you want executed your model?

    The RequestObjects, etc. should probably be moved down to the controller and not used in the strange "HTTPRequest"-class I put in there last night tho.

    The reason I like Action/Model-Specific Intercepting Filters(even if they do break some of the layering) is that you can put - for example authentication on the pages that need it without to much of a hassle.

    I think there should be some way for the Action/Model to request another action upon failure - So that you don't have to throw a header('location index.php?action=FailedACtion'); at the client and cause loads of new transfer between the client and server.

    Edit: This laptop keyboard is driving me nuts o.O

  9. #9
    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 thr
    The reason I like Action/Model-Specific Intercepting Filters(even if they do break some of the layering) is that you can put - for example authentication on the pages that need it without to much of a hassle.
    You wouldn't normally see something called InterceptingFilter at the "action" level (it's meant to wrap the entire application) but it is just a form of ChainOfResponsibility and chains can be useful anywhere. ActionFilterChain might be a better name.

    You can pop loosely-coupled objects in and out of a chain on different pages if you make it configurable. Somehow, somewhere, you'll need to map a request parameter (like "viewtopic") to a list of filters.

    However, I think authentication might be a task for an InterceptingFilter rather than an ActionFilterChain. I think it could help to think carefully about the different roles of things you are adding to your chains and figure out if they belong together or not (I like to have a separate request-handling chain) and whether they are better at the action level or an application wrapper level.

  10. #10
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    McGruff: If I move the "Action Intercepting Filters" to the "real Intercepting Filters", How would i switch them out between different actions?(Some actions need authentication, some need logging, etc.)

    Should I have one config for sitewide Inctercepting Filters and one for those that should be run depending on what Action is requested ?

  11. #11
    SitePoint Enthusiast
    Join Date
    Sep 2004
    Location
    S. Florida, USA
    Posts
    60
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by thr
    How do you take care of, for example authentication that could go as intercepting filters but are only needed for specific pages?

    --snip--

    I think there should be some way for the Action/Model to request another action upon failure - So that you don't have to throw a header('location index.php?action=FailedACtion'); at the client and cause loads of new transfer between the client and server.

    Im still new to this, but this is the idea I've come up with over these past few months.
    1. index.php executes filtermanager
    2. filtermanager executes *global* application filters
    3. The last *global* filter is the bootstrap filter which looks at the request and determines which action to execute, and any additional *action* specific filters to run (can be viewed as a FC??).
    4. filtermanager appends *action* specific filters to filter list and executes them.
    5. At the end of the *action* specific filters, execute the action.

    This way, I can use, for example, the authentication filter for specific pages.
    Sorry, no code or uml. Its my job today, to get back up to speed with svn, and I need to update my uml diagrams

  12. #12
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    trini0: That's the idea I've been thinking about today to, and I realy love your idea about a "bootstrap" filter.

    But we need to be able to put POST filters in the application to, and what if a action fails? We would need to load another one action, with it's specific filters. How should this be taken care of? (not flaming, just thinking out loud and trying to get a better idea of what we need)

  13. #13
    SitePoint Enthusiast
    Join Date
    Sep 2004
    Location
    S. Florida, USA
    Posts
    60
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by thr
    trini0: That's the idea I've been thinking about today to, and I realy love your idea about a "bootstrap" filter.

    But we need to be able to put POST filters in the application to, and what if a action fails? We would need to load another one action, with it's specific filters. How should this be taken care of? (not flaming, just thinking out loud and trying to get a better idea of what we need)
    No problem about the critical thinking.
    If Im understanding you correctly, with the idea I gave above, you can have
    *action* specific filters between the *bootstrap* filter and the actual action class.
    These filters are specific to the action, so you can do your POST filtering there???
    And if an error occurs, do a server side redirect to somewhere else.
    As far as an error occuring in the action class, for me, with what I
    have, its not possible to do a server side redirect in the action.

    With what Im working with right now, for every page, Im maintaining 2 filter lists.
    One for *global* filters, and one for *action* filters.

  14. #14
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Trini0: Yes, but how would the "bail out" method look for the actions/actionfilters? Because I realy dont want to throw a header('location: ....'); at the client. As far as I'm concerned, there should be SOME way for the Action to tell the controller to take another action instead.

  15. #15
    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 thr
    Should I have one config for sitewide Inctercepting Filters and one for those that should be run depending on what Action is requested ?
    Yes. With a FrontController you might use some kind of configuration file to define InterceptingFilter candidates - or they could be hard-coded in a PageController. I'm trying to think what action-level filters there might be (output filters for different formats possibly?) but I might have misunderstood what you mean by Action. I tend to think of actions as items in a "to do list" executed in response to a request.

    First, you have to decide how to handle the request for example is the user authenticated, is the user input in a valid form, and so on. That's what I would call request-handling logic. A lot of this is shared between different requests and so an InterceptingFilter can be a good place to put it (avoiding lots of copy-pasting is one of the forces for the pattern). By the time you get down to "actions" all the decisions - which actions to carry out in response to the request - have been made.

    One way to do this is with a strict GoF ChainOfResponsibility. This is slightly different to InterceptingFilter in that only one "filter" is ever active (it's just a switch/case, with classes). In the chain are a bunch of handlers. Each tries to handle the request, in turn, and if it can't the next one has a go. You'd want some kind of default handler at the end to catch anything which wasn't picked up by any of the others, and some handlers might need to rollback if they don't find out that they're unable to carry out all of their actions until they are half way through them.

    FooRequestSyntax --> FooHandler --> Handler404

    FooRequestSyntax knows what form GPC should be in for the "foo" request. It wants to dump the user into a 400 "bad request syntax" page if it can. If it can't (user input is valid), control passes to the FooHandler. FooHandler tries to create the foo client page and maybe an email or a log or two. If it can't, the final 404 handler will sweep up.

    The key to CoR is that the items in the chain are loosely-coupled. That lets you swap items in and out easily. For example, you could stick authentication and authorisation handlers in there to restrict access to the foo page. Authentication would want to send a login page but fails if the user can be identified. An authorisation handler might try to send a 403 page but fails if the user is authorised for "foo".

    InterceptingFilter works the same way except that a whole bunch of other stuff is mixed up in there as well, and everything is called a "filter". This is, I think, confusing until you figure out the word has many meanings here. My refactoring alarm beeps whenever I think about it but maybe it should be viewed more as a layer rather than having a specific job to do.

  16. #16
    SitePoint Enthusiast
    Join Date
    Sep 2004
    Location
    S. Florida, USA
    Posts
    60
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by thr
    Trini0: Yes, but how would the "bail out" method look for the actions/actionfilters? Because I realy dont want to throw a header('location: ....'); at the client. As far as I'm concerned, there should be SOME way for the Action to tell the controller to take another action instead.
    Im not sure if you're understanding what Im saying above (or me understanding you).
    To make things clear.
    1. Server Side redirect does not use header().
    2. Client side redirect does use header().
    3. In the code Im using, the intercepting filters use server side redirect.
    I briefly talked about them here.
    Since (for us, or at least me), actions are dictated by a variable passed in the url,
    when I need to do a server side redirect, I manually change the value of this $_GET variable, and restart the intercepting filter processing (server side redirect).
    For example, if the current request value of $_GET['command'] = 'showForm', I change it to $_GET['command'] = 'error404', and restart filter processing within the same request.
    That way, the action "error404" is displayed instead of "showForm".
    4. As far as my code, what is described in item 3, cannot be done in the action classes (there may be a way, but I'll see).

    To hopefully explain further, take a look at
    http://www.trini0.org/
    You'll notice, that Im echoing content around the html table.
    That echoed content are the filters at work (its just a visual aid for me).
    http://www.trini0.org/ is a normal page load
    http://www.trini0.org/index.php?cmd=foo_bar shows it doing a server side redirect because it couldn't find $_GET['command']
    http://www.trini0.org/index.php?command=foo_bar shows a server side redirect (this simulates what happens during an action filter server side redirect)

    In these examples, Im not using header(), but resetting the $_GET['command'] variable and restarting filter processing.
    Hopefully in the next day or so, I'll be putting the code into svn, if you want you can review it, and see if you can adapt it to your needs (and maybe get an idea on if its possible to do a server side redirect in action classes).

  17. #17
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    McGruff: Thanks for the great feedback, here comes my response(mostly questions, but anyways).

    Quote Originally Posted by McGruff
    Yes. With a FrontController you might use some kind of configuration file to define InterceptingFilter candidates - or they could be hard-coded in a PageController. I'm trying to think what action-level filters there might be (output filters for different formats possibly?) but I might have misunderstood what you mean by Action. I tend to think of actions as items in a "to do list" executed in response to a request.
    By an action I mean something a user requests from the applications(maybee action is the wrong term). For example, a user could request the: "Inbox" action thru "index.php?action=Inbox" which would show the user(if successfully authenticated, etc.) his inbox in a webmail.

    Quote Originally Posted by McGruff
    First, you have to decide how to handle the request for example is the user authenticated, is the user input in a valid form, and so on. That's what I would call request-handling logic. A lot of this is shared between different requests and so an InterceptingFilter can be a good place to put it (avoiding lots of copy-pasting is one of the forces for the pattern). By the time you get down to "actions" all the decisions - which actions to carry out in response to the request - have been made.
    This is the problem I face at the moment - How do I do the actually decideing? For example our "Inbox" action requires the user to be authenticated with a correct email and password. Since all pages does not require this authentication (for example, the page where you login does not require authentication). Where should I put this? In a seperate Intercepting Filter(I'm also starting to see these as a seperate layer) that is mapped to some specific actions?

    About the CoR, it something like this I want to achieve - but probably not *exactly* that.

  18. #18
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    trini0:

    Ah, yes.. I quite missunderstood you there - sorry. What I'm interrested in is how do you perform the actuall serverside redirect? I've been thinking about something like a while(true) loop that goes over and over untill you get a valid response and then break; it?

    The thing that I want to achive is for the action classed to be able to bail out of them selves - for example if I get the UserListAction required which includes getting stuff from a database(for example mysql) or some other persistent storage(file,etc.) but the connection to the database/storage fails? Where should the action go? It can't complete itself. This is where I wan't some type of "bail out" functionallity. Or should the action itself just return false and the the controller should look at the mapping on what to do next?

  19. #19
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I made a new image/diagram over the flow of the application, I also made comments on two of the problems(as I see it) in the diagram - please check it out and comment it.


    Edit #1:
    trini0: How do you handle the mapping between the actions,filters, etc. ?
    Attached Images Attached Images
    Last edited by thr; Feb 6, 2005 at 13:34.

  20. #20
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This is on of those examples where patterns clarify and confuse me. Here is how I think of the phases execution of a PHP page. Please

    1. Run any code that is needed for all pages in this site or group of pages. This is usually creating the common objects used by the system. For example a Request object might check if magic_quotes is on an add slashes accordingly, or object like DB Connector, Validator, Filter, etc. are created. Any configuration data is setup here too. This can all be hard coded in the global scope, added to a chain and executed, or both.

    2. Then, if there is a FrontController, it checks the request to see if an action is specified. If no action then a default action is selected. Then either the specified or default action is executed.

    3. The action executed is a controller, whether in an informal sense (like most PHP pages) or formally. If it is a "formal" controller then it is a PageController, or some special purpose child of a PageController such as a FormController, UploadController, etc.

    4. The PageController might first do some initialization that is specific to this page, such as checking Access Control or loading page specific configuration data. The phase is in some ways analogous to the the Phase #1 step but is page specific.

    5. The PageController creates one or more objects to access the data for this page. This is referred to as the Model, but could be anything from a RecordSet to a full ORM system.

    6. The output gets rendered using data from the Model. In formal MVC, this is a View object and the Model is passed to the View (enforcing that the Model does not know about the View). In a simple system it could just be iterating through a RecordSet and generating the output directly or though a Template system.

    7.Output (response) is sent back to the user. This could happen directly in the View, or often later as the PageController or FrontController finish up.

    I usually have the same questions about how to implement this scheme:

    A. Do you implement it as one big chain in the InterceptingFilter style? Or do you implement an InterceptingFilter chain before the Controllers and then have the controller take over running things?

    B. Does the Controller simply create a Model and View and pass the Model to the View? Or, do you implement an ActionChain within the Controllers so that you can keep adding actions and components as necessary for the page or allow the chain to be cleared for errors and “in controller redirects” ?

    How do different people implement MVC and what are the tradeoffs in the choices?
    Christopher

  21. #21
    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 thr
    By an action I mean something a user requests from the applications(maybee action is the wrong term). For example, a user could request the: "Inbox" action thru "index.php?action=Inbox" which would show the user(if successfully authenticated, etc.) his inbox in a webmail.
    OK. An action could be something the user does - like clicking a link or button - or it could refer to something the server app does. At the server end, I think you are using "action" to describe the script as a whole rather than (as I tend to) individual tasks within a response (which you can break down ad infinitum).

    Server actions do not always map one to one with requests (in fact they probably never should). A single request might have a range of possible outcomes in terms of what actions are taken by the app. There could be several client pages associated with a single request and various non-client options such as emails and logs (I think you've got all that).

    Quote Originally Posted by thr
    How do I do the actually decideing?
    This is the ApplicationController pattern "a centralised point for handling screen navigation and the flow of an application" ((Fowler)). If you have a wizard style interface where a series of pages are shown in a particular order, or choice of page depends on the state of something or other (eg an authentication check leading either to a login page or to the page requested) then it's good to have a discrete part of the design responsible for this.

    If you don't you don't need one - except I can't think of a case where you don't. The simplest dynamic page I can imagine is the foo request example, above. Even here clients won't necessarily get the page they asked for: bad input might have been submitted or a connection to the db server might be unavailable.

    I hope I'm not "doing a Tony" here, but the best way I can think to implement an ApplicationController is with a ChainOfResponsibility. Requests map one-to-one with chains. Chains are configurable. 99% of the time client pages map one-to-one with handlers in the chain - add a handler for each of your possible "actions".

    I'm guessing that your problem has arisen with form submissions. A request handling chain for a form submission might look like this:

    BadRequestSyntax --> RedisplayHandler --> ProcessForm -->404 handler

    Each handler has only one job to do. The redisplay handler will redisplay the form if the submission has invalid or missing values, if not, it does nothing at all and control passes to the ProcessForm handler. And so on.

    There's a subtle difference between bad request syntax and invalid form submissions. Although both examine user input, the redisplay handler only looks at submission values in either GET or POST (depending on the form action). Bad request syntax performs wider checks on all of GPC. As a brief example, a missing required key outside of a form a submission could indicate tampering but a missing key in the form submission just means the user forgot to enter a value. Checking request syntax is basically a security check - kind of a firewall for the app - rather than a form validation check where you just want to know if the submission can be processed. Different logic, different actions to take, hence a different handler.

    If access is restricted, you'd add:

    BadRequestSyntax --> AuthenticationHandler --> AuthorisationHandler --> RedisplayHandler --> ProcessForm -->404 handler

    In this case, AuthenticationHandler maps to a login page and AuthorisationHandler maps to a 403 page. However, if the user can be authenticated and is authorised, they don't do anything at all.

    A CoR splits everything up nicely. Request-handling logic (ApplicationController) is refactored out of InterceptingFilter / FrontController / PageController. PageControllers for example are redefined slightly and now map one-to-one with client pages. Requests map one-to-one with specific chain configurations (ApplicationControllers) rather than PageControllers. InterceptingFilter looks a whole lot more cohesive without any request-handling logic.

    To make chains configurable per request type, one option is to use ini files named after a request var. You'd probably be using a FrontController setup to map requests to chains although you don't have to.

    The most basic implementation of an ApplicationController is a simple switch case and you'll often see it implemented exactly like that (not that I'd recommend it).

  22. #22
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    My problem with sayng ChainOfResponsibility is that there are two different things refered to as ChainOfResponsibility. The traditional sense is a chain that goes along until it finds a node that will "take responsibility" for the event. Then it has this other meaning that is really a "ChainOfExecution" where you each node in the chain is executed sequentially, but there is no responsibility.

    I think an InterceptingFilter and ChainOfResponsibility are related, but as the name says InterceptingFilter is really for applying filters to something and passing it on the possibly more filters.

    So what is the real difference between InputController->ApplicationController and FrontController->PageController? I really don't know and for web apps I'm not sure there is a difference.

    One thought, as the ApplicationController is often mentioned for wizards. In web apps that would usually be a sequence of related forms. Perhaps an ApplicationController in a web app goes in front of a PageController for sequences of pages:

    SINGLE PAGE
    FrontController->PageController

    SINGLE FORM
    FrontController->FormController (extends PageController)

    PAGE SEQUENCE
    FrontController->ApplicationController->PageControllers

    In that case the ApplicationController should really be renamed to something like PageSequenceController.

    I agree that "requests map one-to-one with specific chain configurations" but the question is what builds the "specific chain configuration." I don't think the big INI file maps are a good idea with PHP. That leaves it to each PageController to build the "specific chain configuration." That fortunately and unfortunately distributes the map out to the controllers for each action. Perhaps some sort of build tool could build all of the controllers from a build-time map?
    Christopher

  23. #23
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by McGruff
    OK. An action could be something the user does - like clicking a link or button - or it could refer to something the server app does. At the server end, I think you are using "action" to describe the script as a whole rather than (as I tend to) individual tasks within a response (which you can break down ad infinitum).

    Server actions do not always map one to one with requests (in fact they probably never should). A single request might have a range of possible outcomes in terms of what actions are taken by the app. There could be several client pages associated with a single request and various non-client options such as emails and logs (I think you've got all that).
    Ah, I thought this is where I got it wrong - I considered action as the whole page, for example if the user requested the "Login"-Action that is the whole page that is displayed with the Login-form on it, is this "wrong" and how should I split up the action instead? And how do they relate/couple to the model?

    Quote Originally Posted by McGruff
    is the ApplicationController pattern "a centralised point for handling screen navigation and the flow of an application" ((Fowler)). If you have a wizard style interface where a series of pages are shown in a particular order, or choice of page depends on the state of something or other (eg an authentication check leading either to a login page or to the page requested) then it's good to have a discrete part of the design responsible for this.

    If you don't you don't need one - except I can't think of a case where you don't. The simplest dynamic page I can imagine is the foo request example, above. Even here clients won't necessarily get the page they asked for: bad input might have been submitted or a connection to the db server might be unavailable.

    I hope I'm not "doing a Tony" here, but the best way I can think to implement an ApplicationController is with a ChainOfResponsibility. Requests map one-to-one with chains. Chains are configurable. 99% of the time client pages map one-to-one with handlers in the chain - add a handler for each of your possible "actions".

    I'm guessing that your problem has arisen with form submissions. A request handling chain for a form submission might look like this:

    BadRequestSyntax --> RedisplayHandler --> ProcessForm -->404 handler

    Each handler has only one job to do. The redisplay handler will redisplay the form if the submission has invalid or missing values, if not, it does nothing at all and control passes to the ProcessForm handler. And so on.

    There's a subtle difference between bad request syntax and invalid form submissions. Although both examine user input, the redisplay handler only looks at submission values in either GET or POST (depending on the form action). Bad request syntax performs wider checks on all of GPC. As a brief example, a missing required key outside of a form a submission could indicate tampering but a missing key in the form submission just means the user forgot to enter a value. Checking request syntax is basically a security check - kind of a firewall for the app - rather than a form validation check where you just want to know if the submission can be processed. Different logic, different actions to take, hence a different handler.

    If access is restricted, you'd add:

    BadRequestSyntax --> AuthenticationHandler --> AuthorisationHandler --> RedisplayHandler --> ProcessForm -->404 handler

    In this case, AuthenticationHandler maps to a login page and AuthorisationHandler maps to a 403 page. However, if the user can be authenticated and is authorised, they don't do anything at all.
    I wouldn't be afraid of "doing a Tony" on this one, as it seems as a pretty good aproach? Maybee the name ApplicationControler should be switched out for ApplicationFlowController instead(or something with "flow" in it).


    Quote Originally Posted by arborint
    A. Do you implement it as one big chain in the InterceptingFilter style? Or do you implement an InterceptingFilter chain before the Controllers and then have the controller take over running things?

    B. Does the Controller simply create a Model and View and pass the Model to the View? Or, do you implement an ActionChain within the Controllers so that you can keep adding actions and components as necessary for the page or allow the chain to be cleared for errors and “in controller redirects” ?
    I tend to ask myself these questions all the time to. I'm starting to look more and more towards the CoR idea that McGruff came up with, as this lets you plug in/out piece of the application as you want, and the actually implementation of a CoR is pretty simple, basicly a FIFO-stack that has some logic around it.

    Quote Originally Posted by arborint
    My problem with sayng ChainOfResponsibility is that there are two different things refered to as ChainOfResponsibility. The traditional sense is a chain that goes along until it finds a node that will "take responsibility" for the event. Then it has this other meaning that is really a "ChainOfExecution" where you each node in the chain is executed sequentially, but there is no responsibility.

    I think an InterceptingFilter and ChainOfResponsibility are related, but as the name says InterceptingFilter is really for applying filters to something and passing it on the possibly more filters.
    As I see it, if the CoR is implemented as the core of the application, you could wrap intercepting filters around it for things that you do NOT need to plug in / out (Request Filters that clean up if magic_quotes_gpc == 1,session filters, etc.) - But this is just a thought, maybee it's out of line? I don't think the ChainOfExection-path is somewhere we should go, that basicly gives us another Incerpection Filter Chain.

    Quote Originally Posted by arborint
    One thought, as the ApplicationController is often mentioned for wizards. In web apps that would usually be a sequence of related forms. Perhaps an ApplicationController in a web app goes in front of a PageController for sequences of pages:

    SINGLE PAGE
    FrontController->PageController

    SINGLE FORM
    FrontController->FormController (extends PageController)

    PAGE SEQUENCE
    FrontController->ApplicationController->PageControllers
    I like this idea, having different Controllers depending on the purpose of the page - but then again, would this mess things up even more then they already are? (for example, a page with forms... but the forms are not requierd, etc.) ?

    Quote Originally Posted by arborint
    1. Run any code that is needed for all pages in this site or group of pages. This is usually creating the common objects used by the system. For example a Request object might check if magic_quotes is on an add slashes accordingly, or object like DB Connector, Validator, Filter, etc. are created. Any configuration data is setup here too. This can all be hard coded in the global scope, added to a chain and executed, or both.

    2. [...]

    3. [...]

    4. [...]

    5. [...]

    6. [...]

    7.Output (response) is sent back to the user. This could happen directly in the View, or often later as the PageController or FrontController finish up.
    I tend ot agree with this aproach, but I've been looking more and more into the idea of a CoR - as it seems like a pretty good aproach in terms of what is actually going on.

    An now, onto my conclussions/idea after your 3 excellent replys(hopeing for more :]) - a CoR with a Controller.


    1. The page get's request with the url of: index.php?action=ShowInbox I think the Inbox makes a quite good example(but maybe I'm lost again, I feel that an action is somewhat alike to what the user wants back after he clicked on the link)
    2. First the Chain of Responsibility gets set up, and it plugs the BadRequestHandler inside it that checks so our request has all the _GET/_POST/_COOKIE values needed.
    3. Assuming(in this case, so I can go on) that the Request is valid the Controller is the next filter to get run inside the CoR. The controller looks as the incomming request and checks the mapping to see if the action asked is valid and what other filters should go in the CoR.
    4. The next filter up is the session filter that starts the session and maybee plugs a custom more secure sessionhandler in, instead of the standard one?
    5. The other filters from the mappings are executed, in this case the next filter up is the AuthenticationFilter needed (we are showing an Inbox, we have to know what the Inbox to show).
    6. The next filter up in our example is the connection filters for databases/storages - we have to pull the email information from somewhere.
    7. Assuming everything is ok the actuall action is loaded up, and also the apropiate model is loaded.
    8. From here on it's self explenatory, the view get's put into the chain, the view is renderd, etc.

    (Filter is probably a bad name? is Handler a better name for what goes on inside the CoR?)

    Some questions on the flow i described above:
    * How would the mapping be handled?
    * Do we have to fill the chain completley before we start going thru it or can we put other objects in it as needed?(as I do in this example)

    Edit(Bah, I always come up with new stuff after I've posted): I realy like how Phrame handles the mappings, how they are translated into an object during runtime and then allows dynamic access to the different parts of the mapping and let the action itself have some part in what forward/action should be taken after it's been performed.

    Edit: And, again. Sorry for the crappy spelling.. I can't seem to get along with this stupid laptop keyboard :/

  24. #24
    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)
    Comming in to this discussion pretty late, but I will insist that the Action isn't part of the Model. It's part of the Controller, but it's the only part of the MVC-structure that actually has access to the Model (Not counting Filters, witch may also depend on the Model)

    I don't know - I may be repeating what has more or less already been said, but I just want to underline it.
    It seems to be a common problem, when discussing the MVC-pattern, that this pattern only describes one aspect of the entire application - namely the controlflow (or controller-oriented apects). In regards to the MVC-aspect, Model and View are just ressources.

  25. #25
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    Comming in to this discussion pretty late, but I will insist that the Action isn't part of the Model. It's part of the Controller, but it's the only part of the MVC-structure that actually has access to the Model (Not counting Filters, witch may also depend on the Model)

    I don't know - I may be repeating what has more or less already been said, but I just want to underline it.
    It seems to be a common problem, when discussing the MVC-pattern, that this pattern only describes one aspect of the entire application - namely the controlflow (or controller-oriented apects). In regards to the MVC-aspect, Model and View are just ressources.
    I guess this is something I got wrong - I sorted it out now. (Ie: the controller executes the action and the action executes the correct model(s) - hope I'm right).

    But I'm still very much into the idea of a CoR-type of applicationflow, which lets you stick other Handlers inside the CoR if one fail.


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
  •