I am wondering if I should include break in my switch even if a case is throwing an exception.
switch ($key) {
case self::ABC:
case self::CBA:
if (!is_string($key)) {
throw new Exception('Well.. this should be a string my friend');
}
break;
}
Am I even getting to the break? I do not think so, so why should I include it? Does it makes sense?
If self::CBA is a string, then the exception won't be thrown and your code will reach to break. If that case is the last case in your switch, then break may not be needed as the switch will end anyways, but it is better to just add break instead of not adding it, it's one line of code that can save you a lot of trouble from executing codes that were not meant to be executed. I know this the hard way.
By adding break to all cases, you can rearrange the cases without any problems in the future and you would also get into the habit of writing break every time you write a switch statement (it's a good habit). I hope it answers your question.
Related
I'm attempting to go through a large number bitwise tests, 32 to be exact, where there could be multiple matches. The only method I can think of that would work is to use a whole long list of if statements, e.g.
$test = 3;
if(($test & 1) == 1) {
do something...
}
if(($test & 2) == 2) {
do something else...
}
The other possibility I was thinking of to cut down on the code, although probably not by much is a switch statement. That said, I'm not even sure if what I am thinking of will even work:
$test = 3;
switch($test) {
case ((1 & $test) == 1):
do something...
break;
case ((2 & $test) == 2):
//Will this run?
do something else...
break;
}
Will the break end the switch? Or will the switch continue and each case run that the bitwise operation returns true?
I ask because my actual program will have 32 different tests, and I don't want to write all 32 just to find it doesn't work and Google hasn't turned up anything on this.
If this doesn't work is there a solution that will, or am I relegated to a large number of if statements?
No this is not the case. Only one of the switch cases will run in your example. As soon as break is encountered the switch processing ends. Only one branch will match. In PHP I think (but you might want to double check) the first matching case will run.
With multiple possible matches you will need to use a set of if statements (note do not use if...elseif)
I would convert to
if($test & 1) {
// do stuff
}
if(test & 2) {
// do stuff
}
Well first, using switch with int this way is not really recommended. It's not a good practice / not really readable / not comfortable. I would say it does not even work, although I have a doubt now... depending on versions and stuff, I'm not aware enough of these things.
Then, to answer your question, you only go inside the first matching case... then the break makes you leave the switch. However, you can omit the break and it will go through the second case.
Anyway, you should make more use of OOP to characterize better what you intend to do, and things will probably get more simple and clearer.
I've been thinking to much...
In the area of switch case is break; required after die()
Example:
switch($i){
case 0:
die('Case without break;');
case 1:
die('Case with break;');
break;
}
die() is just an alias for exit(), where exit() will terminate the program flow immediately. (Shutdown functions and object destructors will still get executed after exit())
And no, it is not a syntax error to omit the break, on the contrary there are many useful cases for omitting the break. Check the manual page of the switch statement for examples.
it's not required. Even for the switch break is not mandatory. If no break is in one case, it just keeps executing the next.
but after die, it makes no difference, since die terminates the program execution. Just hope you don't plan to use die inside some cases.
Syntactically, it is not required, but it won't be executed since die() causes the execution to stop.
Is it a good practice to use break and continue as sentinel for loops in PHP?
e.g.
if (!empty($var))
break;
do {
if (condition1)
break;
some code;
some code;
if (condition2)
break;
some code;
some code;
if (condition3)
break;
some code;
some code;
} while (false);
vs.
if (!condition1) {
some code;
some code;
if (!condition2) {
some code;
some code;
if (!condition3) {
some code;
some code;
}
}
Some find the first version an abhomination and difficult to read and love the second version. Some find the first version cleaner and easier to read. As the number of conditions multiply, I tend to find the first version easier to follow, as the second one tends to get more and more difficult to follow the level of nesting. Also if the if (condition) break; gets into something only slightly more complex like if (condition) {some code; break}, the do {if .. break; if .. break..;} while(false) pattern gets even more clear compared with equivalend nested ifs.
In light usage it is ok, but in heavy usage it makes your code spaghetti. break and continue is basically just a restricted goto and as such, use sparingly.
It absolutely is, they're both valid programming constructs.
What is not a good idea is the newly introduced GOTO. (Please tell me this was an April fool's joke I didn't see the note about!)
It is perfectly correct to use break or continue as long as it helps to make the code easier to read and understand. I personally use them very rarely, and only when I cannot easily use another structure.
In the case of most while statements, it's easier to achieve the same result as a break or continue by using a boolean variable as the condition for the loop in the first place, and then modifying its value inside the loop.
On the other hand, the best use case for the break, in my opinion, is to save resources if you are iterating through an array or something similar with a for or foreach block and are only interested in processing elements until some item is reached. By using a break after reaching this element, it is possible to save on processing power by breaking out of the loop without going over the remaining elements. This makes the code more efficient without making it less legible.
And of course, it is practically impossible to use switch statements without break.
Another exception is if you need to control nested structures, in which case it is sometimes simpler to use break n or continue n than manipulate multiple variables concurrently. (Even though this use case is probably the most controversial...)
In Python, we use infinite loop and break to improve readability. So yes, you can use it, provided you do it correctly, and for a good reason.
Let me answer with a couple of questions:
Why shouldn't it be considered good practice?
Does it reduce readability of your code?
Does it slow down your for cycles?
For a discussion of break and continue in PHP (and looping in general) have a look at Advanced loops - you get the impression that the author can just about manage to swallow break and continue but not break n and continue n. :-)
In 5+ years programming PHP I never had to use break outside of switch statements.
Continue is sometimes used to skip first or last items in iterations, but I don't like it very much.
Why did they reintroduce GOTO ? that's a shame
To answer the question, in
if (!empty($var))
break;
Why not use return (if in a method context)
if (!empty($var))
return false;
I think this way much clear and makes the caller aware of what's happened inside. A better use for argument errors is using Excecptions, which in facte will break execution a the point they are raised.
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.
we're trying to implement new coding style guidelines for our team, the php codesniffer is printing an warning on switch case statements when no "break" is found like:
switch ($foo) {
case 1:
return 1;
case 2:
return 2;
default:
return 3;
}
is there any good reason to use :
switch ($foo) {
case 1:
return 1;
break;
}
?? the break is never reached ?
It's perfectly valid to leave out the break when you return from a switch.
But it's fairly common practise to add explicit breaks to every case as a defensive programming practise.
switch ($foo) {
case 1:
return 1;
break;
case 2:
return 2;
break;
}
The idea is that should you later change your code in case 1 and remove the return statement, you could forget to add a break.
That would accidentally cause program flow to fall through to case 2.
switch ($foo) {
case 1:
somethingDifferent();
case 2:
return 2;
break;
}
Falling through case statements is slightly unusual and you should add a comment to your code when you do it to show that it's intentional.
switch ($foo) {
case 1:
somethingDifferentAndWeWantToDoCase2AsWell();
// fallthrough
case 2:
return 2;
break;
}
As with many defensive programming practises you've got to balance whether the code bloat - which potentially clutters your code and make it less readable - is worth it or not.
If your "php codesniffer is printing a warning" try to get another better codesniffer and don't forget to try to use the last PHP stable version. You can, of course, write a breakafter one return, but it doesn't make sense, because it will never be read at all. Your code is OK.
Look at this:
$fun = function(int $argument): string {
switch ($argument) {
case 1:
return "one";
case 2:
return "two";
default:
return "more than two";
}
};
$str = $fun(4); // return "more than two"
In my opinion, this is simpler and better: fewer lines => less code to maintain :-)
To answer your question, no there's no good reason to have something that does nothing. Think about it this way, a comment after the return instead of a break saying "don't forget" will have the same affect - none. And put that way it sounds silly, right?
Unless you need to set a var to use later, I'd suggest the approach you have is perfectly fine. I knew the code's intent within 2 seconds from looking at it. Having a break just creates confusion.
There is no one size fits all really. The correct approach depends on whichever fits the scenario. Set a variable in each case and having a break may be the right way, or perhaps just return makes sense.
Some observations on other suggestions made in answers:
1) Not having a break after return means problems could arise if code is later changed
Whenever possible, code should be explicit, as well as readable and clear. We can also code in a way to make future changes easier. But in something as simple as a switch it should be no problem and need no safety net to refactor a case later to add or remove a return or break.
In fact, if you removed a return and "didn't notice there was no break" then that's a poor mistake and could be made in any part of coding. No gotcha checking will save you from that. And one should be very careful coding for future potentials, as that potential may never happen, or something else may happen, and you just end up maintaining obsolete code for years.
In the same vein this was argued to be a safety net for future changes - What if you remove the return and accidentally left in that safety net break when you should have removed it?
Even if this switch statement was a life or death scenario, really serious code, I would be against adding the "pointless" break after the return. Just make sure whoever was working on the code knew what they were doing, and it was code reviewed by enough eyes and tested fully.
If it was that serious, then you'd have additional checks in place better than a proposed safety net to catch sloppy devs.
To argue that break after return adds a safety net, means you're not coding or testing properly. If this is a safety net deemed useful then it's likely there are tons of bugs in the code in potentially more serious places.
The wiki article of "Defensive Programming" was linked to, but it's not relevant here:
Defensive programming is a form of defensive design intended to ensure
the continuing function of a piece of software under unforeseen
circumstances.
Leaving a safety net break in is not a scenario of unforeseen circumstances, nor defensive programming. It's just bad coding, and you can't litter your code with back up code just in case you don't code correctly when you change something. That's such a bad approach to coding. The argument that "if someone removed return it won't work", well you could also have a typo in the case var, or forget to write the case, or...
The return returns, and you don't code "defensively" to avoid a return failing. That would mean PHP is broken, and you aint gonna fill your code with safety nets to cater for that. That's something you have on a much higher level up.
2) break after return keeps it explicit
But it's explicitly wrong. The return returns, so the break won't happen. To me that is scratch head time wondering if I've missed the intent - not for long as it's clear what will happen, but there will be a moment where I ponder it to make sure I've not missed something.
While it's not invalid or error to have a return and then break in the same case, it's just entirely pointless as the break does nothing. It's pointless code that needs to be seen, maintained, and figured out as it's not logical.
If explicit is the core goal and having a break after a return urks you because it's pointless, then I'd say it'd be better to set a variable and break, then return the variable after breaking from the switch.
Like #RageZ answer https://stackoverflow.com/a/1437476/2632129
3) Set a variable and return after the switch statement is completed
There's nothing wrong with this approach at all, but if there's no reason to store the value in a variable (later use etc) then it's good to return immediately when there's no need to hang around to do anything else.
That shows clear intent - return a value as soon as the case is matched.
I have much better solution.Please follow below code for above switch statment:
$result = 3; // for default case
switch ($foo) {
case 1:
$result = 1;
break;
case 2:
$result = 2;
break;
default:
// do nothing
}
return $result;
It will not result in any error and code is also fine with concepts.
I am not an expert in perfect coding but I think the validator would prefer something like that
switch ($foo) {
case 1:
$ret = 1;
break;
case 2:
$ret = 2;
break;
default:
$ret = 3
}
return $ret
I think using return in case statement to break the flow of the code is not really a best practice. So that's why the validator say there is no break ...
For your question about at category, I don't know ... sorry
From the PHP manual (http://us3.php.net/manual/en/control-structures.switch.php) :
PHP continues to execute the statements until the end of the switch block, or the first time it sees a break statement. If you don't write a break statement at the end of a case's statement list, PHP will go on executing the statements of the following case. For example:
<?php
switch ($i) {
case 0:
echo "i equals 0";
case 1:
echo "i equals 1";
case 2:
echo "i equals 2";
}
?>
Here, if $i is equal to 0, PHP would execute all of the echo statements! If $i is equal to 1, PHP would execute the last two echo statements. You would get the expected behavior ('i equals 2' would be displayed) only if $i is equal to 2. Thus, it is important not to forget break statements (even though you may want to avoid supplying them on purpose under certain circumstances).