Loops within Switch statement - php

my switch statement has about ten outcome, but some of them need 1/2 loops to check, so i can't write them within case(condition), so i've tried using more than one default case, is this possible?
<?php
switch(true) {
case 1:
break;
case 2:
break;
default:
echo "this text is never printed ??";
while(true) {
while(true) { // case 3
break 3;
}
break;
}
while(true) {
// case 4
break 2;
}
case 5:
break;
default:
while(true) {
// case 6
break 2;
}
case 7:
break;
}
?>
is this sort of thing possible, as my first default doesn't seem to be executing at all?!
thanks

You cannot have more than one default in a switch statement. Also, default should be at the end of of the switch after all the case statements.
What might be happening when your code is run through the PHP engine is that the parser is reading the switch statements into a hash map type data structure and each time the parser finds a default label, it's overwriting the existing entry in the hash map. So only last default label ends up in the data structure that gets used in execution.

No this isn't possible, you can't have more than one default case in a switch statement, you'll need to put additional logic into the single final case statement.
when the default case is reached it captures all conditions so later cases are not evaluated.

To answer your question - no, it is only possible to have one default and that at the end. I'm not sure whether you can place other cases after the default, but what I'm sure of is that they would never be reached...
EDIT:
Also, I don't see what you're trying to do there. What's the point? Could you explain a bit? We might be able to help you accomplish what you want to do

You can have only one default in a switch. Remember that Zend is not the only thing that parses PHP, you may confuse other parsers by not putting the default case as the very last part of the switch.

Related

Switch case statement in PHP

I am learning PHP. I have downloaded an open source project from a website and looking the workflow of each modules in that project. I noticed a switch case which is unfamiliar to me.
switch ($value) {
case 'student':
case StudentClass::getInstance()->getId();
return new StudentClass();
break;
case 'teacher':
case TeacherClass::getInstance()->getId();
return new TeacherClass();
break;
default:
break;
}
The above patch is what I looked.
When I give input:
$value = 'student';
It returns StudentClass instance.
If I give
$value = 'teacher';
then it returns TeacherClass instance.
If anyone explain the flow, it will be helpful to me to understanding PHP much better
Your string cases don't have break or return statements, so they "fall through" to the next case. Also, your breaks don't serve any purpose here.
I've added comments to your code to explain what's happening.
switch ($value) {
case 'student': // keeps going with next line
case StudentClass::getInstance()->getId();
return new StudentClass(); // handles both cases above
break; // unnecessary because of the return above
case 'teacher': // keeps going with next line
case TeacherClass::getInstance()->getId();
return new TeacherClass(); // handles both cases above
break; // unnecessary because of the return above
default:
break; // pointless, but handles anything not already handled
}
Also, PHP explicitly allows use of a semicolon (;) after a case, but it is not generally considered good style. From the docs:
It's possible to use a semicolon instead of a colon after a case...
Switch statement is used to perform different actions based on different conditions.
First we have a single expression n (most often a variable), that is evaluated once. The value of the expression is then compared with the values for each case in the structure. If there is a match, the block of code associated with that case is executed. Use break to prevent the code from running into the next case automatically. The default statement is used if no match is found.
switch (n) {
case label1:
code to be executed if n=label1;
break; // if n=label1,break ends execution and exit from switch
case label2:
code to be executed if n=label2;
break; // if n=label2,break ends execution and exit from switch
case label3:
code to be executed if n=label3;
break; // if n=label3,break ends execution and exit from switch
...
default:
code to be executed if n is different from all labels;
}

Should default case always be the last in switch statement? [duplicate]

