I'm curious is there a way to write a shorthand setter in PHP. My primary quest when writing code is to make it as tight as possible and I think the following is kind of cumbersome:
$value = "Which array do I go in?";
if(true)
$arr_1[] = $value;
else
$arr_2[] = $value;
Is there a better way to write that? I tried to use the shorthand if:
(true)?$arr_1[]:$arr_2[] = "Which array do I go in?";
But that doesn't seem to work. Anyone have any cool tricks for this type of situation?
Thanks!
There is no shorthand for what you are trying to do. Also you should realize that making code "as tight as possible" often comes at the cost of readability.
EDIT: There is some ugly hacks to do what you want, but I would strongly recommend against. E.g.:
$GLOBALS[cond ? 'varname1' : 'varname2'] = $value;
Another hack would be:
$arr = ($cond ? &$arr_1 : &$arr_2);
$arr[] = 'Which array do I go in';
it's two lines but it doesn't require global and would work in a function. However for readability it is probably better to use an if statement. (Note: the & is making a reference to the variable, which is why this works). Another (which might make you understand HOW the ternary operator works) would be:
$cond ? $arr_1[] = $value : $arr_2[] = $value;
You see the ternary operator only evaluates (runs the code path) of the successful evaluation (on the right side of the ? if true, on the right side of : if false). However if you think this is faster than using 'if' you are wrong, your less 'tight' code will actually perform better.
Another option (e.g. if you can't/don't want to use globals).
${$cond?'arr_1':'arr_2'}[] = $value;
Related
When I learned PHP I was taught to make my code error free, but to still hide errors in production code to ensure a clean user experience.
I've recently been involved in some projects where the original writer took the approach of leaving in errors and warnings and even utilizing them to achieve something, rather than write code without it.
For example, the code would look like this:
$numm = 0;
while($numm < 10){
$var = "something,".$var;
$numm++;
}
This code will throw a non-fatal Noticethe first time through the loop, because $var doesn't exist for the first concatenation.
There are tons of other examples where they either ignore errors, or even utilize them (to end loops, etc.) but then hide them from the user.
To me, this seems like bad practice, but I could just be OCD.
A Notice is a bug waiting to happen. I routinely run development with error_reporting(E_ALL); set. I want to find the bugs before they are a problem, and not simply ignore the problems, potential, or not.
Set a requirement of isset($var) in the while loop.
One thing that I have always found annoying was doing things like:
$var = isset($var) ? "something,".$var : "something,";
This one liner will prevent the error but not ideal way of doing it when you consider the number of possible uses. Imagine an associative array that returns that doesn't always have all it's key/values you would expect set.
One approach that i take to nearly all my apps is creating and using the following function:
function rtnVal(&$val, $default = null){
return isset($val) ? $val : $default;
}
so in this case, all I have to do is this:
$var = "something,".rtnVal($var);
Easy ain't it? In case you didn't know, defining
function rtnVal(&$var) { ... }
instead of:
function rtnVal($var) { ... }
(notice the & symbol) means that $var is a 'placeholder' (passed by reference) and not actually passed. So when you use it, it doesn't have to be previously set.
There is one limitation to this though and that's working with Objects, they don't like being passed by reference this way so for those, I have yet to find a better solution.
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.
Pretty sure there's a simple answer to this but difficult to search on because of the vague terms used.
I'm using shorthand if statements and want to do more than one action when it returns true, what does the syntax look like?
For example, logically thinking I tried something like:
<?php
$var = "whatever";
(isset($var) ? $var2=$var; $var3=$var : $error="fubar");
?>
Obviously this stops with unexpected ; but hopefully you get the idea of what I'm trying to accomplish.
So sorry if this is a duplicate question, I swear I searched for it. :)
Thanks!
EDIT
I understand that whether or not shorthand is appropriate for this situation should be questioned. But still, can it be done, is the question.
Yes it's possible by using && between each assignment:
(isset($var) ? ($var2=$var) && ($var3=$var) : $error="fubar");
In the above code, if $var is set, $var2 and $var3 will get the same value, otherwise the two variables will not be changed.
That said, it is not the most appropriate method. The ternary operator should be used for simple logic, when the logic starts to get complicated, ternary is most likely no longer the best option. Instead you should just use a simple if/else.
For this specific instance, you can do this:
In this specific instance you can use this:
$output = (isset($var)) ? $var2 = $var3 = $var : false;
Slightly better option for this specific test instance:
$error = (isset($var)) ? !(bool)($var2 = $var3 = $var) : true;
This will set $error to true IF $var is not set, and to false if $var is set, so you could follow this up with an if($error) block.
However, ternary probably isn't the best way to approach this...
For more complicated instances you'd need to use closures or, worse, predeclared functions:
$output = (isset($var)) ? setVars($var) : false;
function setVars($var) {
$var2 = $var3 = $var;
}
At this point, you're probably better off with if or switch statements.
As far as I know, it is not possible, and shouldn't be possible. (?:) is not, and should not be taken as a if, because it doesn't works the same way, and is not designed for it.
The ternary operator exist as a way to return a value depending of a condition, not as a "quick" if.
If you are using it without needing the return value, then you probably are using it wrong.
In this specific case, you should be using and if-else statement. It would also help making your code more readable.
$specify_step = ($_GET['specify_step']) ? $_GET['specify_step'] : getNextStep($returnId,$type);
Given the above statement, is there a way to shorthand this if statement even more so that I don't have to say $_GET['specify_step'] twice?
In the cases when I'm accessing GET or COOKIES etc, it always seems redundant and "wordier" then it needs to be.
I don't think it gets much more compact than that. My only thought is to make a temporary variable to hold $_GET['specify_step'], but that doesn't seem any shorter.
$specify_step = ($_GET['specify_step']) ?: getNextStep($returnId,$type);
It made enough logical sense to me that I had to go look it up....and according to php.net, it works in PHP 5.3. If you're using 5.3, you're in luck.
As I mentioned in a comment to your question, I don't know PHP.
Check if this works. In most langauages, if the first part is true, the function getNextStep won't be called.
$specify_step = ($_GET['specify_step']) || getNextStep($returnId,$type);
There would be this alternate boolean evaluation approach, but it just goes to show that you have to duplicate something:
$specify_step = $_GET['specify_step']
or
$specify_step = getNextStep($returnId,$type);
(Also works without decorative linebreaks.)
With PHP 5.3 you might of course use the ?: shortcut. If that's available.
Personally I can alternate to $_GET->default('specify_step', 123) for such cases.
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.