> From: Bill Moseley [mailto:[EMAIL PROTECTED]] > Sent: 08 June 2002 20:48
> I've gone full circle on handling user input. I used to try to abstract > CGI input data into some type of request object that was then passed onto > the models. But then the code to create the request object ended up > needing to know too much about the model. > For example, say for a database query the controller can see that there's a > query parameter and thus knows to pass the request to the code that knows > how to query the database. That code passes back a results object which > then the controller can look at to decide if it should display the results, > a "no results" page and/or the query form again. So in pseudo code-speak, how about something like: # Note that I am ignoring Exceptions for the sake of dealing with the # Controller / Model interaction question. # $param is a ref to an Apache::Table that contains all the user submitted # parameters from the request. The main job of cleanupParams() is to do # things like URDDecode() etc, and marshal all the user input into a simple # structure. my $param = cleanupParams($r); # Instantiate Model. Pass it ALL user parameters - Model can cherry pick only # the ones it is interested in, and ignore the others. Adding new parameters # in the preceeding View that gave rise to this request makes no difference # to the Controller - only the Model and View needed to change. my $Model = My::Model->new( %$param ); # And which View should we instantiate? Well, you might choose one in the # Controller, but I only do this if there was a major Model meltdown. For # no result searches, the usual search View should be able to handle things # with a nice message. > Now, what happens is that features are added to the query code. Let's say > we get a brilliant idea that search results should be shown a page at a > time (or did Amazon patent that?). So now we want to pass in the query, > starting result, and the page size. As shown above, the Controller doesn't really care about any new parameters, it passes them all, including new ones through transparently to the model. The model I like for paginated results is straight-forward. When the Model is instantiated, it does NOT find a query_id field in the passed parameters, so it assumes a brand new query, and returns the first N results. A brand new, unique query_id is issued, and becomes a property of the Model. In the paginated View, this query_id is inserted into a hidden field (or cookied if you prefer). A session is created using the query_id that contains all of the parameters that the Model considers important. The paginated View contains First, Last, Next, Prev links that just call the same URL with an action=>next, last, prev etc. When the Model is instantiated for a subsequent page, it sees a query_id, loads all the query details in from the session storage, and retrieves the appropriate set of records for the this-time-round View. > What I didn't like about this is I then had to adjust the so-called > controller code that decoded the user input for my request object to > include these new features. But really that data was of only interest to > the model. So a change in the model forced a change in the controller. I think covered above? > So now I just have been passing in an object which has a param() method > (which, lately I've been using a CGI object instead of an Apache::Request) > so the model can have full access to all the user input. It bugs me a bit > because it feels like the model now has intimate access to the user input. I don't like this either, but probably need a concrete example of exactly what Request properties you find it necessary to use in your Model. The way I see it is that the Controller is interested in the gory details of the Request object, after all it is a Web Controller, but the Model should only be interested in the parameters. The Controller uses the Request object context, and sometimes basic parameters to decide which Model to instantiate, it doesn't care about Model parameter requirements - the Model must validate itself. > links back to a page, such as a link for "page next". I like to build > links in the view, keeping the HTML out of the model if possible. But > for something like a "page next" link that might contain a bunch of > parameters it would seem best to build href in the model that knows > about all those parameters. As described above, I like to use a session to store Model state over multiple executions / pagination of a collection type Model. Regards Jeff