Best way to make a PHP switch with multiple values ​​for each case?

How do you do this with a PHP statement?

Also note that these are much smaller versions, the one I have to create will have many more values ​​added to it.

Version 1:

switch ($p) { case 'home': case '': $current_home = 'current'; break; case 'users.online': case 'users.location': case 'users.featured': case 'users.new': case 'users.browse': case 'users.search': case 'users.staff': $current_users = 'current'; break; case 'forum': $current_forum = 'current'; break; } 

Version 2:

 switch ($p) { case 'home': $current_home = 'current'; break; case 'users.online' || 'users.location' || 'users.featured' || 'users.browse' || 'users.search' || 'users.staff': $current_users = 'current'; break; case 'forum': $current_forum = 'current'; break; } 

UPDATE - Test Results

I did some speed testing for 10,000 iterations,

Time1: 0.0199389457703 // If approval
Time2: 0.0389049446106 // switch statements
Time3: 0.106977939606 // Arrays

+59
php switch-statement
Aug 21 '09 at 1:52
source share
12 answers

In any situation where you have an unknown row, and you need to find out which of several rows it matches, the only solution that does not get slower when you add more elements is to use an array, but have all possible rows as keys . Therefore, your switch can be replaced by the following:

 // used for $current_home = 'current'; $group1 = array( 'home' => True, ); // used for $current_users = 'current'; $group2 = array( 'users.online' => True, 'users.location' => True, 'users.featured' => True, 'users.new' => True, 'users.browse' => True, 'users.search' => True, 'users.staff' => True, ); // used for $current_forum = 'current'; $group3 = array( 'forum' => True, ); if(isset($group1[$p])) $current_home = 'current'; else if(isset($group2[$p])) $current_users = 'current'; else if(isset($group3[$p])) $current_forum = 'current'; else user_error("\$p is invalid", E_USER_ERROR); 

It doesn't look as clean as switch() , but it is the only quick solution that does not include writing a small library of functions and classes to keep it in order. It is still very easy to add elements to arrays.

+47
Aug 21 '09 at 2:50
source share

Version 2 does not work!

 case 'users.online' || 'users.location' || ... 

exactly the same as:

 case True: 

and that case will be selected for any value of $p , if only $p is an empty string.

|| It doesn't really matter inside the case , you are not comparing $p with each of these lines, you are just checking to see if it is False .

+21
Aug 21 '09 at 2:19
source share

Put these many values ​​in an array and query the array, since the switch case seems to hide the basic semantics of what you are trying to achieve when a string variable is used as a condition, which makes it difficult to read and understand, for example:

 $current_home = null; $current_users = null; $current_forum = null; $lotsOfStrings = array('users.online', 'users.location', 'users.featured', 'users.new'); if(empty($p)) { $current_home = 'current'; } if(in_array($p,$lotsOfStrings)) { $current_users = 'current'; } if(0 === strcmp('forum',$p)) { $current_forum = 'current'; } 
+8
Aug 21 '09 at 2:11
source share

If anyone else ever supports your code, they will almost certainly make a double version of version 2 - this is extremely non-standard.

I would stick with version 1. I am from school, although the statements of this case without their own block of statements should have an explicit // fall through comment next to them to indicate that it is really your intention to fail, thereby eliminating any ambiguity about whether you will handle things differently and have forgotten or something like that.

+4
Aug 21 '09 at 2:09
source share

Version 1 is certainly easier on the eyes, clearer than your intentions, and it is easier to add case conditions.

I have never tried the second version. In many languages, this does not even compile, because the labels of each case must be evaluated in a constant expression.

+3
Aug 21 '09 at 1:56
source share

For completeness, I will point out that the broken Version 2 logic can be replaced with a switch statement that works, and also use arrays for speed and clarity, for example:

 // used for $ current_home = 'current';
 $ home_group = array (
     'home' => True,
 );

 // used for $ current_users = 'current';
 $ user_group = array (
     'users.online' => True,
     'users.location' => True,
     'users.featured' => True,
     'users.new' => True,
     'users.browse' => True,
     'users.search' => True,
     'users.staff' => True,
 );

 // used for $ current_forum = 'current';
 $ forum_group = array (
     'forum' => True,
 );

 switch (true) {
     case isset ($ home_group [$ p]):
         $ current_home = 'current';
         break;
     case isset ($ user_group [$ p]):
         $ current_users = 'current';
         break;
     case isset ($ forum_group [$ p]):
         $ current_forum = 'current';
         break;
     default:
         user_error ("\ $ p is invalid", E_USER_ERROR);
 }    
+3
Oct 10
source share

I definitely prefer version 1. Version 2 may require fewer lines of code, but it will be very difficult to read as soon as you have many values ​​there, as you predict.

(Honestly, I did not even know that version 2 was legal until now. I had never seen this done before.)

+1
Aug 21 '09 at 2:00
source share

No version 2 actually works, but if you want this approach, you can do the following (perhaps not the fastest, but perhaps more intuitive):

switch (true) {
case ($var === 'something' || $var === 'something else'):
// do some stuff
break;
}

+1
Apr 28 2018-11-11T00:
source share

Some other ideas are not mentioned yet:

 switch(true){ case in_array($p, array('home', '')): $current_home = 'current'; break; case preg_match('/^users\.(online|location|featured|new|browse|search|staff)$/', $p): $current_users = 'current'; break; case 'forum' == $p: $current_forum = 'current'; break; } 

Someone will probably complain about reading problems with C # 2, but I will not have problems inheriting such code.

+1
Feb 21 '14 at 2:17
source share

I think version 1 is the way to go. It is much easier to read and understand.

0
Aug 21 '09 at 2:12
source share
 if( in_array( $test, $array1 ) ) { // do this } else if( stristr( $test, 'commonpart' ) ) { // do this } else { switch( $test ) { case 1: // do this break; case 2: // do this break; default: // do this break; } } 
0
Apr 17 '12 at 22:33
source share

Switching in combination with variables will give you more flexibility:

 <?php $p = 'home'; //For testing $p = ( strpos($p, 'users') !== false? 'users': $p); switch ($p) { default: $varContainer = 'current_' . $p; //Stores the variable [$current_"xyORz"] into $varContainer ${$varContainer} = 'current'; //Sets the VALUE of [$current_"xyORz"] to 'current' break; } //For testing echo $current_home; ?> 

To learn more, check and examples that i presented in php manual:
Example 1 : http://www.php.net/manual/en/language.variables.variable.php#105293
Example 2 : http://www.php.net/manual/en/language.variables.variable.php#105282

PS: This sample code is SMALL AND SIMPLE , just as I like. It is tested and works too.

0
Nov 16
source share



All Articles