How to pass form values to page that actually does something.
I'm quite frustrated with the Form API right now, so please forgive my tone. I've got a form that has a bunch of inputs, all of them multiselects, that allow the user to choose what classes to see in our schedule. (our class schedule is in an external database). I've got a bunch of code in the form_submit function that builds a very elaborate sql query to get the list of requested classes. Unfortunately, the form_submit function is not actually permitted to display anything except through drupal_set_message(). So I have to either pass my complicated sql query, or all the contents of the form fields to some other page through $form_state['redirect']. How do I do that without shoving it all into the querystring? Right now, I'm looking at the performance issues of: A: storing the query as a string in the database with a query_id, then sending a query_id in the redirect, B: storing the result of the query in the database with a result_id, then sending a result_id in the redirect. Is there some other way to accomplish what I want? p.s. I've looked at the search module, it basically shoves the form input into the querystring of the redirect. That'll work for a single input, but multiple array inputs will be a huge pain.
I like your option A. You can either store the SQL query string, or be a little more like the search module and store the relevant portion of $form_state['values'], and allow the code in the redirect page to build the query from that. In either case, you can make the query_id or input_id be the md5() of what you're storing. That way, multiple submissions with the same options (whether from the same person or from different people) don't flood the table with essentially duplicate records. And it allows the page to be more effectively page cached (i.e., a particular set of options always results in the same URL of the redirect page). Alex. Bayne, Sam wrote:
I'm quite frustrated with the Form API right now, so please forgive my tone.
I've got a form that has a bunch of inputs, all of them multiselects, that allow the user to choose what classes to see in our schedule. (our class schedule is in an external database). I've got a bunch of code in the form_submit function that builds a very elaborate sql query to get the list of requested classes.
Unfortunately, the form_submit function is not actually permitted to display anything except through drupal_set_message().
So I have to either pass my complicated sql query, or all the contents of the form fields to some other page through $form_state['redirect'].
How do I do that without shoving it all into the querystring?
Right now, I'm looking at the performance issues of:
A: storing the query as a string in the database with a query_id, then sending a query_id in the redirect, B: storing the result of the query in the database with a result_id, then sending a result_id in the redirect.
Is there some other way to accomplish what I want?
p.s. I've looked at the search module, it basically shoves the form input into the querystring of the redirect. That'll work for a single input, but multiple array inputs will be a huge pain.
We're doing testing with option A. The idea of using the md5 for query_id is a good one for saving space in the database, but we actually want to prevent caching on the client. That's why we went with option A in the first place. This also has opened up the idea of saving recent or favorite searches per user or session. In the meantime, we're timestamping the queries, and we can clear out old ones with cron. On May 10, 2010, at 9:52 AM, Alex Bronstein wrote:
I like your option A. You can either store the SQL query string, or be a little more like the search module and store the relevant portion of $form_state['values'], and allow the code in the redirect page to build the query from that.
In either case, you can make the query_id or input_id be the md5() of what you're storing. That way, multiple submissions with the same options (whether from the same person or from different people) don't flood the table with essentially duplicate records. And it allows the page to be more effectively page cached (i.e., a particular set of options always results in the same URL of the redirect page).
Alex.
Bayne, Sam wrote:
I'm quite frustrated with the Form API right now, so please forgive my tone.
I've got a form that has a bunch of inputs, all of them multiselects, that allow the user to choose what classes to see in our schedule. (our class schedule is in an external database). I've got a bunch of code in the form_submit function that builds a very elaborate sql query to get the list of requested classes.
Unfortunately, the form_submit function is not actually permitted to display anything except through drupal_set_message().
So I have to either pass my complicated sql query, or all the contents of the form fields to some other page through $form_state['redirect'].
How do I do that without shoving it all into the querystring?
Right now, I'm looking at the performance issues of:
A: storing the query as a string in the database with a query_id, then sending a query_id in the redirect, B: storing the result of the query in the database with a result_id, then sending a result_id in the redirect.
Is there some other way to accomplish what I want?
p.s. I've looked at the search module, it basically shoves the form input into the querystring of the redirect. That'll work for a single input, but multiple array inputs will be a huge pain.
On Mon, May 10, 2010 at 8:14 PM, Bayne, Sam <sbayne@sccd.ctc.edu> wrote:
We're doing testing with option A.
The idea of using the md5 for query_id is a good one for saving space in the database, but we actually want to prevent caching on the client. That's why we went with option A in the first place.
This also has opened up the idea of saving recent or favorite searches per user or session. In the meantime, we're timestamping the queries, and we can clear out old ones with cron.
A bunch of clarifications: - displaying results in a POST (on form submission) is just a bad idea. Don't do that, you should use GET. - if you really want to display results in a POST (remember: don't do that), use the form submit function for what it is designed to do: take action. In your case the action is to rebuild the form and display the result there: store the results in $form_state['storage'], and display that in your form callback. Damien
Damien: I'd be interested in hearing more detail. A bunch of clarifications: - displaying results in a POST (on form submission) is just a bad idea. Don't do that, you should use GET. The converse is a *really* bad idea: using a GET when changing state on the server, of course - this is the path to XSS everywhere. But why is it bad to use a POST to display results? Just using a POST to gather info that you don't want as arguments seems innocuous to me, as long as they're properly handled. An example might be a one-time in-form (non-session) authentication, which must not be a GET. So please elaborate.
- if you really want to display results in a POST (remember: don't do that), use the form submit function for what it is designed to do: take action. In your case the action is to rebuild the form and display the result there: store the results in $form_state['storage'], and display that in your form callback.
Every multistep form is essentially rebuilding the form based on prior input. What is the difference between that and displaying (correctly processed) results by processing information in the form builder function? Thanks for your thoughts, -Randy
Damien
-- Randy Fay Drupal Module and Site Development randy@randyfay.com +1 970.462.7450
I share Randy's questions, but want to diverge to discuss one thing. On Tue, May 11, 2010 at 6:55 AM, Randy Fay <randy@randyfay.com> wrote:
The converse is a *really* bad idea: using a GET when changing state on the server, of course - this is the path to XSS everywhere.
It's a path to CSRF (cross site request forgery) and not XSS (cross site scripting). But really the answer is that you should use GET/POST depending on what makes the most sense in general and then protect it in a sane way - either with the default token that FAPI gives you or via a self-created/self-verified query string token. All this and more documented at http://crackingdrupal.com/node/48 Regards, Greg -- Greg Knaddison | 303-800-5623 | http://growingventuresolutions.com Mastering Drupal | http://www.masteringdrupal.com
Bayne, Sam wrote:
Is there some other way to accomplish what I want?
p.s. I've looked at the search module, it basically shoves the form input into the querystring of the redirect. That'll work for a single input, but multiple array inputs will be a huge pain.
Check out what I did for the lastest 3.x-dev release of advuser and see if that will work for you. -- Earnie -- http://progw.com -- http://www.for-my-kids.com
Add the display bits to your form builder function, and pass the data back with $form_state['storage'] or something like that. This is a basic multi-step form. There are a few examples in Drupal 6 core of this, or just google for "drupal 6 multistep form." -Mike __________________ Michael Prasuhn mike@mikeyp.net http://mikeyp.net On May 10, 2010, at 9:37 AM, Bayne, Sam wrote:
I'm quite frustrated with the Form API right now, so please forgive my tone.
I've got a form that has a bunch of inputs, all of them multiselects, that allow the user to choose what classes to see in our schedule. (our class schedule is in an external database). I've got a bunch of code in the form_submit function that builds a very elaborate sql query to get the list of requested classes.
Unfortunately, the form_submit function is not actually permitted to display anything except through drupal_set_message().
So I have to either pass my complicated sql query, or all the contents of the form fields to some other page through $form_state['redirect'].
How do I do that without shoving it all into the querystring?
Right now, I'm looking at the performance issues of:
A: storing the query as a string in the database with a query_id, then sending a query_id in the redirect, B: storing the result of the query in the database with a result_id, then sending a result_id in the redirect.
Is there some other way to accomplish what I want?
p.s. I've looked at the search module, it basically shoves the form input into the querystring of the redirect. That'll work for a single input, but multiple array inputs will be a huge pain.
Michael Prasuhn wrote:
Add the display bits to your form builder function, and pass the data back with $form_state['storage'] or something like that. This is a basic multi-step form. There are a few examples in Drupal 6 core of this, or just google for "drupal 6 multistep form."
That doesn't work well for multi-page forms. The selection criteria is lost. -- Earnie -- http://progw.com -- http://www.for-my-kids.com
I have a vague recollection of seeing something like this done with a regular page callback that returns drupal_get_form('your_form') if it doesn't receive a $form_state (or even check $_POST if necessary to be unambiguous about the function arguments). If you do have your form values, output whatever you want like any other callback. Anyway, the key is moving drupal_get_form out of your menu item, unless I'm just not getting what you're trying to do. All the Best, Matt Chapman Ninjitsu Web Development -- The contents of this message should be assumed to be Confidential, and may not be disclosed without permission of the sender. On Mon, May 10, 2010 at 9:58 AM, Earnie Boyd <earnie@users.sourceforge.net> wrote:
Michael Prasuhn wrote:
Add the display bits to your form builder function, and pass the data back with $form_state['storage'] or something like that. This is a basic multi-step form. There are a few examples in Drupal 6 core of this, or just google for "drupal 6 multistep form."
That doesn't work well for multi-page forms. The selection criteria is lost.
-- Earnie -- http://progw.com -- http://www.for-my-kids.com
I may not be understanding your needs correctly, but I recently did this: 1. The form builder function switches based on some piece of info in $form_state. 2. If the info is there, present information. If the information is not there, present a form. 3. The submit function contains onlly $form_state['rebuild'] = TRUE. Basically you're giving the form builder function two ways to build the page: With data and without it. -Randy On Mon, May 10, 2010 at 10:37 AM, Bayne, Sam <sbayne@sccd.ctc.edu> wrote:
I'm quite frustrated with the Form API right now, so please forgive my tone.
I've got a form that has a bunch of inputs, all of them multiselects, that allow the user to choose what classes to see in our schedule. (our class schedule is in an external database). I've got a bunch of code in the form_submit function that builds a very elaborate sql query to get the list of requested classes.
Unfortunately, the form_submit function is not actually permitted to display anything except through drupal_set_message().
So I have to either pass my complicated sql query, or all the contents of the form fields to some other page through $form_state['redirect'].
How do I do that without shoving it all into the querystring?
Right now, I'm looking at the performance issues of:
A: storing the query as a string in the database with a query_id, then sending a query_id in the redirect, B: storing the result of the query in the database with a result_id, then sending a result_id in the redirect.
Is there some other way to accomplish what I want?
p.s. I've looked at the search module, it basically shoves the form input into the querystring of the redirect. That'll work for a single input, but multiple array inputs will be a huge pain.
-- Randy Fay Drupal Module and Site Development randy@randyfay.com +1 970.462.7450
I generally use a static variable object caching mechanism for this: function mymodule_class_factory() { static $object = ''; $path = drupal_get_path('module','mymodule'); require_once($path.'mymodule_class.inc'); if (!$object) { $object = new mymodule_class(); } return $object; } Now whenever I need my complex data storage mechanism, I simply call the factory method, which will (the first time it is called) initialize the object. Thereafter it returns the instantiated object... like this: $o = mymodule_class_factory(); The submit function can get the object and invoke methods in the class. This means that business logic is all in the class definition, and you can use it equally well in the the rendering function, the form submit handler, validation handler and rendering function. You can also put the external database connectivity logic into the contructor for the object, and know that it's only used when needed. Saves on module memory footprint too. If you want to you can move the require_once into the menu hook file include mechanism if you find that more elegant. Dave On May 10, 2010, at 9:37 AM, Bayne, Sam wrote:
I'm quite frustrated with the Form API right now, so please forgive my tone.
I've got a form that has a bunch of inputs, all of them multiselects, that allow the user to choose what classes to see in our schedule. (our class schedule is in an external database). I've got a bunch of code in the form_submit function that builds a very elaborate sql query to get the list of requested classes.
Unfortunately, the form_submit function is not actually permitted to display anything except through drupal_set_message().
So I have to either pass my complicated sql query, or all the contents of the form fields to some other page through $form_state['redirect'].
How do I do that without shoving it all into the querystring?
Right now, I'm looking at the performance issues of:
A: storing the query as a string in the database with a query_id, then sending a query_id in the redirect, B: storing the result of the query in the database with a result_id, then sending a result_id in the redirect.
Is there some other way to accomplish what I want?
p.s. I've looked at the search module, it basically shoves the form input into the querystring of the redirect. That'll work for a single input, but multiple array inputs will be a huge pain.
We solved this problem by using tablewizard (tw) to make the data available to Drupal and views. If you combine it with bef and views_savedsearches you can accomplish the same. Best regards, Peter Droogmans Attiks Ketsstraat 94 2140 Borgerhout Belgium 32 3 288 61 17 32 497 44 44 77 -----Original Message----- From: development-bounces@drupal.org [mailto:development-bounces@drupal.org] On Behalf Of Bayne, Sam Sent: maandag 10 mei 2010 6:37 PM To: development@drupal.org Subject: [development] How to pass form values to page that actually does something. I'm quite frustrated with the Form API right now, so please forgive my tone. I've got a form that has a bunch of inputs, all of them multiselects, that allow the user to choose what classes to see in our schedule. (our class schedule is in an external database). I've got a bunch of code in the form_submit function that builds a very elaborate sql query to get the list of requested classes. Unfortunately, the form_submit function is not actually permitted to display anything except through drupal_set_message(). So I have to either pass my complicated sql query, or all the contents of the form fields to some other page through $form_state['redirect']. How do I do that without shoving it all into the querystring? Right now, I'm looking at the performance issues of: A: storing the query as a string in the database with a query_id, then sending a query_id in the redirect, B: storing the result of the query in the database with a result_id, then sending a result_id in the redirect. Is there some other way to accomplish what I want? p.s. I've looked at the search module, it basically shoves the form input into the querystring of the redirect. That'll work for a single input, but multiple array inputs will be a huge pain.
participants (10)
-
Alex Bronstein -
Bayne, Sam -
Damien Tournoud -
David Metzler -
Earnie Boyd -
Greg Knaddison -
Matt Chapman -
Michael Prasuhn -
Peter Droogmans -
Randy Fay