Need Help in Simplifying PHP Code

Hi There,

I am going to paste php code; which consist of 2 IF Statements and 3 Switch statements and ONLY one to be true out of 5 statements;

I am sure, that I can get idea from good programmers to make it shorter to a function or class to get the same result in short and more precise code;

I will really appreciate if someone can make a function or class or any other shorter logic for this piece of code;


// $journey could be Oneway/Return
// $duration could be anything over 0 to 99
// $driving_hours is Integer anything over 0

if($journey == "Oneway") { 
			
			switch($driving_hours) { 

			case ($driving_hours <= 4.5):
			$type = "S/Half Day";
			$driver = 1;
			break;
			
			case(($driving_hours >=4.6) && ($driving_hours<=9)):
			$type = "S/Full Day";
			$driver = 1;
			break;
			
			case(($driving_hours >=9) && ($driving_hours <=21)):
			$type = "S/Double";
			$driver =2;
			break;
			
			
			case($driving_hours > 21):
			$type = "S/Over 21hrs";
			$driver = 2;
			break;
			}
			 
} 
else {

		if($duration <=21) { 
		
					switch($duration) { 
			
					case (($duration <= 4.5) && ($driving_hours <=4.5)):
					$type = "R/Half Day";
					$driver = 1;
					break;
					
					case (($duration <= 9) && ($driving_hours <=9)):
					$type = "R/Full Day";
					$driver =1;
					break;
					
					case (($duration <= 21) && ($driving_hours <=9)):
					$type = "R/Full Day/O";
					$driver = 1;
					break;
					
					case (($duration <= 21) && ($driving_hours >= 9)):
					$type = "R/DOUBLE";
					$driver = 2;
					break;
			
					} 
			} 
			else {


				switch($duration) { 
				
				case (($duration >= 21) && ($driving_hours <=4.5)):
				$type = "R/HDD/";
				$driver = 1;
				break;
				
				case (($duration >= 21) && ($driving_hours <=9)):
				$type = "R/FDD";
				$driver = 1;
				break;
				
				case (($duration >= 21) && ($driving_hours >=9)):
				$type = "R/DDD";
				$driver = 2;
				break;
				
				} 
			}
 } 

Many Thanks @cups, Mal and pmw;

I really liked your idea, absolutely amazing@pmw a very nice approach;
Just One more suggestion;with your solution; if I need more variables under a condition came TRUE,

something like this;


if($duration >= 21 && $driving_hours <=4.5) {
 $type = "R/HDD/";
 $variable1 = "variable 1";
 $variable2 = "variable 2";
 .... 

} 

Imagine you make driver = 1 the default result, now you just have to look for when its not, that should halve it.

The solution to that depends on the number of variables, and on the different number of different conditions that will be involved.

One possible solution is to use an object to contain the variables, so that instead of just a string in the array, there is an associative array instead


array(
    0 => array(
        'type' => 'R/HDD/',
        'variable1' => 'variable 1',
        'variable2' => 'variable 2'
    ),
    ...
);

which would mean making a few other changes too, to how the array is processed.

If it is only one or two conditions though, then those may be more easily taken care of separately.

The time differences can be mapped to index values. The magic numbers are 4.5, 9 and 21, so we can use a function that returns an appropriate index. 0 for <= 4.5, 1 for <= 9, and so on. This then allows us to map on to information from an array.


function time_index($driving_hours)
{
	if ($driving_hours <= 4.5) {
		return 0;
	} else if ($driving_hours <= 9) {
		return 1;
	} else if ($driving_hours <= 21) {
		return 2;
	}
	return 3;
}

We can also simply things with $driver by working that out separately.

$driver is 1 when <= 9 and 2 when it’s over.


$drivers = array(1, 1, 2, 2);
$driving_index = time_index($driving_hours);
$driver = $drivers[$driving_index];

That removes one complexity from the code.

Now we can put the oneway types into an array, and access them from there.


