Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Variable variable names

by cei (Monk)
on Oct 24, 2000 at 01:24 UTC ( [id://38031]=perlquestion: print w/replies, xml ) Need Help??

cei has asked for the wisdom of the Perl Monks concerning the following question:

I have a CGI script that I'm developing that dynamically creates form elements along with the HTML content, based on items in a database. Think of it this way -- the page you're looking at was created by pulling this message from a MySQL database. One of the items on this page, right below this message, is probably a Radio Button allowing you to vote on this post. The source code for the HTML will identify this radio button with something similar to <INPUT type=radio name='vote__37894' value='1'> where 37894 is a unique identifier tied to this record.

Now my CGI isn't going to know to look for vote__37894 or even $query->param('vote__37894'). But if I get a list of all the variables I'm returning, using @names = $ query->param; then I should be able to pattern match against "vote__*" and do something from there based on the wildcard.

So my question is, if I'm passing other things, like comment__37894, how can I build a variable name based on variable content? If a variable exists named vote__foo then I want to update my database with comment__foo where foo is the record number in my database. How do I concatinate "comment__" and the value of "foo", and use that concatinated string as a variable name?

Hoping some of that made sense...

Replies are listed 'Best First'.
Re: Variable variable names
by chromatic (Archbishop) on Oct 24, 2000 at 01:28 UTC
    Use a hash. A hash key can be just about any name you please, and the value can be any scalar value (including a reference).

    Any time you're tempted to create a variable with a variable name, use a hash. It will save your hair, sanity, and marriage, even if you're not married. I promise.

    The alternative is so Cthonically dangerous, I dare not even speak its name. Suffice it to say that when you know how to deal with the Perl equivalent of an octopus riding a unicycle, you will know when to use it.

Re: Variable variable names
by btrott (Parson) on Oct 24, 2000 at 01:51 UTC
    You're not alone in wanting to do this. Almost every time, though--and I'm pretty sure this applies to you--people want to do this for the wrong reason.

    Here's why you shouldn't do this: Part 1, Part 2, and Part 3.

    And here's what you should do: use a hash or something similar. You have the right idea using $query->param, then grabbing the variables that you need to match based on a pattern. Instead of creating *variables* with those matched names, add entries to a hash.

Re: Variable variable names
by Trimbach (Curate) on Oct 24, 2000 at 03:04 UTC
    At the risk of presenting heresy, (and after reading all 3 of the "use soft references and die!" articles) I'd like to say that I like using soft references when I'm writing CGIs.

    Here's the deal: When you're writing a CGI, you know (well, most of the time) all the form element names. Lots of times there's lots of elements, and for security's sake you only want to mess around with the elements that you care about. (i.e., if some bozo submits a form element named "foo" you want to ignore it and not import it accidentally into your namespace.) So, here's a favorite idiom I like to use:

    @vars = qw(name rank serial_num shoe_size); foreach (@vars) { ${$_} = param ($_}; }
    ...and that's it. Now I have magically created a batch of globals that I want... that I know I want, while properly ignoring anything extraneous that the form might be handing my CGI. Because it's a CGI, it is very unlikely that I'll want to use a "$name" variable somewhere else for some purpose other than sucking in the "name" element as in my example. (After all, it's easy to keep track of "form element = variable name") Plus, as I add (or subtract) values from my HTML form all I have to do is add (or subtract) elements from my @vars array.

    Now, according to the (excellent) articles I should not use soft references but instead do something like this:

    @vars = qw(name rank serial_num shoe_size); foreach (@vars) { $form_input{$_} = param ($_}; }
    ...but I mean, really, isn't that almost the same thing? The only thing this buys you is a (fractionally) smaller percentage of accidentally blowing one of your variables away, something that's even less likely to happen when you localize all your subs anyway.

    Don't mean to be crazy here, but remember, variables don't kill people... people kill people.

    Gary Blackburn
    Trained Killer

      Here's one of the summaries from the last of mjd's articles:
      One of the biggest problems in all of compter programming is namespace management and data hiding. When you use a symbolic reference you are throwing away forty years of expensive lessons from the School of Hard Knocks.
      The fact is, a hash in my opinion buys you much larger than a "fractional" benefit w/r/t blowing away your variables. Why do you want to mix up your form values with variables in your application? What are you *gaining* by doing that?

      You give the example of a variable called $name:

      Because it's a CGI, it is very unlikely that I'll want to use a "$name" variable somewhere else for some purpose other than sucking in the "name" element as in my example.
      Sorry, but $name isn't a very good example of an uncommon variable name. :) That's the sort of thing that could very easily get you in trouble if your programs start getting larger, or if you start doing development in a team environment, etc.

      The basic point here is: you're buying yourself nothing, save typing a couple of characters, by not using a hash. Even if you view using a hash as providing only "fractionally" more security, why not use it?

        All good points, but remember that it's a CGI, which means I am (by definition) stuck with that pesky HTML form and those form elements. I want to confuse my element names with my application variables... one way of looking at it is a deliberate, controlled extension of my application's namespace to include the HTML form.

        I'm not saying that using a hash is a bad idea, but I do think that we should be very careful in our choice of dogma. Perl, far more than most languages, is not a black and white affair. I challenge the dogma that "all soft references are bad" by presenting a reasonable situation where some programmer somewhere might choose to use them to advantage.

        Gary Blackburn
        Trained Killer

      You seem to be a good enough programmer that you can probably get away with symbolic references in this case. (I tend to use the list of allowed variables too.)

      I don't like the idea of encouraging beginning programmers to use them, however. It's a quick way to open up a security hole in a CGI script, and you don't get the protection of -w and strict. Worst yet, it lets beginning programmers tie themselves up in knots trying to make "var1", "var2", ... "varn" when they should be using an array or a hash.

      Programming well is hard enough without encouraging people to put on blindfolds, put raw meat down their pants, and dangle over an alligator pit. People like you and I, who know what we're doing (or can fake it convincingly) can get away with that sort of thing... but I'm not going to recommend it for someone who can't tell me what a typeglob is, for example.

RE: Variable variable names
by PsychoSpunk (Hermit) on Oct 24, 2000 at 08:55 UTC
    I did something similar in Referents Anonymous. You may want to see how I tackled the problem. The code that chromatic sent would be a slightly better solution and it's a comment to that node.

    ALL HAIL BRAK!!!

OT: Re: Variable variable names
by BastardOperator (Monk) on Oct 24, 2000 at 02:37 UTC
    OFF TOPIC:

    I'm curious how you decide whether something should be a radio button (or a pulldown, etc). I'm working on something where I would possibly need similar functionality, and although I'm not sure how much chance there is with yours that something could be a pulldown or a multiple select or whatnot (i.e. how sure are you of the databases structure), that's the challenge I'm facing. If you are doing anything close to this, how? Also, how much "prettying up" are you doing? For instance, you have names for the columns, do you simply use that name when you display it in html?

      For me, I think in the following way: if a question has only one answer, with few choices, a Radio Button is best. If you only want one item, but the list of choices may grow over time, a pull-down may be best. If you want a bit of info that is in no way dependent on other info, checkboxes are the answer.

      Some things make themselves more obvious. Things like multiple choice questions, with potentially long answers, do the answers in HTML text and put radio buttons next to them. Long questions with short answers, pull-down menues. I don't think I've ever needed to use a multiple select in anything I have created. That data could always be represented in other methods.

      As far as "prettying up" the form elements, in my current project, I assign some variables as "selected" or "checked" and then include them in the HTML form element. That way I can maintain state between calls.

Re: Variable variable names
by Anonymous Monk on Oct 24, 2000 at 23:38 UTC
    Although I am a relative newby here, I thought I would throw my 2 cents in. Perusing the recently released "Programming Perl" (3rd Edition), on page 77 I find something that might be of use: The construct of an anonymous hash ref like ${$record_id}. Would this be the kind of thing you are doing?

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://38031]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (6)
As of 2024-04-23 07:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found