I have to perform a big code fix in an old php project.
The issue is the following: I have a number statements where the code tries to add integers to non-initialized multimensional arrays, like this:
$array_test['first']['two']['three'] += 10;
But $array_test is declared just like this:
$array_test = array();
This situation gives me a lot of warnings in the project cause this code pattern happens like 16k times.
Is there any way to solve this like adding a statement like this:
if (!isset($array_test['first']['two']['three']))
{
$array_test['first']['two']['three']=0;
}
and then
$array_test['first']['two']['three'] += 10;
But I would like to do it in only one code line (for both statement, the if isset and the increment) in order to make a big and safe replace in my project.
Can someone help me?
Thanks and sorry for my english.
PHP does not yet (and probably won't ever) have a "null coalescing addition operator.
From PHP7.0, you can avoid the isset() call by null coalescing to 0. Demo
$array_test['first']['two']['three'] = ($array_test['first']['two']['three'] ?? 0) + 10;
If below PHP7 (all the way down to at least PHP4.3), you can use an inline (ternary) condition. Demo
$array_test['first']['two']['three'] = (isset($array_test['first']['two']['three']) ? $array_test['first']['two']['three'] : 0) + 10;
Related
Can I write this code shorter in PHP7?
if(isset($content[$i]['count']))
$content[$i]['count'] = 1;
else
$content[$i]['count'] += $content[$i]['count'];
You could use use a ternary
$content[$i]['count'] = isset($content[$i]['count']) ? 0 : += $content[$i]['count'];
Which is 3 lines less.
It also depends on your code, as the usual method is to set the initial count to 0, e.g. outside a foreach or whatever, then increment on each loop simply with $count++;
I wonder why though, as sometimes code just is what it is, and you should avoid being too terse for the sake of less code as it can make it less obvious or understandable.
Also, seems wrong setting your count to 0 if it's set, this would suggest only 1 count could happen.
I think the shortest possible way is with use of the coalesce operator:
$content[$i]['count'] = ($content[$i]['count'] ?? 0.5) * 2;
But it seems rather complex to understand quickly. :)
I cant seem to find any discussion about this.
In JavaScript to check if something exists, and use a default if it doesn't is like this:
var myvariable = mysetting || 3
In PHP from what I understand, the same thing can be done like this:
$myvariable = $mysetting ?: 3;
Am i completely off on this? I understand the implications of not using isset() and not_empty() and all that, but if I just want to know if the variable exists and is truthy otherwise use a default - this should work I think. Does this syntax have any hidden bad things about it?
Because it doesn't work. That code will still throw a notice Notice: Undefined variable: mysetting in C:\wamp\www\x.php on line, which might be visible to the user, depending on the PHP settings. Apart from that, it will work. If notices are suppressed, then the end result is correct.
So, to get around that, you can either use isset, which isn't really a function, but a language construct, and is specifically designed to do this check:
$myvariable = isset($mysetting)? $mysetting: 3;
Or you can suppress the notice using the # operator:
$myvariable = #$mysetting ?: 3;
For this specific case, maybe it's acceptable, but in general the use of # is frowned upon by many. Personally, I would rather use a couple more characters and make it feel less 'dirty', but it's a matter of opinion.
Another reason why people may not use it, is that it's relatively new (PHP 5.3). Not everyone might know of this new syntax or be comfortable with it. They have been used to isset for years, and old habits die hard.
Those statements are not equivalent. From what I have found the javascript is equivalent to:
if (!mysetting) {
myvariable = 3;
} else {
myvariable = mysetting;
}
Whereas the equivalent PHP statement using the ternary operator would be:
$mysetting = isset($myvariable) ? $myvariable : 3;
aka:
if( isset($myvariable) ) {
$mysetting = $myvariable;
} else {
$mysetting = 3;
}
The ternary operator is essentially a shorthand for and if/else statement, and the first operand is interpreted as a logical expression.
I've been out of the PHP world for a couple years and I've recently inherited a PHP project. Something that should be fairly easy in PHP is eluding me though. In Python I can do the following:
value = some_dict.get(unknown_key, default_value)
My first guess to do the same in PHP was:
$value = $some_array[$unknown_key] || $default_value;
But $value becomes a boolean because PHP doesn't support value short-circuiting. I also get a Notice: Undefined index: the_key but I know I can suppress that by prefixing #.
Is there I way to accomplish similar behavior in PHP to Python's dict.get(key, default)? I checked PHP's list of array functions but nothing stood out to me.
I guess you want something along the lines of the following:
$value = array_key_exists($unknown_key, $some_array) ? $some_array[$unknown_key] : $default_value;
This checks that the key exists and returns the value, else will assign the default value that you have assigned to $default_value.
$value = isset($some_array[$unknown_key]) ? $some_array[$unknown_key] : $default_value;
This way you won't need to suppress warnings
Try this:
$value = $some_array[$unknown_key] ?: $default_value;
This is equivalent to this line of code in Python:
value = some_dict.get(unknown_key, default_value)
Note that in the edge-case that the key exists but its value is falsey, you will get the $default_value, which may not be what you intend.
Is there difference between ternary operator and if condition in php ?
if yes, kindly provide.
The ternary operator is an operator, so it forms an expression. So it will have a value that you can assign to a variable or use however you want. It is used for simple situations where a variable can take two possible values depending on a condition.
For example: $status = $age > 18 ? 'adult' : 'child';
Although possible, you should not nest the ternary operator.
The control structure if is something absolutely different. The only thing they have in common that both evaluate a condition (true/false). if is used to execute code fragments based on the result of that condition. You will find yourself using if most of the time (in fact, you can live without the ternary). In certain situations, it is less code and more readable if you replace certain types of ifs with the ternary, like this one:
if ($age > 18) {
$status = 'adult';
} else {
$status = 'child';
}
Personally, I only use the ternary operator if it fits on one line. If it need to span, then it's time for the good old
$value = ($a < 0) ? 'minus' : 'plus';
also you can see one interesting question how multiple ternary works :
unusual ternary operation
If statements are faster than ternary, but in most cases it doesn't matter.
Here is a post on the performance of If statements vs ternary.
Summary: It's basically the same unless you are evaluating large objects because ternary copies the objects being evaluated. This was using PHP 5.3 I'm not sure if it has been changed in current versions.
The ternary operator can do anything that an if/else statement can. In some cases it can provide brevity and expressiveness, but beware: it is easily abused.
One thing I like it for is checking for null:
$foo = (is_null($bar)) ? 0 : $bar->someNumber();
If my PHP memory serves me correctly, then it can also be used on an lvalue:
((is_null($foo)) ? $bar : $foo) = $quux;
It can be easily overdone though, such as in this C++ example, where it is used in place of loops and if/else statements:
while( ( ! printingStars) ?
( ( ! reachedMax) ?
( ( ++numberOfStars == n - 1) && (reachedMax = 1) )
: --numberOfStars ), printingStars = 1, starsLeft = numberOfStars
: ( ( ! starsLeft ) ?
printingStars = 0, (std::cout<< std::endl), 1
: --starsLeft, (std::cout<< "*"), 1 ) );
Use with caution.
Maybe another point of view: Performance.
A while ago I noticed that the ternary operator is faster than an if(). I don't know if this still applies to the latest versions of PHP.
< wild guess >
The reason may be that an if() allows more flexibility like using code blocks ({ }). A ternary operator basically is just testing an expression and grabbing a value depending on the result of the test.
Going back into my Assembler-days I'd say that an if() has to jump in memory and, therefore, takes a bit more time to do things.
< /wild guess >
However, this may be become noticeable only if the code is executed a decent number (1k+) of times.
There is a big difference in maintenance, if you use none trivial logic.
If you have a difficult problem you need under circumstances much more time, to sove it, as if you have an 'if ... then' in your code. And be sure: it's happen!
The time is not a friend of ternary operator. Fast to write, but not fast to understand, if the years gone!
I want to set a variable to a value, but only if a condition is true.
Instead of doing the following:
if($myarray["foo"]==$bar){
$variablename=$myarray["foo"];
}
This can end up being quite long if the variable names are long, or perhaps it involves arrays, when it's quite simple what I want to do — set a value if a condition is true.
I would like to use the conditional operator, something like this:
$variablename=($myarray["foo"]=="bar")? $myarray["foo"]......
But this fails because I don't want the variable to be set at all if the statement is false.
Basically, what I'm trying to do is make the first example shorter. Perhaps the conditional operator is not the way though...
Does anyone have any suggestions?
It doesn't get much shorter than:
if($condition) $var = $value;
IMO, the best way to make your code sample shorter is:
if($myarray["foo"] == $bar)
$variablename = $myarray["foo"];
FYI, the name of the operator you're asking about isn't "the ternary operator", it's the conditional operator.
Since you ask, a way you could actually use the conditional operator to do what you're asking is:
$myarray['foo'] == $bar ? $variablename = $myarray['foo'] : null;
but that's somewhat horrifically ugly and very unmaintainable.
You could do this, but I wouldn't as it is pretty unreadable and stupid:
$myarray["foo"] == $bar ? $variablename = $myarray["foo"] : 0;
or
$myarray["foo"] == $bar && $variablename = $myarray["foo"];
Your right, ternary is not the way to go. It's there to handle the if and else part of the statement.
Just stick with the regular if statement.
if($myarray["foo"]==$bar) $variablename=$myarray["foo"];
The "problem" you have isn't really a problem. Your example code is very clear and maintainable. I would really say leave it like it is.
You -could- remove the braces, but that will have an impact on maintainability.
Your other alternative is to create a set_if_true(mixed array, string key, boolean conditional) wrapper function. It hides what is really happening but depending on your specific implementation it is a good option. (For instance a configuration type object, or caching backend)
Put != instead of == and ?: instead of just ?..
$variablename = ($myarray["foo"] != "bar") ?: $myarray["foo"];
is the same as
if($myarray["foo"] != "bar"){} else { $variablename = $myarray["foo"]; }
It might not be the smartest solution but it works. I like this one more
if($myarray["foo"] != "bar") {$variablename = $myarray["foo"]};
Set the variable to itself in the false case:
$variablename=($myarray["foo"]=="bar")? $myarray["foo"] : $variablename
You can put the original expression in the else part of the ternary operation, but if you want to guarantee single evaluation of the expression then you'll have to use a temporary variable and an if statement.
Ternary isn't the way, even though it can be written so that ternary works.
The reason is this: you're trying to use it in a way it's not intended, which will make your code awkward for other developers to read.