Why is my conditional echo-ing the wrong thing - php

I have something like
just a snipplet
$i = 1; while (...) {
echo ($i % 5 == 1) ? 'class="first-col"' : ($i % 5 == 0) ? 'class="last-col"' : '';
$i++;
}
but even when $i % 5 == 1, I will get class="last-col" echo-ed is my logic right?
This is actually a CSS fix for IE so that I wont need to use nth-child. I am trying to target the 1st and last columns of my grid which contains 5 col/row

The ?: operator is left-associative, i.e. you have
echo ( ($i % 5 == 1) ? 'class="first-col"' : ($i % 5 == 0) ) ? 'class="last-col"' : '';
See http://php.net/manual/en/language.operators.comparison.php
It is best not to nest ternary operators.
Better use if / elseif / else constructs, they are more legible.

adding parenthesis helps:
echo (($i % 5 == 1) ? 'class="first-col"' : (($i % 5 == 0) ? 'class="last-col"' : ''));

For a start you're using nested ternary operations. I'd at least use brackets around the individual conditions to make it obvious what should be carried out first.

Related

check if a number is a multiple of another inside for [duplicate]

Within a for loop, i need to add some HTML that outputs only when the loop is on a [(multiple of 3) minus 1].
For example, what i could do is:
for($i=0; $i<count($imagearray); $i++)
{
if($i=="0" || $i=="2" || $i=="5" || $i=="8" || $i=="11")
{
echo 'string';
}
}
but this isnt very elegant and extremely useless for big for loops, is there a proper way to do this?
if ( $i==0 || ($i+1)%3 == 0 )
{
//do stuff
}
What this will do, is go to the next index, divide it by 3, and see if there is a remainder. If there is none, then that means that the current index is one less than a number that is divisible by 3
Use the modulus operator.
if (! (($i+1) % 3) ) {
If $i+1 divides into 3 with no remainder, the result will be zero. Then you just need a boolean not.
If you want to match 0 as well (since you use it in your example, but it doesn't match your description) then you will have to special case it with an ||.
You want to use the modulo for that:
(1 % 3) == 1
(2 % 3) == 2
(3 % 3) == 0
(4 % 3) == 1
Good luck
Modulo is the same thing as saying, give me the remainder of a division. So 1 / 3 equals 0 remainder 1, and so on.
if(($i+1)%3 == 0){
//do something
}
The % operator is known as the modulus operator and returns the remainder of a division.
the most elegent method is thus
if ($i % 3 === 2) {
//do stuff
}
as it doesn't add things to the $i value, but all answers are essentially correct!

PHP understanding ternary operators

I'm still getting used to ternary operators and I find it a helpful way of minimizing code. I can make sense out of it if it is simple like the example showed below (example 1)
Example 1
$OrderType = ($name == 'first' ? 'Fred' : ($name == 'last' ? 'Dabo' : 'RAND()'))
This can be read as: if $name is 'first' then use 'Fred' else if $name is 'last' then use 'Dabo' else use 'RAND()'
However I saw this (example 2) on another website and it doesn't make any sense to me.
Example 2
$score = 10;
$age = 20;
echo 'Taking into account your age and score, you are: ',($age > 10 ? ($score < 80 ? 'behind' : 'above average') : ($score < 50 ? 'behind' : 'above average')); // returns 'You are behind'
So can someone explain to me in simple language how this ternary operator will read?
In simple language, that ternary says, if $age > 10, consider 80 a good score, otherwise consider 50 a good score.
Rather than nesting ternaries, consider breaking out the nested logic into its own helper function. I find the following code much more understandable.
function adult_score($score) {
return $score > 80 ? "behind" : "above average";
}
function child_score($score) {
return $score < 50 ? "behind" : "above average";
}
$score = 10;
$age = 20;
echo $age > 10 ? adult_score($score) : child_score($score);
So, you understand a ternary, part before the ? is the if statement, part between ? and : is the "to do if truthy" and the part after : is the "to do if falsey". So if you took that ternary and wrapped the "if" part with an if statement and wrapped the "true" and "false" with curly braces and replaced the : with an else, you end up with this:
if($age > 10){
if($score < 80){
return 'behind';
} else {
return 'above average';
}
} else {
if($score < 50){
return 'behind';
} else {
return 'above average';
}
}
Like others have said though, it is ugly and hard to follow. Unless your goal was to make it hard for others to follow your code, then don't do this. Just please, don't. They are nice for one off if statements, but get confusing fast. Do yourself and any future readers of your code a favor.

Simple "== x OR y" in PHP

I have a loop in which I check for numbers. Something like this, more or less:
<?php $counter = 0; ?>
<?php /* The loop */ ?>
<?php while ( have_posts() ) : the_post(); ?>
<?php $counter++; ?>
<?php get_template_part( 'content', get_post_format() ); ?>
<?php if ($counter == (2 || 4)) : ?>
// DO SOMETHING
<?php endif; // counter ?>
...
But $counter ==(2||4) returns true for every number (1, 2, 3, 4 etc.). I also tried:
$counter == 2 || 4
$counter === 2 || 4
$counter == (2 or 4)
But to no avail. The first and last one also return true for every natural number and the second one never returns true.
An alternate solution would be to do the following:
$allowed = array(2, 4);
if (in_array($counter, $allowed)) {
// good value
}
The advantage of this is that you can extend the list of allowed values very easily, maybe even placing them in an external config.
simply replace
if ($counter == (2 || 4)) :
with
if ($counter == 2 || $counter == 4) :
see also the manual: http://www.php.net/manual/en/control-structures.if.php
If you want to do something when the counter is even, you can use the following:
<?php if ($counter % 2 === 0) : ?>
// do something
// will match 0, 2, 4, 6, ...
<?php endif; ?>
Its not possible to check for multiple values inside a condition like that.
This is one reason why php sucks... you're are forced to use two conditions, like
if($counter == 2 || $counter == 4)
or if you want to trigger your conditions on even numbers
if($counter % 2 == 0)
someone mentioned in_array() but you should know that arrays are very expensive in php in terms of resources.
The expression (2 || 4) will always return true. This is because both operands to the || operator are non zero valued constants. It is essentially equivalent to (true || true) which is always true as is (false || true).
the expression
$counter == (2 || 4)
will yield true except when $counter is 0
You want to write
($counter === 2 || $counter === 4)
note that you should always use === instead of == because the latter performs type coercion on its operands.

PHP Elseif Ternary Operators

I am trying to convert the following code into a Ternary Operator, but it is not working and I am unsure why. I think my problem is that I do not know how to express the elseif operation in ternary format. From my understanding and elseif is performed the same way as an if operation by using the format : (condition) ? 'result'.
if ($i == 0) {
$top = '<div class="active item">';
} elseif ($i % 5 == 0) {
$top = '<div class="item">';
} else {
$top = '';
}
$top = ($i == 0) ? '<div class="active item">' : ($i % 5 == 0) ? '<div class="item">' : '';
$top = ($i == 0) ? '<div class="active item">' : (($i % 5 == 0) ? '<div class="item">' : '');
you need to add parenthesis' around the entire else block
The Ternary Operator doesn't support a true if... else if... else... operation; however, you can simulate the behavior by using the following technique
var name = (variable === 1) ? 'foo' : ((variable === 2) ? 'bar' : 'baz');
I personally don't care for this as I don't find it more readable or elegant. I typically prefer the switch statement.
switch (variable) {
case 1 : name = 'foo'; break;
case 2 : name = 'bar'; break;
default : name = 'bas'; break;
}
Too late probably to share some views, but nevertheless :)
Use if - else if - else for a limited number of evaluations. Personally I prefer to use if - else if - else when number of comparisons are less than 5.
Use switch-case where number of evaluations are more. Personally I prefer switch-case where cases are more than 5.
Use ternary where a single comparison is under consideration (or a single comparison when looping), or when a if-else compare is needed inside the "case" clause of a switch structure.
Using ternary is faster when comparing while looping over a very large data set.
IMHO Its finally the developer who decides the trade off equation between code readability and performance and that in turn decides what out of, ternary vs. if else-if else vs. switch-case, can be used in any particular situation.
//Use this format before reducing the expression to one liner
$var=4; //Change value to test
echo "Format result: ";
echo($var === 1) ? 'one' : //if NB.=> $varname = || echo || print || var_dump(ternary statement inside); can only be (placed at the start/wrapping) of the statement.
(($var === 2) ? 'two' : //elseif
(($var === 3) ? 'three' : //elseif
(($var === 4) ? 'four' : //elseif
'false' //else
))); //extra tip: closing brackets = totalnumber of conditions - 1
// Then echo($var === 1)?'one':(($var === 2)?'two':(($var === 3)?'three':(($var === 4)?'four':'false')));
echo "<br/>";
var_dump("Short result: ", ($var === 1)?'one':(($var === 2)?'two':(($var === 3)?'three':(($var === 4)?'four':'false'))) );

nested php ternary trouble: ternary output != if - else [duplicate]

This question already has answers here:
Stacking Multiple Ternary Operators in PHP
(11 answers)
Closed 2 years ago.
I am fairly capable at using the PHP ternary operator. However I have hit a roadblock at trying to figure out why the code below does not match the if-else equivalent structure. The test was run three times on different numbers. The output for each structure is below the code.
Ternary:
$decimal_places = ($max <= 1) ? 2 : ($max > 3) ? 0 : 1;
Ternary Output:
max: -100000 decimal: 0
max: 0.48 decimal: 0
max: 0.15 decimal: 0
If-Else
if($max <= 1)
$decimal_places = 2;
elseif($max > 3)
$decimal_places = 0;
else
$decimal_places = 1;
If-Else Output:
max: -100000 decimal: 2
max: 0.48 decimal: 2
max: 0.15 decimal: 2
Can anyone please tell me why the these two control stuctures do not output the same data?
Your right-hand-side ternary expression needs to be wrapped in parentheses so it'll be evaluated by itself as a single expression:
$decimal_places = ($max <= 1) ? 2 : (($max > 3) ? 0 : 1);
// Another way of looking at it
$decimal_places = ($max <= 1)
? 2
: (($max > 3) ? 0 : 1);
Otherwise your ternary expression is evaluated from left to right, resulting in:
$decimal_places = (($max <= 1) ? 2 : ($max > 3)) ? 0 : 1;
// Another way of looking at it
$decimal_places = (($max <= 1) ? 2 : ($max > 3))
? 0
: 1;
Which, translated to if-else, becomes this:
if ($max <= 1)
$cond = 2;
else
$cond = ($max > 3);
if ($cond)
$decimal_places = 0;
else
$decimal_places = 1;
Therefore $decimal_places ends up as 0 for all values of $max except 2, in which case it evaluates to 1.
The code is executed as
$decimal_places = (($max <= 1) ? 2 : ($max > 3)) ? 0 : 1;
so you'll never get 2 and 1 only when 1 < $max <=3. This is because the conditional operator is left-associative. Solution: Place parentheses to make sure the order you want is coded:
$decimal_places = ($max <= 1) ? 2 : (($max > 3) ? 0 : 1);
Just put the parenthesis and you would be fine, like this:
$decimal_places = ($max <= 1) ? 2 : (($max > 3) ? 0 : 1);
As others pointed out, use paranthesis.
However, if you actually want to make it readable, what about this:
$decimal_places =
($max <= 1) ? 2 : (
($max > 3) ? 0 : (
1
));
This still looks super awkward, but this awkwardness has a regular shape, so it's easier to live with.
$drink = 'wine';
return
($drink === 'wine') ? 'vinyard' : (
($drink === 'beer') ? 'brewery' : (
($drink === 'juice') ? 'apple tree' : (
($drink === 'coffee') ? 'coffeebeans' : (
'other'
))));
You could of course omit the last pair of brackets, but that would make it less regular-looking.

Categories