-1
$id = 1;
foreach (@products) {
$productid$id = param(product$id);
++$id;
}

I am trying to loop through the products array and create a new variable for each item in products for a form which uses checkboxes to select products which are for sale. I tried to use $productid$id and $productid"$id" but it returned syntax errors. Is there a way to achieve this?

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
OrcMan
  • 69
  • 10

3 Answers3

4

I am trying to loop through the products array and create a new variable for each item in products.

While it is possible to create a new variable for each item, it's a bad idea. They have to be global, the syntax is ugly, and it's difficult to pass those variables around as a collection. Instead, use a hash or an array. In this case, since your items are indexed by number and there's no gaps an array makes the most sense.

my @product_params;
foreach my $product (@products) {
    push @product_params, param($product);
}

For each $product in @products, it will add param($product) to @product_params. For example, the parameter for $products[5] is stored in $product_params[5].

Since this is a one-to-one mapping of @products to its parameters, its easier and faster to do the above with a map. A mapping runs each element of a list through a function to create a new list. $_ contains each element of @products in turn.

my @product_params = map { param($_) } @products;
Schwern
  • 153,029
  • 25
  • 195
  • 336
3
  1. Variables aren't interpolated in single quotes.
  2. You're resetting the $id in each iteration of the loop.

Update: Your changes invalidated both the bullets above.

my $id = 1;
for my $product (@products) {
    $product_id = param("product$id");
    ++$id;
}
choroba
  • 231,213
  • 25
  • 204
  • 289
  • Thanks that worked, is there a way to set the end of the variabe with the value of $id? For example: $productid1 $productid2 etc – OrcMan Jul 25 '17 at 21:34
  • 4
    @KieranO'Connor: Why? Use an array instead. – choroba Jul 25 '17 at 21:34
  • maybe my logic is bad but I need to upload each product the user requests into a mysql table and wanted to set a variable for each product ordered. – OrcMan Jul 25 '17 at 21:36
  • 2
    Just `push @products, param("product$id");` and use the array. – choroba Jul 25 '17 at 21:38
  • 4
    @KieranO'Connor [When you find yourself adding an integer suffix to variable names, think "**I should have used an array**"](https://stackoverflow.com/questions/1829922/concatenating-variable-names-in-c/1829927#1829927). – Sinan Ünür Jul 25 '17 at 22:44
1

Say you have four checkboxes named

  • product1
  • product2
  • product3
  • product4

Say product1 and product3 are checked.

The following will place 1 and 3 in @selected_product_ids:

my @selected_product_ids =
      map { my ($id) = /^product(\d+)\z/; defined($id) && param($_) ? $id : () }
         params();

If you have the list of all existing product ids in @product_ids, the following will do the same:

my @selected_product_ids =
      grep { param("product$_") }
         @product_ids;
ikegami
  • 367,544
  • 15
  • 269
  • 518