Page 1 of 1

can't get code dealing with arrays to work

Posted: Fri Jun 04, 2010 7:09 pm
by medworks
I'm using oscommerce for my website's shopping cart, which uses php. And there is a shipping function which has various tables defined. Actually it only had one table until I added things to it. But it has a table delimited by commas and colons, for determining shipping cost by weight. For instance, 5:3.62,16:6.1,29:8.89 would charge a customer $3.62 if the weight was less than or equal to 5, but failing that, if it was still no more than 16, it would charge $6.10, and if not, then as long as it was less than 29 units of whatever, it would charge $8.89. I added an insurance table to it, so that there was a shipping cost measured in units of weight, but an insurance cost which has the same format but uses the order subtotal as its input variable.

Now it also has many different zones, and each zone has an array of different countries. The point being that every country in the list for one particular zone gets treated the same way. So being in the United States, for instance, it costs me the same to ship to France as to England. However, shipping to Canada is cheaper. So Canada would get its own zone, the United States certainly gets its own zone, but England and France are separate countries in the same zone. As it so happens, I have 5 zones defined. US is one. Canada another. Mexico another. Japan, most of Europe, Greenland, and Australia is another. And the fifth contains some others, like Anguilla, New Zealand and Israel. Not that I expect to ship to these countries very often. But my point is there are 5 separate zones, each of which contains a TABLE of countries. Now in researching shipping and insurance costs, I noticed that there is a free insurance called an "automatic indemnity" which comes with shipping internationally, but it is country-dependent. And it turns out that in all other aspects, all the countries in my 4th zone (which contains Japan, Europe, Greenland and Australia) have identical shipping costs BUT different indemnity limits. And my 5th zone, well EVERY ONE of them is different in the indemnity limit. So if I had an insurance table like 100:1,200:2,300:3,400:4,500:4,600:6 that would mean the customer gets charged a dollar for each hundred dollars he's insuring. BUT suppose insurance comes free if it is up to 415 dollars for one country, but I only get 70 dollars of free insurance for a different country, and both these countries are in the zone of consideration which use the same table aside from the automatic indemnity. In other words, in all other aspects, it costs the same to ship or insure to country A and country B for a given weight and price, BUT if the subtotal is between 70.01 and 415 then I can get insurance for free to country A but not to B. So I want it to check, WITHIN the table, which country it is going to, and if country A, then IDEALLY turn the table into 70:0,100:1,200:2,300:3,400:4,500:5,600:6, and if country B, then turn the table into 415:0,500:5,600:6. It would of course be, for all intents and purposes, equivalent if it changed the table, if country B, to 415:0,415:0,415:0,415:0,500:5,600:6. I don't really care which one it does, and so I tried implementing my code each way. And the same problem appears for both. But what I want to do is if the coverage anywhere in the array is less than the country-specific automatic indemnity, in this case 415, then the first number gets overwritten with the country-specific automatic indemnity and the second number, the cost for that level of coverage, gets overwritten with 0. I have made some code that SHOULD do this, or rather something close to it - its only failing that it SHOULD theoretically have is that it won't insert into the table to make it longer - I don't know what in theory would allow me to allocate an extra element into an array - so for it to work with country A, it needed to start with maybe 0:0,100:1,200:2,300:3,400:4,500:4,600:6, and then the 0:0 would get overwritten with 70:0. But it unfortunately doesn't work at ALL. The whole table rate stops working. Instead of throwing the indemnity in there making things at worst the same and at best cheaper, with free insurance possibly being available, that particular component doesn't work at all. None of my variables are typed wrong, I have done the code for this several different ways, and everything that SHOULD work just doesn't. Now look at this part below:

Code: Select all

      for ($i=1; $i<=$this->num_zones; $i++) {
        $countries_table = constant('MODULE_SHIPPING_ZONES3_COUNTRIES_' . $i);
        $country_zones = split("[,]", $countries_table);
        if (in_array($dest_country, $country_zones)) {
          $dest_zone = $i;
          break;
        }
      }
