skip to Main Content

How can I optimize these tons of if? Co2 payment begins from 131 and ends at 301 so until 131 is 0 and more than 301 is the same payment as 301. Tried with array but don’t know how to get the price from the array if the number corresponds to co2 plus need to know fuel_id. Can’t imagine how this code should look with switch().

<?php
$co2 = '170'; // co2 number taking from DB

// fuel id taking from DB
(1, 'Petrol'),
(2, 'Diesel'),
(3, 'Electic'),
(4, 'Petrol / Gas'),
(5, 'Petrol / Hibrid'),
(6, 'Diesel / Hibrid'),
(7, 'Petrol / Hibrid / Plug-in'),
(8, 'Petrol / Hibrid / Gas'),
(9, 'Diesel / Hibrid / Plug-in');

echo $co2 ? 'Your co2 price is ' : '';

// Payment going from 131 co2
if($co2 >= 131 && $co2 <= 140){
    echo $fuel_id == 2 ? '40.47' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '20.24';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '18.21';}
}else if($co2 >= 141 && $co2 <= 150){
    echo $fuel_id == 2 ? '80.94' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '40.47';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '36.42';}
}else if($co2 >= 151 && $co2 <= 160){
    echo $fuel_id == 2 ? '121.41' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '60.71';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '54.63';}
}else if($co2 >= 161 && $co2 <= 170){
    echo $fuel_id == 2 ? '161.88' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '80.94';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '72.85';}
}else if($co2 >= 171 && $co2 <= 180){
    echo $fuel_id == 2 ? '202.35' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '101.18';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '91.06';}
}else if($co2 >= 181 && $co2 <= 190){
    echo $fuel_id == 2 ? '242.82' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '121.41';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '109.27';}
}else if($co2 >= 191 && $co2 <= 200){
    echo $fuel_id == 2 ? '283.29' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '141.65';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '127.48';}
}else if($co2 >= 201 && $co2 <= 210){
    echo $fuel_id == 2 ? '323.76' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '161.88';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '145.69';}
}else if($co2 >= 211 && $co2 <= 220){
    echo $fuel_id == 2 ? '364.23' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '182.12';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '163.9';}
}else if($co2 >= 221 && $co2 <= 230){
    echo $fuel_id == 2 ? '404.7' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '202.35';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '182.12';}
}else if($co2 >= 231 && $co2 <= 240){
    echo $fuel_id == 2 ? '445.17' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '222.59';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '200.33';}
}else if($co2 >= 241 && $co2 <= 250){
    echo $fuel_id == 2 ? '485.64' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '242.82';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '218.54';}
}else if($co2 >= 251 && $co2 <= 260){
    echo $fuel_id == 2 ? '526.11' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '263.06';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '236.75';}
}else if($co2 >= 261 && $co2 <= 270){
    echo $fuel_id == 2 ? '566.58' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '283.29';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '254.96';}
}else if($co2 >= 271 && $co2 <= 280){
    echo $fuel_id == 2 ? '607.05' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '303.53';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '273.17';}
}else if($co2 >= 281 && $co2 <= 290){
    echo $fuel_id == 2 ? '647.52' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '323.76';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '291.38';}
}else if($co2 >= 291 && $co2 <= 300){
    echo $fuel_id == 2 ? '687.99' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '344';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '309.6';}
}else if($co2 >= 301){
    echo $fuel_id == 2 ? '728.46' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '364.23';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '327.81';}
}

echo $co2 ? ' $' : '';
?>

2

Answers


  1. You could make the code more compact and potentially faster if you’re on PHP version 8 or above using match:

    echo match (true) {
        ($co2 < 131) => '',
    
        ($co2 <= 140) => 
            match ($fuel_id) {
                2 => '40.47',
                1, 5, 7, 8 => '20.24',
                4 => '18.21',
                default => '',
            },
        ($co2 <= 150) => 
            match ($fuel_id) {
                2 => '80.94',
                1, 5, 7, 8 => '40.47',
                4 => '36.42',
                default => '',
            },
        // etc for other boundary points on $co2
         
        default => '',
    };
    

    The conditions in the top-level match are evaluated in order, so there’s no need to keep checking the lower bound (ie if it hasn’t matched $co2 <= 140 then we already know $co2 is larger than 140 when we come to evaluate the next condition $co2 <= 150, and so on)

    Login or Signup to reply.
  2. $co2 = '170';
    $fuel_id = 1;
    
    $type = match ( $fuel_id ) {
      2          => 't2',
      1, 5, 7, 8 => 't1578',
      4, 9       => 't49',
      default    => ''
    };
    
    $result = match ( true ) {
      $co2 >= 131 && $co2 <= 140 => [ 't2' => '40.47', 't1578' => '20.24', 't49' => '18.21' ],
      $co2 >= 141 && $co2 <= 150 => [ 't2' => '80.94', 't1578' => '40.47', 't49' => '36.42' ],
      $co2 >= 151 && $co2 <= 160 => [ 't2' => '121.41', 't1578' => '60.71', 't49' => '54.63' ],
      $co2 >= 161 && $co2 <= 170 => [ 't2' => '161.88', 't1578' => '80.94', 't49' => '72.85' ],
      // ...
      $co2 >= 301                => [ 't2' => '728.46', 't1578' => '364.23', 't49' => '327.81' ],
      default                    => [ 't2' => '', 't1578' => '', 't49' => '' ]
    };
    
    echo $result[$type] ?: 'no match';
    

    So it seems that the structure of the data is as follows:

    Each range (131 – 140, 141 – 150, etc.) has values for $fuel_id, which are a multiple of the values of the first entry (the one for the range 131 – 140).

    So basically one can subtract the 130 from $co2, divide it by the length of each range (10), ceil the result and this gives a multiplier for these ‘start’ values in the first entry with the range 131 – 140.

    Note that the result will be slightly off compared to the data in the OP (by 0,01 to 0,0x for some of the entries only).

    $co2 = random_int(131, 400);
    $fuel_id = random_int(1, 9);
    
    $start = [
      1 => 20.24,
      2 => 40.47,
      3 => 0,       // no value for $fuel_id = 3 in the OP
      4 => 18.21,
      5 => 20.24,
      6 => 0,       // no value for $fuel_id = 6 in the OP
      7 => 20.24,
      8 => 20.24,   // or 18.21 ( 8 is used in two places
      9 => 18.21    // or 20.24   in the code of the OP )
    ];
    
    $result = $start[$fuel_id] * ceil(( $co2 - 130 ) / 10);
    
    echo "co2: $co2 & fuel_id: $fuel_id -> $result";
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search