I have this simple if code:
Which is better, doing it with esleif or doing two separate ifs?
if(is_home() && $currentpage == ''){
$catname = 'cars';
} elseif(is_home() && $currentpage != '' && is_page_template('models.php')){
$catname = 'newcars';
}
Two separete if clauses:
if(is_home() && $currentpage == ''){
$catname = 'cars';
}
if(is_home() && $currentpage != '' && is_page_template('models.php')){
$catname = 'newcars';
}
Does the order of if matters? could I place the second if before first?
The question should have been how php treats conditions from more particular to more general?
Should you always start with the more particular ones and work your way up to general?
Or php can sort them through?
The second version would be easier for me since I have allot of if's:)
This depends what behaviour you want:
If you use elseif, only the first matching block will execute.
$foo = $bar = true;
if($foo) { /* executed */ }
elseif($bar) { /* not executed */ }
When using separate if claused, all matching blocks will execute:
$foo = $bar = true;
if($foo) { /* executed */ }
if($bar) { /* also executed */ }
If the conditions are distinct, i.e. only one is ever true it doesn't really matter. However, by using elseif you avoid useless checks since as soon as one condition evaluates to true no further conditions need to be checked.
For the sake of script optimization, I would recommend elseifs as to avoid running extra unnecessary conditionals.
If possible, I would recommend the use of switch/case statements (where you can check the value of a single variable). They're cleaner and easier to maintain from a reduce clutter point of view.
One problem with multiple if statements (instead of elseif statements) is it makes debugging issues more complicated. How are you to know that the second statement isn't overriding the first statement or that your conditional logic is correct for every statement? Using multiple ifs increases the likelihood that one conditional overrides the function of another. Start adding multiple variables inside these if statements and it'll start to hurt your brain.
if (is_home()) {
if ($currentpage == '') {
$catname = 'cars';
}
else if (is_page_template('models.php')) {
$catname = 'newcars';
}
}
i would go with,
if(is_home()) {
if($currentpage == '') {
$catname = 'cars';
}
elseif(is_page_template('models.php')) {
$catname = 'newcars';
}
}
Related
I have a long if condition as follows. There are two conditions that both have to not be met, for the statement to evaluate. I did have it as a one liner with a lot of && and ! but it became unreadable. I have tried splitting it into an if elsif else, which is more readable but doesn't read well, as the first if elsif blocks have no code in them.
What would be the best practice to tidy this code block?
if ($instructionObject->instruction=='nesting_grammar' && $instructionObject->match=='>'){ //if instruction is a '>' child indicator
//don't change the child depth
}else if ($instructionObject->instruction=='selector' && is_object($this->instructions[$key+1]) && $this->instructions[$key+1]->instruction == 'nesting_grammar' && $this->instructions[$key+1]->match == '>'){ //if instruction is a selector followed by a '>'
//don't change the child depth
}else{
$insertOffset += $childDepth;
unset($childDepth);
}
You can use "extract method" refactoring. Replace your conditions to new methods.
if ($this->isInstructionNestingGrammar($instructionObject)){
//don't change the child depth
}else if ($this->isIntructionSelect($instructionObject)){
//don't change the child depth
}else{
$insertOffset += $childDepth;
unset($childDepth);
}
In new methods put every compare to separate line.
P.S. Don't be afraid of long name of methods.
Just negate the conditions and skip the if and else if parts as the two initial conditions don't do anything...
if (
!($instructionObject->instruction=='nesting_grammar' &&
$instructionObject->match=='>')
|| !($instructionObject->instruction=='selector'
&& is_object($this->instructions[$key+1])
&& $this->instructions[$key+1]->instruction == 'nesting_grammar'
&& $this->instructions[$key+1]->match == '>')
) {
$insertOffset += $childDepth;
unset($childDepth);
}
Not directly answering your question, but what about something like:
if (my_check($instructionObject) || $instructionObject->instruction=='selector' && my_check($this->instructions[$key+1])) {
} else {
$insertOffset += $childDepth;
unset($childDepth);
}
function my_check($obj) {
return is_object($obj) && $obj->instruction == 'nesting_grammar' && $obj->match == '>';
}
-- you are basically doing the same thing twice, time to think about a function for that.
Personally if i'm going to span the check across multiple lines i lay it out similar to how i'd lay out a JavaScript object;
if (
great big long check line goes in here &&
another really long ugly check line goes in here too
) {
// Do this code
}
else if (
check 3 &&
check 4
) {
//Do this code
}
Pull out sub-expressions into variables. Pseudo-example:
flibjit = FlibjitManager.FlibjitInstance(this);
isFrob =
(flibjit.Froblocity >= FlibjitManager.FrobThreshold) &&
(flibjit.Type == FlibjitTypes.Frobby);
if (isFrob) {
// ...
out of curiosity I'm wondering if there's a more elegant way to write the conditionals below? I can't see a shorter way of writing it but it feels pretty clunky, so any suggestions welcome!
// Check whether this page has any visuals
if (count($this->page->pagevisuals->find_all()) > 0)
{
// Ok to go ahead and assign
$visual = $this->page->pagevisuals->find_all();
}
// If this is a sub page, parent page may have visuals we can use
elseif (count($this->page->parent->pagevisuals->find_all()) > 0)
{
$visual = $this->page->parent->pagevisuals->find_all();
}
// If two levels deep, grandparent page might have visuals
elseif (count($this->page->parent->parent->pagevisuals->find_all()) > 0)
{
$visual = $this->page->parent->parent->pagevisuals->find_all();
}
You can write a loop instead:
$page = $this->page;
$visual = null;
while (!$visual && $page) {
$visual = $page->pagevisuals->find_all();
$page = $page->parent;
}
I believe this is equivalent, and will work no matter how many levels of parents/nesting you have.
You could assign $this->page to a variable and begin the statements with that, for a very slight improvement.
Alternatively, you could create nested ternary statements to assign $visual, but that's certainly not recommended practice.
A recursive approach:
function getVisuals($root) {
$visuals = $root->pagevisuals->find_all();
if(count($visuals) === 0 && isset($root->parent)) {
$visuals = getVisuals($root->parent);
}
return $visuals;
}
$visuals = getVisuals($this->page);
If you have control over whatever class $this->page is an instance of, then you can make it an instance method.
You could make a recursive method to get rid of those nasty conditionals. Also you're calling the find_all() method twice for every conditional branch which doubles the process time.
Here's an attempt at a recursive function (might not work though, recursive functions are always a bit tricky!). Beware of infinite loops.
<?php
$visual = $this->page->find_all_visuals();
class Page {
function find_all_visuals()
{
$found = $this->pagevisuals->find_all();
if (count($found) > 0) {
return $found;
} else if ($this->parent == null) {
return null;
} else {
return $this->parent->find_all_visuals();
}
}
}
?>
You might want make two changes in your code:
Ensure that getVisuals() returns an empty array instead of null in case there are no visuals
Consider making a null-object - a singleton page instance that has no visuals and has itself as a parent. It might have a method like isNull() so you can easily test if a given page is the null page.
If you make the two adjustments, most of the code concerning visuals will become easier to write and debug.
Getting all the visuals for two levels (I assume you don't want recursion):
$visuals = array_merge(
$this->page->pagevisuals->find_all(),
$this->page->parent->pagevisuals->find_all(),
$this->page->parent->parent->pagevisuals->find_all(),
);
Getting the visuals of the page OR of parent OR of grand parent:
($visuals = $this->page->pagevisuals->find_all()) ||
($visuals = $this->page->parent->pagevisuals->find_all()) ||
($visuals = $this->page->parent->parent->pagevisuals->find_all());
Recursive functions would be much simpler too (this is a method to add to the page object):
public function findRecursive(){
$my_visuals = $this->pagevisuals->find_all()
return $this->parent->isNull()?
$my_visuals
: array_merge($my_visuals, $this->parent->findRecursive());
}
$visual = $this->page->pagevisuals->find_all()
or $visual = $this->page->parent->pagevisuals->find_all()
or $visual = $this->page->parent->parent->pagevisuals->find_all();
What do you do if none of them match? In this code it will be set to the last one, which is not the same as what you did. (In your code $visual was not touched if none matched, in this code it will be set to zero. You could add or $visual = -1 or something similar.)
You can make a loop if you want to avoid all the ->parent, but you'll need some terminator.
$el = $this->page;
while(!$visual = $el->pagevisuals->find_all()) {
$el = $el->parent;
}
This could run forever if it never matches, but I don't know enough about your application to suggest a termination condition - you could add a counter, or something else.
This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
php multiple if conditions
What is better ? Multiple if statements, or one if with multiple conditions
So I was working on a segment of code in which I ended up using two different styles of if statements. That got me wondering - which one is more efficient in PHP? Are there times when one might be better than the other, despite general differences (if present)? Is there a certain level of complexity where the benefits become clear (if close) or close (if originally clear)? Also, are there other benefits of one method over the other, other than aesthetic or subjective differences?
if ($value == 'someval') {
if($otherval == 'someval') {
// do stuff
} else if ($otherval == 'otherval') {
// do same stuff
}
}
vs
if (($value == 'someval') && ($otherval == 'someval' || $thirdval == 'someval') {
// do stuff
}
Note - I don't care what works for C# or Java or whatever other language, unless someone can show that they handle the construct exactly the same.
So long as you're executing the same code in each block (as you've indicated by your comments) then they'll both do the trick (and no, there's really not much of a performance difference).
However, typically it's not the case that you'd execute the same code both ways, so logically the first block is actually different from the second in that case. Here's an example:
if($value == 'someval') {
if($otherval == 'someval') {
doSomething();
}
else if ($otherval == 'otherval') {
doSomethingElse();
}
}
versus:
if(($value == 'someval') && ($otherval == 'someval' || $otherval == 'otherval')) {
//we now still need to evaluate $otherval in order to determine which func to execute...
//this adds bloat...
if($otherval == 'someval') {
doSomething();
}
else if ($otherval == 'otherval') {
doSomethingElse();
}
}
So as you can see in the case above the second block is actually less efficient than the first.
There is no real difference, you should use whichever is more readable.
Nested or not nested if-blocks?
Is this a proper way to say: if something is the case, do nothing?
if ( ($hostNameInfo == $hostNameInput) && ($hostAddressInfo == $hostAddressInput) )
{
return;
}
Update:
I'm not inside a function. :(
So the return is just nonsense.
Here is more code:
//if the input fields are equal to database values, no need to update and waste resources,hence, do nothing:
if ( ($hostNameInfo == $hostNameInput) && ($hostAddressInfo == $hostAddressInput) )
{
//do nothing
}
//If, however, (they are NOT equal and) input fields are not empty:
elseif (!empty($hostNameInput) && (!empty($hostAddressInput)))
{
//do something.
}
Thanks in advance,
MEM
For do nothing you simply can type:
function relax() {
;
}
if (($hostNameInfo == $hostNameInput) && ($hostAddressInfo == $hostAddressInput)) {
relax();
}
Maybe you should do the opposite, do something if your condition is not verified
if($hostNameInfo != $hostNameInput || $hostAddressInfo != $hostAddressInput) {
// do something
}
I assume you're inside a function in which case it does what you expect, although multiple return statements within a function can lead to confusion and a lack of readability. (Apparently I was wrong.)
Instead, I prefer to let all conditional blocks (my description for the code between in the if's {...} block) contain the relevant code, i.e., write the conditional check in such a way that the total condition evaluates to true when additional processing (sub-flow) is needed:
if ($hostNameInfo != $hostNameInput || $hostAddressInfo != $hostAddressInput) {
// do stuff, else skip
}
Furthermore, you can extract the conditional statement in order to improve both readability and simplicity of control flow:
$hostInfoEqualsInput = ($hostNameInfo == $hostNameInput && $hostAddressInfo == $hostAddressInput);
if (!$hostInfoEqualsInput) {
...
}
UPDATE (based on updated question). Consider this instead:
$fieldsAreFilled = (!empty($hostNameInput) && !empty($hostAddressInput));
$hostInfoEqualsInput = ($hostNameInfo == $hostNameInput && $hostAddressInfo == $hostAddressInput);
if ($fieldsAreFilled && !$hostInfoEqualsInput) {
...
}
ERGO
Minimize branch rate and avoid empty blocks by writing conditions you want to be met, not all the exceptions you want to ignore (subjective).
You're talking about best practices here..
One of best practice things is that routine shall have single exit point, though it is widely discussed and is up to developer/style.
UPDATE:
New answer, since the question was changed:
Don't see any reason to add additional checks if the code should run only under some circustances. To make the code more readable, you should stuck to whatever you accept as easy-maintainable, like this (or something similar):
// Do something only if required
if (($hostNameInfo != $hostNameInput) || ($hostAddressInfo != $hostAddressInput)) &&
!empty($hostNameInput) && !empty($hostAddressInput))
{
echo 'place some code here';
}
A native do_nothing() function would be very nice and readable sometimes.
To avoid stressing alerts from syntax checkers & linters, that go crazy when you have an empty if block, I use:
echo(null);
The other possibility is to throw a new exception, which you can later catch in your application.
UPDATE: not inside the function this is probably a bad idea.
I have a basic PHP question, take the code below for example, let's say I need to use this 10 times on a page, is there a better way to do it?
I realize I could wrap it in a function and just keep calling that function but is there a better way then to keep on checking if the item is set and equals a a certain value. After finding this out the first time is there some other way of remembering the result from the first time instead of doing it 10 different times?
Hope that makes sense.
<?PHP
if (isset($_SESSION['auto_id']) && $_SESSION['auto_id'] == "1") {
//do something
}
// do other code here that breaks these up
if (isset($_SESSION['auto_id']) && $_SESSION['auto_id'] == "1") {
//do something else
}
// do other code here that breaks these up
if (isset($_SESSION['auto_id']) && $_SESSION['auto_id'] == "1") {
//do something else
}
// do other code here that breaks these up
if (isset($_SESSION['auto_id']) && $_SESSION['auto_id'] == "1") {
//do something else
}
...ect
?>
In this case, yes you have to, although you could do it once and assign the result to a variable.
how about...
<?PHP
$myCheck = (isset($_SESSION['auto_id']) && $_SESSION['auto_id'] == "1") ;
if($myCheck) {
//do something
}
// do other code here that breaks these up
if($myCheck) {
//do something else
}
// do other code here that breaks these up
if($myCheck) {
//do something else
}
// do other code here that breaks these up
if($myCheck) {
//do something else
}
etc.
?>
Syntax may be off - it's a long time since I've done any PHP work...
Sure. Just save the value of the boolean expression in another variable.
<?php
$auto_id_is_one = ($_SESSION['auto_id']) && $_SESSION['auto_id'] == "1");
// ...
if ($auto_id_is_one) {
// do something
}
// ...
if ($auto_id_is_one) {
// do something else
}
// ...
?>
You probably want to give it a more meaningful name than $auto_id_is_one, though.
Maybe a better approach is to use isset once at the top of the function, and set the variable to a default value there. Then you can simply use the value through the rest of the function.
In your example, you could set it to "0", though I realize that may not be the real code...
It depends what the "do something" block of code is, and whether or not the auto_id index of $_SESSION is changed in the other code. You can be certain that, in the body of the first if, the variable exists and is 1. Once that if concludes, you can no longer be certain - you'll have to check again later unless all the rest of the code is executed in a context that only exists if the first test succeeds (i.e. there's an else clause that terminates the script), and you are sure you don't change the value (and no external code you call changes it).
A better way to check the sanity might be to ensure most of the environment is as you expect it just once, then just check specific values at various places. However, if you're constantly rechecking this, it might indicate a design flaw, where similar logic (i.e. that dependent on auto_id = 1) is not well isolated and grouped.
In the example you provided, PHP will just issue an E_NOTICE that the index is not found in the $_SESSION super global (It will not throw the notice if you turned off strict mode). The best practice would be to go and set the value to a default so that you know for sure that the variable is set.
ex
<?php
$myVar = isset($_SESSION['auto_id']) ? $_SESSION['auto_id'] : FALSE;
if (false !== $myVar)
{
//do something
}
//do something not realated to myVar being set
if (false !== $myVar)
{
//do somethign else
}
?>
<?PHP
if (isset($_SESSION['auto_id']) && $_SESSION['auto_id'] == "1") {
$sessionOK = TRUE;
}
if ($sessionOK) {
//do this
}
if ($sessionOK) {
//do that
}