Now, this is where it determines the zone within the set of several possible zones. I didn't write this part. It searches through all the countries in a list defined for each zone to see if it matches the country of the customer. If so, it uses that zone. In other words, if shipping to France, it will eventually settle on zone 3 because the country table for zone 3 is "JP,GB,GL,DK,ES,PT,CH,LI,NL,MC,PL,GR,AU,SE,IS,IE,BE,NO,DE,FI,FR,IT" and it contains the letters "FR". Of course, first it turns the comma-delimited monstrosity into an array. But it doesn't keep track of the position of the country in that table of countries, it just says "the customer's country is somewhere in this list, so we use this zone". It doesn't know, just from this, that "FR" is the 21st element in this list and in the array will have index 20. But if I want a country-specific automatic indemnity then I have to recover which country in the zone it is, you see. And I have another table defined side by side with the country list which is MODULE_SHIPPING_ZONES3_FREE_INDEMNITY_ and this is a list of indemnity coverages that respectively should go with each country in the list. So if some country table was "US,CA,MX,IT" and the indemnity table was "4400,2200,68,650" then it should give an indemnity coverage of 4400 dollars if the customer is in the US, 2200 if Canada, 68 if in Mexico, 650 if Italy. So I try to accomplish this by having it later search through the country table to see where in the country list the customer's country is, and it takes the index it finds, and uses the same place in the table produced from $zones_indemnity_table which is a table produced from the comma-delimited MODULE_SHIPPING_ZONES3_FREE_INDEMNITY_ and uses that value in that table to fit into the first term of $zones_alternate_insurance_table as well as $zones_insurance_table if the shipping weight is above a certain threshold. The trouble is, when it does this, it just doesn't work for some reason. This is the specific code I wrote withing the whole function to accomplish this:

Code: Select all

        $zones_indemnity_cost = constant('MODULE_SHIPPING_ZONES3_FREE_INDEMNITY_' . $dest_zone);
        $zones_indemnity_table = split("[,]", $zones_indemnity_cost);
        $altinsursize = sizeof($zones_alternate_insurance_table);
        $insursize = sizeof($zones_insurance_table);
        $i=0;
        while ($dest_country != $country_zones[$i]) { $i++; }
        if ($zones_indemnity_table[$i] > 0) {
          $j=0;
          while (($j < $altinsursize) && ($zones_alternate_insurance_table[$j] <= $zones_indemnity_table[$i])) {
            $j+=2;
          }
          if ($j) {
            $j-=2;
            $zones_alternate_insurance_table[0] = $zones_indemnity_table[$i];
            $altinsursize = $altinsursize - $j;
            for ($k=1; $k < $altinsursize; $k++) {
              $zones_alternate_insurance_table[$k] = $zones_alternate_insurance_table[$k + $j];
            }
          }
          if ($shipping_weight > $zones_insurance_threshold1) {
            $j=0;
            while (($j < $insursize) && ($zones_insurance_table[$j] <= $zones_indemnity_table[$i])) {
              $j+=2;
            }
            if ($j) {
              $j-=2;
              $zones_insurance_table[0] = $zones_indemnity_table[$i];
              $insursize = $insursize - $j;
              for ($k=1; $k < $insursize; $k++) {
                $zones_insurance_table[$k] = $zones_insurance_table[$k + $j];
              }
            }
          }
        }

What this should do is if the country's indemnity is say, 415 dollars, and the insurance array looks like this:
100:1,200:2,300:3,400:4,500:5,600:6, it should change it to be like this: 415:0,500:5,600:6 in two separate tables, the alternate insurance table and the insurance table, but only do the insurance table if it is above a certain threshold. I redid it so that it would instead turn it into 415:0,415:0,415:0,415:0,500:5,600:6 with this code:

Code: Select all

        $zones_indemnity_cost = constant('MODULE_SHIPPING_ZONES3_FREE_INDEMNITY_' . $dest_zone);
        $zones_indemnity_table = split("[,]", $zones_indemnity_cost);
        $altinsursize = sizeof($zones_alternate_insurance_table);
        $insursize = sizeof($zones_insurance_table);
        $i=0;
        while ($dest_country != $country_zones[$i]) { $i++; }
        if ($zones_indemnity_table[$i] > 0) {
          for ($j=0; (($j < $altinsursize) && ($zones_alternate_insurance_table[$j] <= $zones_indemnity_table[$i])); $j+=2) {
            $zones_alternate_insurance_table[$j] = $zones_indemnity_table[$i];
            $zones_alternate_insurance_table[$j+1] = $zones_alternate_insurance_table[1];
          }
          if ($shipping_weight > $zones_insurance_threshold1) {
            for ($j=0; (($j < $insursize) && ($zones_insurance_table[$j] <= $zones_indemnity_table[$i])); $j+=2) {
              $zones_insurance_table[$j] = $zones_indemnity_table[$i];
              $zones_insurance_table[$j+1] = $zones_insurance_table[1];
            }
          }
        }