$oneway_types = array('S/Half Day', 'S/Full Day', 'S/Double', 'S/Over 21hrs');

if($journey == "Oneway") {
	$type = $oneway_types[$driving_index];
} else {
	...
}

Finally we can move the double comparison of $duration out to separate conditions, which then allows us to see that we can map the results on to an array that contains arrays.


$return_types = array(
	0 => 'R/Half Day',
	1 => 'R/Full Day',
	2 => array(
		0 => 'R/Full Day/O',
		1 => 'R/Full Day/O',
		2 => 'R/DOUBLE'
	),
	3 => array(
		0 => 'R/HDD',
		1 => 'R/FDD',
		2 => 'R/DDD',
		3 => 'R/DDD'
	)
);

All you then need to do is to check if the type is an array, so that you can then retrieve the appropriate driving-based value.


} else { 
	$type = $return_types[$duration_index];
	if (is_array($type)) {
		$type = $type[$driving_index];
	} 
} 

Here’s the sample code in full.


// $journey could be Oneway/Return 
// $duration could be anything over 0 to 99 
// $driving_hours is Integer anything over 0 

function time_index($driving_hours)
{
	if ($driving_hours <= 4.5) {
		return 0;
	} else if ($driving_hours <= 9) {
		return 1;
	} else if ($driving_hours <= 21) {
		return 2;
	}
	return 3;
}

$drivers = array(1, 1, 2, 2);
$oneway_types = array('S/Half Day', 'S/Full Day', 'S/Double', 'S/Over 21hrs');
$return_types = array(
	0 => 'R/Half Day',
	1 => 'R/Full Day',
	2 => array(
		0 => 'R/Full Day/O',
		1 => 'R/Full Day/O',
		2 => 'R/DOUBLE'
	),
	3 => array(
		0 => 'R/HDD',
		1 => 'R/FDD',
		2 => 'R/DDD',
		3 => 'R/DDD'
	)
);

$duration_index = time_index($duration);
$driving_index = time_index($driving_hours);
$driver = $drivers[$driving_index];

if($journey == "Oneway") {
	$type = $oneway_types[$driving_index];
} else { 
	$type = $return_types[$duration_index];
	if (is_array($type)) {
		$type = $type[$driving_index];
	} 
} 

You don’t really need to use the switch statements as they are more for making an equals comparison to a given value, whereas you’re trying to do multiple logical comparisons inside it. The ifelse structure is better suited.

Note: You’ve got both >=9 and <=9 in the structure there, one should be without the = sign, otherwise they will technically both match the exact value 9 - so be aware of the consequences of that.

This is all I could simplify it down too without perhaps going back to the original structure and seeing what you’re trying to accomplish.

$driver = 1;

if($journey == "Oneway") { 
	if($driving_hours <= 4.5)
		$type = "S/Half Day";
	else if($driving_hours<=9)
		$type = "S/Full Day";
	else if($driving_hours <=21){
		$type = "S/Double";
		$driver =2;
	}else($driving_hours > 21){
		$type = "S/Over 21hrs";
		$driver = 2;
	} 
} else {
	if($duration <= 21) { 
		if($duration <= 4.5 && $driving_hours <=4.5){
			$type = "R/Half Day";
		}elseif($duration <= 9 && $driving_hours <=9){
			$type = "R/Full Day";
        }elseif($duration <= 21 && $driving_hours <=9){
			$type = "R/Full Day/O";
		}elseif($duration <= 21) && $driving_hours >= 9){
			$type = "R/DOUBLE";
			$driver = 2;
		} 
	} else {
		if($duration >= 21 && $driving_hours <=4.5)
			$type = "R/HDD/";
		elseif($duration >= 21 && $driving_hours <=9)
			$type = "R/FDD";
		elseif($duration >= 21 && $driving_hours >=9){
			$type = "R/DDD";
			$driver = 2;
		} 
	}
 }