I want to get a value from the session, but use a default if it is not defined. And ofcourse I want to circumvent the PHP notice.
You can write a function that does this
function get(&$var, $default){
if(isset($var)) return $var;
return $default;
}
echo get($foo, "bar\n");
$foobar = "foobar";
echo get($foobar, "ERROR");
Example in action
Is there a way to do this without defining this function in every file?
You can define it in one script and then require_once that script in your other scripts
You could also just use the ternary operator:
$myVar = isset($var)?$var:$default;
From PHP 7, you can now use the null coalescing operator :
$var ?? $default
that does exactly like your function
Use this concise alternative:
isset($myVar) || $myvar=$default;
The || operator is short circuit, it will not evaluate second operant if the first one be evaluated true.
The Null coalescing operator has been added to PHP version 7.0, what it does is replaces
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
with a shorter version:
$username = $_GET['user'] ?? 'nobody';
What the line above does, is check if $_GET['user'] is set, and not null, then it will assign that to the $username variable, if $_GET['user'] is not set (and thus null) it will default to the 'nobody' string so $username is nobody.
Your code should look like:
echo $foo ?? "bar\n";
$foobar = "foobar";
echo $foobar ?? "ERROR";
Use less code to do what you need.
You don't need to specify the variable again using the _?_:_ format.
echo $var?:"default";
Is the same as
echo $var?$var:"default";
Now as far as an empty check, you could use # to mute notices, I'm not sure of the technical ramifications, but you're already doing your own checking while using this format:
echo #$non_existing_var?:"default";
Some examples:
<?php
$nope = null;
$yup = "hello";
echo ($nope?:$yup) . "\n" ;
echo ($yup?:$nope) . "\n" ;
$items = [ 'one', 'two', false, 'three', 'four', null ];
foreach($items as $item):
echo($item?:"default shown (".var_export($item,true).")")."\n";
endforeach;
echo(#$non_existing?:"default for non-existant variable!");
?>
Output:
$ php variabledefault.php
hello
hello
one
two
default shown (false)
three
four
default shown (NULL)
default for non-existant variable!%
You could use my tiny library ValueResolver in this case, for example:
$myVar = ValueResolver::resolve($var, $default);
and don't forget to use namespace use LapaLabs\ValueResolver\Resolver\ValueResolver;
There are also ability to typecasting, for example if your variable's value should be integer, so use this:
$id = ValueResolver::toInteger('6 apples', 1); // returns 6
$id = ValueResolver::toInteger('There are no apples', 1); // returns 1 (used default value)
Check the docs for more examples
Related
Can you use the Ternary Operator in PHP without the closing 'else' statement? I've tried it and it's returning errors. Google search isn't yielding anything, so I think the answer is probably no. I just wanted to double check here. For instance:
if ( isset($testing) {
$new_variable = $testing;
}
Will only set $new_variable if $testing exists. Now I can do
$new_variable = (isset($testing) ? $testing : "");
but that returns an empty variable for $new_variable if $testing isn't set. I don't want an empty variable if it's not set, I want the $new_variable to not be created.
I tried
$new_variable = (isset($testing) ? $testing);
and it returned errors. I also tried
$new_variable = (isset($testing) ? $testing : );
and it also returned errors. Is there a way to use the Ternary Operator without the attached else statement, or am I stuck writing it out longhand?
EDIT: Following Rizier123's advice, I tried setting the 'else' part of the equation to NULL, but it still ends up appending a key to an array. The value isn't there, but the key is, which messes up my plans. Please allow me to explain further.
The code is going to take a bunch of $_POST variables from a form and use them for parameters in a stdClass which is then used for API method calls. Some of form variables will not exist, as they all get applied to the same variable for the API call, but the user can only select one. As an example, maybe you can select 3 items, whichever item you select gets passed to the stdClass and the other 2 don't exist.
I tried this:
$yes_this_test = "IDK";
$setforsure = "for sure";
$list = new stdClass;
$list->DefinitelySet = $setforsure;
$list->MaybeSet = (isset($yes_this_test) ? $yes_this_test : NULL);
$list->MaybeSet = (isset($testing) ? $testing : NULL);
print_r($list);
But obviously MaybeSet gets set to NULL because (isset($testing) comes after (isset($yes_this_test) and it returns
stdClass Object ( [DefinitelySet] => for sure [MaybeSet] => )
I won't know what order the $_POST variables are coming in, so I can't really structure it in such a way to make sure the list gets processed in the correct order.
Now I know I can do something like
if ( isset($yes_this_test ) {
$list->MaybeSet = $yes_this_test;
}
elseif ( isset($testing) ) {
$list->MaybeSet = $testing;
}
But I was hoping there was a shorthand for this type of logic, as I have to write dozens of these. Is there an operator similar to the Ternary Operator used for if/elseif statements?
Since PHP 5.3 you can do this:
!isset($testing) ?: $new_variable = $testing;
As you can see, it only uses the part if the condition is false, so you have to negate the isset expression.
UPDATE
Since PHP 7.0 you can do this:
$new_variable = $testing ?? null;
As you can see, it returns its first operand if it exists and is not NULL; otherwise it returns its second operand.
UPDATE
Since PHP 7.4 you can do this:
$new_variable ??= $testing;
It leaves $new_variable alone if it isset and assigns $testing to it otherwise.
Just set it to NULL like this:
$new_variable = (isset($testing) ? $testing : NULL);
The you variable would return false with a isset() check.
You can read more about NULL in the manual.
And a quote from there:
The special NULL value represents a variable with no value. NULL is the only possible value of type null.
A variable is considered to be null if:
it has been assigned the constant NULL.
it has not been set to any value yet.
it has been unset().
Since PHP 7.0 you can do the following, without getting an ErrorException "Trying to get property 'roomNumber' of non-object":
$house = new House();
$nr = $house->tenthFloor->roomNumbers ?? 0
Assuming the property "tenthFloor" does not exist in the Class "House", the code above will not throw an Error.
Whereas the code below will throw an ErrorException:
$nr = $house->tenthFloor->roomNumbers ? $house->tenthFloor->roomNumbers : 0
You can also do this (short form):
isset($testing) ? $new_variable = $testing : NULL;
JUST USE NULL TO SKIP STATEMENTS WHEN IT WRITTEN IN SHORTHAND
$a == $b? $a = 20 : NULL;
I am looking to expand on my PHP knowledge, and I came across something I am not sure what it is or how to even search for it. I am looking at php.net isset code, and I see isset($_GET['something']) ? $_GET['something'] : ''
I understand normal isset operations, such as if(isset($_GET['something']){ If something is exists, then it is set and we will do something } but I don't understand the ?, repeating the get again, the : or the ''. Can someone help break this down for me or at least point me in the right direction?
It's commonly referred to as 'shorthand' or the Ternary Operator.
$test = isset($_GET['something']) ? $_GET['something'] : '';
means
if(isset($_GET['something'])) {
$test = $_GET['something'];
} else {
$test = '';
}
To break it down:
$test = ... // assign variable
isset(...) // test
? ... // if test is true, do ... (equivalent to if)
: ... // otherwise... (equivalent to else)
Or...
// test --v
if(isset(...)) { // if test is true, do ... (equivalent to ?)
$test = // assign variable
} else { // otherwise... (equivalent to :)
In PHP 7 you can write it even shorter:
$age = $_GET['age'] ?? 27;
This means that the $age variable will be set to the age parameter if it is provided in the URL, or it will default to 27.
See all new features of PHP 7.
That's called a ternary operator and it's mainly used in place of an if-else statement.
In the example you gave it can be used to retrieve a value from an array given isset returns true
isset($_GET['something']) ? $_GET['something'] : ''
is equivalent to
if (isset($_GET['something'])) {
echo "Your error message!";
} else {
$test = $_GET['something'];
}
echo $test;
Of course it's not much use unless you assign it to something, and possibly even assign a default value for a user submitted value.
$username = isset($_GET['username']) ? $_GET['username'] : 'anonymous'
You have encountered the ternary operator. It's purpose is that of a basic if-else statement. The following pieces of code do the same thing.
Ternary:
$something = isset($_GET['something']) ? $_GET['something'] : "failed";
If-else:
if (isset($_GET['something'])) {
$something = $_GET['something'];
} else {
$something = "failed";
}
It is called the ternary operator. It is shorthand for an if-else block. See here for an example http://www.php.net/manual/en/language.operators.comparison.php#language.operators.comparison.ternary
? is called Ternary (conditional) operator : example
What you're looking at is called a Ternary Operator, and you can find the PHP implementation here. It's an if else statement.
if (isset($_GET['something']) == true) {
thing = isset($_GET['something']);
} else {
thing = "";
}
If you want an empty string default then a preferred way is one of these (depending on your need):
$str_value = strval($_GET['something']);
$trimmed_value = trim($_GET['something']);
$int_value = intval($_GET['somenumber']);
If the url parameter something doesn't exist in the url then $_GET['something'] will return null
strval($_GET['something']) -> strval(null) -> ""
and your variable $value is set to an empty string.
trim() might be prefered over strval() depending on code (e.g. a Name parameter might want to use it)
intval() if only numeric values are expected and the default is zero. intval(null) -> 0
Cases to consider:
...&something=value1&key2=value2 (typical)
...&key2=value2 (parameter missing from url $_GET will return null for it)
...&something=+++&key2=value (parameter is " ")
Why this is a preferred approach:
It fits neatly on one line and is clear what's going on.
It's readable than $value = isset($_GET['something']) ? $_GET['something'] : '';
Lower risk of copy/paste mistake or a typo: $value=isset($_GET['something'])?$_GET['somthing']:'';
It's compatible with older and newer php.
Update
Strict mode may require something like this:
$str_value = strval(#$_GET['something']);
$trimmed_value = trim(#$_GET['something']);
$int_value = intval(#$_GET['somenumber']);
I've been coding personal scripts for years in PHP and get used to turn off Error display. I'm about to release some of these scripts and would like to do it the proper way.
The only reason why I turn off error display is to avoid having to test every single var, prior using it, thanks to isset().
So, here is my question:
Is there a better way to declare multiple vars than this ?
<?php
// at the begining of my main file
if (!isset($foo)) ($foo = '');
if (!isset($bar)) ($bar = '');
if (!isset($ping)) ($ping = '');
if (!isset($pong)) ($pong = '');
// etc. for every single var
?>
Something like this for instance :
<?php
var $foo, $bar, $ping, $pong;
?>
<?php
$foo = $bar = $ping = $pong = '';
?>
If it's your script and you know which variables where you use, why you want spend recourses to check if the variable was declared before?
I posted this in a comment earlier, but someone suggested I submit it as an answer.
The shortest and simplest way I can think of, is to do:
$foo = $bar = $ping = $pong = '';
I often prefer to set things to false, instead of an empty string, so that you can always do checks in the future with === false, but that is just a preference and depends on how you are using these variables and for what.
Your if() with isset() attempt is the proper way of doing that!
But you can write it a little bit shorter/more readable, using the Ternary Operator:
$foo = isset($foo) ? $foo : '';
The first $foo will be set to the value after the ? when the condition after the = is true, else it will be set to the value after the :. The condition (between = and ? ) will always be casted as boolean.
Since PHP 5.3 you can write it even shorter:
$foo = isset($foo) ?: '';
This will set $foo to TRUE or FALSE (depending on what isset() returns), as pointed by #Decent Dabbler in the comments. Removing isset() will set it to '' but it will also throw an undefined variable notice (not in production though).
Since PHP 7 you can use a null coalesce operator:
$foo = $foo ?? '';
This won't throw any error, but it will evaluate as TRUE if $foo exists and is empty, as opposed to the shorthand ternary operator, that will evaluate as FALSE if the variable is empty.
A somewhat round-about way of doing this is if you put the name of your variables in an array, and then loop them with a Ternary Operator, similar to powtac's answer.
$vars = array('foo', 'bar', 'ping', 'pong');
$defaultVar = '';
foreach($vars as $var)
{
$$var = isset($$var) ? $$var : $defaultVar;
}
As mentioned in other answers, since version 5.3, PHP allows you to write the above code as follows:
$vars = array('foo', 'bar', 'ping', 'pong');
$defaultVar = '';
foreach($vars as $var)
{
$$var = isset($$var) ?: $defaultVar;
}
Note the changed Ternary Operator.
In OOP you can use this approach:
protected $password, $full_name, $email;
For non-OOP you declare them just in code they will be Undefined if you didn't assign any value to them:
$foo; $bar; $baz;
$set_foo = (isset($foo)) ? $foo : $foo = 'Foo';
echo $set_foo;
Why not just set them?
<?php
$foo = '';
$bar = '';
//etc
?>
If you're trying to preserve the value in them, then yes that's the correct way in general. Note that you don't need the second pair of brackets in your statements:
if (!isset($foo)) $foo = '';
is enough.
To fix the issue of
<?php
$foo = $bar = $ping = $pong = '';
?>
throwing
Notice: Undefined variable: ...
<?php
#$foo = $bar = $ping = $pong = '';
?>
It will not fix it but it will not be shown nd will not stop the script from parsing.
What's the equivalent of the following (based in JS style) in PHP:
echo $post['story'] || $post['message'] || $post['name'];
So if story exists then post that; or if message exist post that, etc...
It would be (PHP 5.3+):
echo $post['story'] ?: $post['message'] ?: $post['name'];
And for PHP 7:
echo $post['story'] ?? $post['message'] ?? $post['name'];
There is a one-liner for that, but it's not exactly shorter:
echo current(array_filter(array($post['story'], $post['message'], $post['name'])));
array_filter would return you all non-null entries from the list of alternatives. And current just gets the first entry from the filtered list.
Since both or and || do not return one of their operands that's not possible.
You could write a simple function for it though:
function firstset() {
$args = func_get_args();
foreach($args as $arg) {
if($arg) return $arg;
}
return $args[-1];
}
As of PHP 7, you can use the null coalescing operator:
The null coalescing operator (??) has been added as syntactic sugar
for the common case of needing to use a ternary in conjunction with
isset(). It returns its first operand if it exists and is not NULL;
otherwise it returns its second operand.
// Coalescing can be chained: this will return the first
// defined value out of $_GET['user'], $_POST['user'], and
// 'nobody'.
$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';
Building on Adam's answer, you could use the error control operator to help suppress the errors generated when the variables aren't set.
echo #$post['story'] ?: #$post['message'] ?: #$post['name'];
http://php.net/manual/en/language.operators.errorcontrol.php
You can try it
<?php
echo array_shift(array_values(array_filter($post)));
?>
That syntax would echo 1 if any of these are set and not false, and 0 if not.
Here's a one line way of doing this which works and which can be extended for any number of options:
echo isset($post['story']) ? $post['story'] : isset($post['message']) ? $post['message'] : $post['name'];
... pretty ugly though. Edit: Mario's is better than mine since it respects your chosen arbitrary order like this does, but unlike this, it doesn't keep getting uglier with each new option you add.
Because variety is the spice of life:
echo key(array_intersect(array_flip($post), array('story', 'message', 'name')));
Is there a function in PHP to set default value of a variable if it is not set ?
Some inbuilt function to replace something like:
$myFruit = isset($_REQUEST['myfruit']) ? $_REQUEST['myfruit'] : "apple" ;
PHP kind of has an operator for this (since 5.3 I think) which would compress your example to:
$myFruit = $_REQUEST['myfruit'] ?: "apple";
However, I say "kind of" because it only tests if the first operand evaluates to false, and won't suppress notices if it isn't set. So if (as in your example) it might not be set then your original code is best.
The function analogous to dictionary.get is trivial:
function dget($dict, $key, $default) {
return isset($dict[$key]) ? $dict[$key] : $default;
}
For clarity, I'd still use your original code.
Edit: The userland implementation #2 of ifsetor() at http://wiki.php.net/rfc/ifsetor is a bit neater than the above function and works with non-arrays too, but has the same caveat that the default expression will always be evaluated even if it's not used:
function ifsetor(&$variable, $default = null) {
if (isset($variable)) {
$tmp = $variable;
} else {
$tmp = $default;
}
return $tmp;
}
As far as i know there exists nothing like this in PHP.
You may implement something like this yourself like
$myVar = "Using a variable as a default value!";
function myFunction($myArgument=null) {
if($myArgument===null)
$myArgument = $GLOBALS["myVar"];
echo $myArgument;
}
// Outputs "Hello World!":
myFunction("Hello World!");
// Outputs "Using a variable as a default value!":
myFunction();
// Outputs the same again:
myFunction(null);
// Outputs "Changing the variable affects the function!":
$myVar = "Changing the variable affects the function!";
myFunction();
You could also create a class implementing the ArrayAccess, which you pass 2 arrays during construction ($_REQUEST and an array with defaults) and make it choose the default value transparently.
Btw., relying on $_REQUEST is not a wise idea. See the manual on $_REQUEST for further information.
Instead of testing, if a key not exists and then return a default value, you can also fill your array with this values, before accessing it.
$expectedKeys = array('myfruit');
$requestData = array_merge (
array_combine(
$expectedKeys,
array_fill(0, count($expectedKeys), null)),
$_REQUEST);
$postData is now an array with all keys you expect (specified by $expectedKeys), but any entry, that is missing in $_REQUEST is null.
$myFruit = $requestData['myfruit'];
if (is_null($myFruit)) {
// Value not exists
}
But I also recommend to just stay with the ternary operator ?:.
There is a function called ife() in the CakePHP framework, you can find it here http://api13.cakephp.org/view_source/basics.php/, it is the last function!
You can use it like this:
echo ife($variable, $variable, 'default');