I've tested this and it works fine, but it looks... weird... to me. Should I be concerned that this is nonstandard form which will be dropped in a future version of PHP, or that it may stop working? I've always had a default case as the final case, never as the first case...
switch($kind)
{
default:
// The kind wasn't valid, set it to the default
$kind = 'kind1';
// and fall through:
case 'kind1':
// Do some stuff for kind 1 here
break;
case 'kind2':
// do some stuff for kind2 here
break;
// [...]
case 'kindn':
// do some stuff for kindn here
break;
}
// some more stuff that uses $kind here...
(In case it's not obvious what I'm trying to do is ensure $kind is valid, hence the default: case. But the switch also performs some operations, and then $kind is used after the switch as well. That's why default: falls through to the first case, and also sets $kind)
Suggestions? Is this normal/valid syntax?
It is an unusual idiom, it causes a little pause when you're reading it, a moment of "huh?". It works, but most people would probably expect to find the default case at the end:
switch($kind)
{
case 'kind2':
// do some stuff for kind2 here
break;
// [...]
case 'kindn':
// do some stuff for kindn here
break;
case 'kind1':
default:
// Assume kind1
$kind = 'kind1';
break;
}
In case anybody find this page through google as I did:
I was wondering the same thing as Josh - so...
One thing is standards, which I think we should all try harder to adhere too, but another thing is hacking (in the: exploit-every-possibility kinda way).
While it's ugly/weird/not normal - it IS possible and IMHO could be useful in some rare cases...
Consider the following:
$color = "greenish";
//$color = "green";
switch($color) {
default:
echo "no colors were selected so the color is: ";
case "red":
echo "red<br />\n";
break;
case "blue":
echo "blue<br />\n";
break;
case "green":
echo "green<br />\n";
break;
}
If $color = "greenish"; the code will print
no colors were selected so the color is red
while if $color = "green"; or any other defined cases, it will just print the color.
It know it not the best example, but you get the point ;)
Hope it helps somebody.
It looks odd for the same reason that
else {
echo "lol";
}
if (1 == 1) {
echo "bbq";
}
would look odd, if it were valid. If for this reason alone I'd avoid it.
In addition, you know that every time you show the code to somebody, you're going to have to explain that putting the default case first was deliberate; this is usually a sign that it's not a great idea.
This is how I'd probably do it... it's easy on the eye and keeps the functionality.
switch($kind)
{
default :
case 'kind1':
$kind = "kind1";
// Do stuff for kind 1
break;
case 'kind2':
// do stuff for kind2
break;
case 'kindn':
// do stuff for kindn
break;
}
I'd personally prefer to do
switch($kind)
{
case 'kind2':
// do some stuff for kind2 here
break;
// [...]
case 'kindn':
// do some stuff for kindn here
break;
case 'kind1':
default:
$kind = 'kind1'; // Redundant if it's already set as 'kind1', but that doesn't make any difference to the code.
// Do some stuff for kind 1 here
break;
}
This can be really handy for flow control, particularly if you aren't breaking between cases.
For example:
$step = $_GET['skip_to_step'];
switch($step) {
default:
case 'step1':
// do some stuff for step one
case 'step2':
// this follows on from step 1 or you can skip straight to it
}
You could add in an additional 'if', or a clever 'or' to make $step default to 'step1' before you start the switch but that's just extra code, reducing readability.
Common practice is to define the default option as last option. But I see nothing wrong with your solution (if there is no predefined schema in your company how to layout your code)
Kind of made me twinge at first, but that's just because we're not use to seeing things that way.
I would suggest that you document this highly, since some might call this "tricky" code. A noob or some future maintainer might come along and move it to the bottom where they're more comfortable with it and break the side-effect that is has being at the top.
Other answers give good examples of it, just stating for clarity's sake...
A Case (including default) does not stop executing at its end unless you include a break. Although switch is often compared to a sequence of if elseif elseif etc., however it's not quite that.
Short version: SWITCH/CASE only acts like IF/ELSEIF/ELSE if you include breaks after each case. SWITCH/CASE is more like a series of "if" statements where each has the same variable check with a different value it's being checked against.
Long version: Without including a break, each case is a "start here"and the differences in a lot of ways make it closer to GOTO without the drawbacks. Technically, if you really REALLY wanted to (read, were a masochistic coder who wanted to really challenge themselves) you could write almost any procedural programs using only one external array, a for loop, and a switch nested inside.
Seriously, why you would want to do this boggles my mind, but it really demonstrates how far switch/case can deviate from if/elseif patterns, so it's here for you for academic reasons (but don't do it!)...
$array = [];
$array['masterLoop'] = 1;
$for ($i = 0, $i < $array['masterLoop'], $i++ ){
switch($array['goto']){
default:
case 1:
PRINT: "Welcome to the program";
case 2:
PRINT: "Please make a choice:";
case 3:
$array['choice']='';
// Wait for some input variable and set choice to it.
case 4:
$array['goto']=$array['choice'];
$array['masterLoop']++;
}
}
The way this code would run (after you set up something for capturing and setting a choice) would be it'd start up with
"Welcome to the program. Please make a choice."
<<user inputs 2>>
"Please make a choice."
<<user inputs 1>>
"Welcome to the program. Please make a choice."
<<user inputs 3>>
// program awaits user input
<<user inputs 4>>
// user triggers infinite loop
So... you can use switches to reflect back to the days of BASIC...
but if you do and I have to debug your code later after you wrote it all like that...
May Linus Torvalds mercy on your soul.