Maybe you know something about how these arrays work and I'm not following the right format with something. Please help. Thanks.

Re: can't get code dealing with arrays to work

Posted: Fri Jun 04, 2010 8:02 pm
by Eran
Some friendly advice - divide up your post into paragraphs and wrap up the code with code brackets... it's completely unreadable

Re: can't get code dealing with arrays to work

Posted: Fri Jun 04, 2010 8:10 pm
by medworks
Well the actual code has spaces, so if you get into an if loop everything is indented 2 spaces, if there's a for loop inside the if loop, it's indented 4 spaces. It is your forum that reformatted it like that. It won't let me attach a file either. It says the extension txt as well as php is not allowed.

Re: can't get code dealing with arrays to work

Posted: Fri Jun 04, 2010 8:15 pm
by Benjamin
Please use [sytax=php] tags when posting code in the forum. There is a "PHP Code" button which will add these automatically.

Re: can't get code dealing with arrays to work

Posted: Fri Jun 04, 2010 8:32 pm
by medworks
Ok, I'll try the button there.

Code: Select all

      for ($i=1; $i<=$this->num_zones; $i++) {
        $countries_table = constant('MODULE_SHIPPING_ZONES3_COUNTRIES_' . $i);
        $country_zones = split("[,]", $countries_table);
        if (in_array($dest_country, $country_zones)) {
          $dest_zone = $i;
          break;
        }
      }
this is the part that was not written by me. It takes the country table and sees if the customer's country is in that table. It does not output the index OF the country WITHIN the table. So to recover where the index is so I can use the same index in my indemnity array, I have to do something for that later:

Code: Select all

        $zones_indemnity_cost = constant('MODULE_SHIPPING_ZONES3_FREE_INDEMNITY_' . $dest_zone);
        $zones_indemnity_table = split("[,]", $zones_indemnity_cost);
        $altinsursize = sizeof($zones_alternate_insurance_table);
        $insursize = sizeof($zones_insurance_table);
        $i=0;
        while ($dest_country != $country_zones[$i]) { $i++; }
        if ($zones_indemnity_table[$i] > 0) {
          for ($j=0; (($j < $altinsursize) && ($zones_alternate_insurance_table[$j] <= $zones_indemnity_table[$i])); $j+=2) {
            $zones_alternate_insurance_table[$j] = $zones_indemnity_table[$i];
            $zones_alternate_insurance_table[$j+1] = $zones_alternate_insurance_table[1];
          }
          if ($shipping_weight > $zones_insurance_threshold1) {
            for ($j=0; (($j < $insursize) && ($zones_insurance_table[$j] <= $zones_indemnity_table[$i])); $j+=2) {
              $zones_insurance_table[$j] = $zones_indemnity_table[$i];
              $zones_insurance_table[$j+1] = $zones_insurance_table[1];
            }
          }
        }
This is the shorter one. If the automatic indemnity is 333 dollars, and the insurance cost table is 0:0,100:1,200:2,300:3,400:4,500:5, then $zones_alternate_insurance_table should be an array with terms 0, 0, 100, 1, 200, 2, 300, 3, 400, 4, 500, 5 and $zones_insurance_table will be the same. But after this function, it SHOULD modify the tables so that they are instead 330, 0, 330, 0, 330, 0, 330, 0, 400, 4, 500, 5. And then the user should get free insurance if the subtotal is no more than 330 dollars. But no dice.

As you can see, $i holds the index OF the country being shipped to within the country table, and the same value is used in the indemnity table to find the indemnity FOR that country. And then that value is to be used to replace the first threshold for the insurance. It's just not doing that.

Re: can't get code dealing with arrays to work

Posted: Fri Jun 04, 2010 10:47 pm
by medworks
Grrr. Never mind. It works. I did it - I THOUGHT - exactly the way I showed last the first time I tried it. Then I did it the other way, which is more complicated, where it doesn't turn 100:1,200:2,300:3,400:4,500:5,600:6 into 415:0,415:0,415:0,415:0,500:5,600:6 but rather into just 415:0,500:5,600:6, and it failed in the exact same way. And then I found that I had accidentally not saved a copy of the first version, so I did it again and replaced it. But this time it worked. I thought it wouldn't, since I thought it was exactly the same as the first time I wrote it. But apparently it wasn't. So never mind. I'm not going to ask questions, I'm just going to take it like it is and use it.