Let's say I have this code:
if (md5($_POST[$foo['bar']]) == $somemd5) {
doSomethingWith(md5($_POST[$foo['bar']]);
}
I could shorten that down by doing:
$value = md5($_POST[$foo['bar']];
if ($value == $somemd5) {
doSomethingWith($value);
}
But is there any pre-set variable that contains the first or second condition of the current if? Like for instance:
if (md5($_POST[$foo['bar']]) == $somemd5) {
doSomethingWith($if1);
}
May be a unnecessary way of doing it, but I'm just wondering.
No, but since the assignment itself is an expression, you can use the assignment as the conditional expression for the if statement.
if (($value = md5(..)) == $somemd5) { ... }
In general, though, you'll want to avoid embedding assignments into conditional expressions:
The code is denser and therefore harder to read, with more nested parentheses.
Mixing = and == in the same expression is just asking for them to get mixed up.
Since the if is just using the result of an expression, you can't access parts of it.
Just store the results of the functions in a variable, like you wrote in your second snippet.
IMHO your 2nd example (quoting below in case someone edits the question) is just ok. You can obscure the code with some tricks, but for me this is the best. In more complicated cases this advise may not apply.
$value = md5($_POST[foo['bar']];
if ($value) == $somemd5) {
doSomethingWith($value);
}
Related
I would like to conditionally execute two functions:
while($row = mysql_fetch_assoc($result))
(strtolower($message) == $row['question'])
? msg($row['answer']) && update($row['question'])
: '';
but this code is not working.
Shorthand only works for one-line statements. Since your if statement contains two lines, shorthand does not work. Usually while loops are formatted as follows:
while (/* condition */)
{
// code to be executed
}
Your ternary expression is also incorrect; it should be written as follows:
(/* condition */) ? /* if true do this */ : /* if false do this */
In the second part of the ternary statement (?:), you use the conditional operator &&, which compares two boolean expressions. As I understand it, your intention of the use of && is to execute two lines, which is incorrect. Refer to the documentation: PHP Docs (Comparison operators)
You need to write the while loop with braces, because your if statement contains multiple lines of code, as follows:
while($row = mysql_fetch_assoc($result))
{
if (strtolower($message) == $row['question'])
{
msg($row['answer']);
update($row['question']);
}
}
Is there any reason why you need to use the shorthand code to do this?
The following would be rather more readable and also when you (or someone else) comes to update/change/review/debug the code sometime in the future it will be much more obvious what the intended outcomes were.
while($row = mysql_fetch_assoc($result)) {
if (strtolower($message) == $row['question']) {
msg($row['answer']);
update($row['question']);
}
}
Usually the shortnened ?: version is reserved only for the very simplest conditions and actions.
Define a function msg_update() that wraps msg() and update():
function msg_update($row) {
msg($row);
update($row);
}
Then you can do:
while($row = mysql_fetch_assoc($result)) (strtolower($message) == $row['question']) ? msg_update($row['answer']) : '';
This is because a tenary operator takes only simple operations. Hope that works for you.
Why this is not possible to accomplish?
foreach($arr as $k => $v)
{
if($condition) { $obj->myMethod() && continue; }
}
After $obj->myMethod() gets evaluated then the keyword continue is evaluated (executed), resulting in skipping the current iteration.
EDIT: i'm asking this because something like:
if($error) { $log->fatal('Something weird happened.') && continue; }
is single line and self-explanatory.
continue is a statement not an expression.
And never the twain shall meet.
You can't put a statement in an expression. (What would echo false && continue; print?)
Instead, use an if, which can contain statements.
You cannot evaluate continue as a condition. The continue keyword does not work the same way as in other languages. In PHP, depending on context continue and break can be somewhat synonymous, consider this construct:
<?php
switch ($months)
{
// start with vowels
case 'august':
break;
case 'april':
continue; // exactly the same as "break" !!!
default:
return 'OK';
}
throw new StartsWithVowelException('Months with vowels are creepy');
?>
While we are on the topic, the break and continue keywords have a feature in PHP that make them a bit more interesting and powerful than their peers in other languages.
Both can be given a numerical argument when used in a loop that indicates how many loops to continue through or break out of. For example, here is an example that restarts the execution of an outer loop from within an inner one::
<?php
//
// verify that each sub array contains the given value
//
$lowerval = strtolower($value);
foreach ($TwoDArray as $otherArray)
{
foreach ($otherArray as $value)
{
if (strtolower($value) == $lowerval)
{
// we found the value -- this one definitely has it.
continue 2;
}
}
// if we've reached here, then the inner loop doesn't have the
// value. ¡aiiee!
}
?>
Hope this helps you out with these 2 constructs, good-luck.
continue is a statement. In PHP a statement and an expression are two different things, statements cannot be evaluated because they do not by nature return true or false which is a requirement for evaluation in PHP.
In PHP you'd have to do something like:
if(test()) continue;
I find my self doing this type of IF statement allot. For example:
if($variable == 1 || $variable == "whatever" || $variable == '492') { ... }
Except for allot of the time, I am comparing the $variable to maybe 4-5 things, sometimes more. Is there a short hand way to write this? You can see that repeating $variable == would get redundant.
I would love for this to work, but it doesn't:
if($variable == (1 || "whatever" || 492) { ... }
You can use this shorthand, but keep in mind that it is less efficient that explicitly listing them all with or clauses:
if(in_array($variable, array(1, 'whatever', '492'))){ ... }
Also if you want to use === instead of == the equivalent is:
if(in_array($variable, array(1, 'whatever', '492'), TRUE)){ ... }
if(in_array($variable, array(1, "whatever", 492)))
in_array(...). http://php.net/manual/en/function.in-array.php
Although this doesn't directly answer the question, I think it's worth adding this method as part of a solution to the above problem:
If you find that something has multiple values, you may find that something like the following is appropriate:
if (true === is_condition_one ( $variable )) {
// Execute any condition_one logic here
}
function is_condition_one ( $variable = null ) {
$arrKnownConditions = array (
// This can be an array from the database
// An array from a file
// An array from any other source
// or an array of hardcoded values
);
return in_array ( $variable, $arrKnownConditions );
}
I agree with Godwin and toon81 and PaulPRO, but feel that if you are doing this a lot, you may actually benefit from a refactor as part of your solution. The refactor above may help you organise this project and others better by defining the purpose of the comparison and letting your code be more readable and abstracting away those hardcoded values to a function. This will probably also help you re-use that check in other parts of your code with greater confidence.
Another viable alternative is to use a regex.
if (preg_match('^1|whatever|492$', $variable)) { ... }
I'm refactoring some code that wasn't written by me. This block sets the value of $val but I want to clean it up a bit. Obviously I can't use the tertiary operator here. What other ways I can make this code cleaner?
if (isset($vars[$input])) {
$val = $vars[$input];
} elseif (isset($this->getI['io'])) {
$val = $this->getI['io'];
} elseif (isset($vars[5])) {
$val = $vars[5];
} else {
$val = 10;
}
$val = 10;
if (isset($vars[$input])) {
$val = $vars[$input];
} elseif (isset($this->getI['io'])) {
$val = $this->getI['io'];
} elseif (isset($vars[5])) {
$val = $vars[5];
}
This is about as simple as it gets without obfuscating the code. I'd rather try to simplify the logic, it's kinda hard to comprehend why the value is being looked for in so many different places.
I'm afraid I don't know php. I'm assuming that if you were to pass (say) $vars[$input] to a function, by the time it was a parameter to the function, the parameter's set-ness would be true (if that's not the case, I'd try writing a function that tested isset() on its parameter and set $val if so). I find elseif's to add complexity; I try to avoid them. In this case, I would write a function that returned the value; then all my elseif's can become plain if's.
f() {
if (isset($vars[$input])) {
return $vars[$input];
}
if (isset($this->getI['io'])) {
return $this->getI['io'];
}
if (isset($vars[5])) {
return $vars[5];
}
return 10;
}
And, of course, in your calling function, assign $val to the result of this function.
In my opinion, your example is as clean as it gets. Sure, you could write it as a huge one-liner using the ternary operator:
$val = isset($vars[$input]) ? $vars[$input] : isset($this->getI['io'] ? $this->getI['io'] : isset($vars[5]) ? $vars[5] : 10;
But this is obviously much harder to read and to maintain, so the original example is definitely cleaner (although it might be missing some comments).
I don't know...it seems to be pretty concise, as is.
If you know what it does, it does it well and it is clean enough that you can figure it out again in the future, I say don't touch it.
While you're at it figure out what it's doing and add some comments.
e.g. why assign it to the magic number 10? maybe the context of the rest of it may shed some light.
As far as code goes, you're not going to get it any simpler than this.
Is there any good alternative for the plain if statements in PHP? I know about switch, but I'll guess that there's some more refined alternative out there that comes handy when working with really big if statements.
Thanks a lot,
If you can't read your algorithm on one screen fold, there's a 99.9% chance you need to refactor your code toward more readability.
Change
if ($isHappening) {
// ... millions of lines of code
} else {
// .. another million lines of code
}
into
if ($isHappening) {
happen();
} else {
didntHappen();
}
function happen() {
// millions of lines of code
}
function didntHappen() {
// another million lines of code
}
There really is no magic hammer out there. Your best bet to making them manageable is to break nested ifs into their own functions to make them more readable.
Also, don't forget about array_filter. That can save you from having to write a for loop to filter out items.
Also, you can eliminate nesting by using guard statements. You basically invert your if and do a return instead (another reason to break conditions into functions).
If you want to improve readability only, then you can always split up the expressions inside the if statement:
$exp1 = is_array($var) && isset($var['key']);
$exp2 = is_object($var) && isset($var->key);
$exp3 = substr($string, 0, 4) == 'foo';
$exp4 = ($exp1 || $exp2) && $exp3;
if ($exp4) {}
instead of
if (((is_array($var) && isset($var['key'])) || (is_object($var) && isset($var->key))) && substr($string, 0, 4) == 'foo') {}
Obviously, these are simplified examples, but you get the idea...
Welcome to the world of Object Orientation :)
class Case1 {
function do() { echo "case 1"; }
}
class Case2 {
function do() { echo "case 2"; }
}
$object = new Case1();
$object->do();
And then, there is dispatching using an array:
$choices = array( "case1" => new Case1(), "case2" => new Case2(), ... );
$choices[ $_GET["case"] ]->do();
Well if is if, there is not much else out there. Of course switch is an alternative but depending on the conditions it might not be applicable.
If you are doing OOP, the state design pattern might be what you need.
Otherwise you have to give more information...
If by "big" you mean large, highly nested "ifs", this is a clear sign of code smell, and you should be looking at OOP and design patterns.