Repeating code in switch statements

I've got and switch statements like this:
switch(x){
case a:
executeSth();
executeA();
break;
case b:
executeSth();
executeB();
break;
...
}
so executeSth(); should allways be executed except in default case but after it some case specific code is called (executeA(); or executeB() and so on). (So simply putting it in front of the switch doesn't work).
Is there an efficient way to reduce the number of "executeSth();" without sacrificing performance?
I could only imagine split it into two switches (one that executes the executeSth() in and one that executes the specific code) but that would sacrifice performance. Maybe you got better ideas?
I'm basicly interessed in code for c/c++ or php. My goal is to minimize code size and in case of c/c++ the size of the resulting executable.
Edit: Yes, the order of the functions matters.
Edit2: I don't have the choice between php or c++, I need it both to be as good as possible.
A nested switch is an option...
This uses two switches, but the second is not triggered in the default case so has a slightly better performance profile than just two in-line switches.
switch($x) {
case a: case b: case c:
executeSth();
switch($x) {
case a:
executeA();
break;
case b:
executeB();
break;
case c:
executeC();
break;
}
break;
default:
...
}
Alternatively, a variable function may do the job...
This is a PHP option which may work, though a lot of people don't like variable functions. This is probably the best option if you want to totally remove nesting & repetition.
switch($x) {
case a:
$function = "executeA";
break;
case b:
$function = "executeB";
break;
case c:
$function = "executeC";
break;
default:
...
}
if(isset($function)) {
executeSth();
$function();
}
I've also made a little live test bed here, if anyone wants to test their PHP solutions work before posting them (case 10 should executeSth() and executeA(), case 20 should executeSth() and executeB(), default should executeDefault()).
In C++, you can use a function pointer to achieve the same as the above
I had a total brain fart when I wrote this, thankfully idipous reminded me that we can do this with a simple function pointer.
// Declare function pointer
int (*functionCall)() = NULL;
// In switch statement, assign something to it
functionCall = &execute;
// After the switch statement, call it
int result = (*functionCall)();
Note: I'm out so haven't checked the syntax on these. The syntax I've used is C syntax and may require some small changes to work in C++.
What you could do (although it might not be the most readable solution) and that if you are using PHP 5.3 and above you could create a method like below:
function mymethod($funcToCall){
executeSth();
$funcToCall();
}
and have the swtich like below:
switch(x){
case a:
mymethod('executeA');
break;
case b:
mymethod('executeB');
break;
...
}
Unless there is really a huge amount of this sort of thing, I'd leave it as is.
One solution is of course to move the call of executeSth into the executeA defintion and executeB definitions - this is of course only meaningful if there are multiple places with similar code - if there aren't more than one place, you have moved two lines of code from one place to another place.
Another solution may be to pass the function executeA or executeB into executeSth as an argument. But it will just make things more complicated to read.
In general, I'd say "smaller code" is not necessarily "better code". The key is to make the code as clear as possible (whilst still achieving reasonable performance and code-size, of course).
In C++, I would additionally expect that if executeSth is small, that it gets inlined into the case-code. So there is no overhead difference between having one or two function calls.
Why don't you set a flag in your default case, and then, after the switch statement, execute the common function if the flag is not set (meaning that it's not the default case)? That sounds like a reasonable solution.
$flag = false;
switch(x){
case a:
executeA();
break;
case b:
executeB();
break;
default:
... // other stuff
$flag = true;
break;
}
if ( !$flag )
executeSth();
EDIT
I misinterpreted the question.
For the reverse order you can put the possible cases in a variable and then use something like in_array in PHP or strstr in C++ (not sure if there's a better native function):
if ( !in_array(x, cases) {
executeSth();
}
switch(x){
case a:
executeA();
break;
case b:
executeB();
break;
...
}
In code size speaking: it doesn't matter. Readability > codesize.
Perhaps you can write something like that for your executeSth():
if(!notDefault){
executeSth();
}
(C++) Let the preprocessor duplicate the code for you? (Dᴏɴ’ᴛ Uꜱᴇ Tʜɪꜱ ɪɴ Mᴀɪɴᴛᴀɪɴᴇᴅ Cᴏᴅᴇʙᴀꜱᴇ. It may hurt readability. I think the two-switch solution is fine.)
#define CASE(n) case n: printf("non-default\n"); _unused_label_##n
switch (x) {
CASE(1):
printf("case 1\n");
break;
CASE(2):
printf("case 2\n");
break;
default:
printf("case else\n");
break;
}
#undef CASE

Behaviour of php switch when array not set

So, I'm trying to have a better understanding of how switch would act when an array is not set and if I should use isset() and/or default:
Example, of the code I'm currently using:
$parameters['sort'] = NULL;
if(isset($parameters['sort'])) {
switch($parameters['sort'])
{
case 'relevance':
$parameters['sort'] = 'rating';
break;
case 'published':
$parameters['sort'] = 'updated';
break;
case 'views':
$parameters['sort'] = 'viewCount';
break;
}
}
Note: I know the break; doesn't have the right indent (should be as below), but it's how I like using it in switch().
Note2: I'm just reviewing my code to fix bugs and improve it while making better sense of how things should be properly implemented/used
case 'relevance':
$parameters['sort'] = 'rating';
break;
So my question is, should I add the extra default and remove the if() or continue using the if() as it didn't caused any problem? Using both wouldn't make any sense!
default:
$parameters['sort'] = '';
break;
default option will be chosen after checking all prior comparisons. If default will be the most common choice and the code will be heavily executed, I think you should stick to the if clause, and you won't have to trust any auto optimizations to save you processor time.
Well, the thing is whether You want to do if value is not found in any of cases.
If You don't, then You can skip default case, but if there is stuff to do even if value is not specified, then use default case.
But I must say, that using default case is good practice, at least logging error/unspecified usage or printing error to screen.
This is personal preference, however I would personally go for removing the if statement and adding default into the switch.
The main reason behind this is because if you use it as you have just now (with the if statement), and $parameters['sort'] is equal to something other than the 3 you have defined in your switch, then you'll have problems. Whereas if a default is defined, then in these cases it'll always know what to default to.

PHP switch() statement

Is this good practise ... ie, grouping the default case with another?
switch ($cond){
case 1:
...;
break;
case 2:
...;
break;
case 3:
default:
...;
break;
}
It makes perfect sense to do it that way.
Also, #Ian is correct, but in a limited scope. If you wanted additional functionality applied to case 3 you would leave it the way it is. As long as you don't break, it will go on to the next case.
It kind of makes case 3 redundant though, so I'd remove it and just leave it as default

Categories