Related
I have (or not) a variable $_GET['myvar'] coming from my query string and I want to check if this variable exists and also if the value corresponds to something inside my if statement:
What I'm doing and think is not the best way to do:
if(isset($_GET['myvar']) && $_GET['myvar'] == 'something'): do something
My question is, exist any way to do this without declare the variable twice?
That is a simple case but imagine have to compare many of this $myvar variables.
Sadly that's the only way to do it. But there are approaches for dealing with larger arrays. For instance something like this:
$required = array('myvar', 'foo', 'bar', 'baz');
$missing = array_diff($required, array_keys($_GET));
The variable $missing now contains a list of values that are required, but missing from the $_GET array. You can use the $missing array to display a message to the visitor.
Or you can use something like that:
$required = array('myvar', 'foo', 'bar', 'baz');
$missing = array_diff($required, array_keys($_GET));
foreach($missing as $m ) {
$_GET[$m] = null;
}
Now each required element at least has a default value. You can now use if($_GET['myvar'] == 'something') without worrying that the key isn't set.
Update
One other way to clean up the code would be using a function that checks if the value is set.
function getValue($key) {
if (!isset($_GET[$key])) {
return false;
}
return $_GET[$key];
}
if (getValue('myvar') == 'something') {
// Do something
}
As of PHP7 you can use the Null Coalescing Operator ?? to avoid the double reference:
// $_GET['myvar'] isn't set...
echo ($_GET['myvar'] ?? '') == 'hello' ? "hello!\n" : "goodbye!\n";
// $_GET['myvar'] is set but != 'hello'
$_GET['myvar'] = 'farewell';
echo ($_GET['myvar'] ?? '') == 'hello' ? "hello!\n" : "goodbye!\n";
// $_GET['myvar'] is set and == 'hello'
$_GET['myvar'] = 'hello';
echo ($_GET['myvar'] ?? '') == 'hello' ? "hello!\n" : "goodbye!\n";
Output:
goodbye!
goodbye!
hello!
Code demo on 3v4l.org
In general, the expression
$a ?? $b
is equivalent to
isset($a) ? $a : $b
Note that in the code example it is necessary to place parentheses around $_GET['myvar'] ?? '' as == has higher precedence than ?? and thus
$_GET['myvar'] ?? '' == 'hello'
would evaluate to:
$_GET['myvar'] ?? ('' == 'hello')
which would be true as long as $_GET['myvar'] was set and "truthy" (see the manual) and false otherwise (since '' == 'hello' is false).
Precedence code demo on 3v4l.org
If you're looking for a one-liner to check the value of a variable you're not sure is set yet, this works:
if ((isset($variable) ? $variable : null) == $value) { }
The only possible downside is that if you're testing for true/false - null will be interpreted as equal to false.
As mellowsoon suggest, you might consider this approach:
required = array('myvar' => "defaultValue1", 'foo' => "value2", 'bar' => "value3", 'baz' => "value4");
$missing = array_diff($required, array_keys($_GET));
foreach($missing as $key => $default ) {
$_GET[$key] = $default ;
}
You put the default values and set the not recieved parameters to a default value :)
My question is, exist any way to do this without declare the variable twice?
No, there is no way to do this correctly without doing two checks. I hate it, too.
One way to work around it would be to import all relevant GET variables at one central point into an array or object of some sort (Most MVC frameworks do this automatically) and setting all properties that are needed later. (Instead of accessing request variables across the code.)
Thanks Mellowsoon and Pekka, I did some research here and come up with this:
Check and declare each variable as null (if is the case) before start to use (as recommended):
!isset($_GET['myvar']) ? $_GET['myvar'] = 0:0;
*ok this one is simple but works fine, you can start to use the variable everywhere after this line
Using array to cover all cases:
$myvars = array( 'var1', 'var2', 'var3');
foreach($myvars as $key)
!isset($_GET[$key]) ? $_GET[$key] =0:0;
*after that you are free to use your variables (var1, var2, var3 ... etc),
PS.: function receiving a JSON object should be better (or a simple string with separator for explode/implode);
... Better approaches are welcome :)
UPDATE:
Use $_REQUEST instead of $_GET, this way you cover both $_GET and $_POST variables.
!isset($_REQUEST[$key]) ? $_REQUEST[$key] =0:0;
why not create a function for doing this, convert the variable your want to check into a real variable, ex.
function _FX($name) {
if (isset($$name)) return $$name;
else return null;
}
then you do _FX('param') == '123', just a thought
I use all time own useful function exst() which automatically declare variables.
Example -
$element1 = exst($arr["key1"]);
$val2 = exst($_POST["key2"], 'novalue');
/**
* Function exst() - Checks if the variable has been set
* (copy/paste it in any place of your code)
*
* If the variable is set and not empty returns the variable (no transformation)
* If the variable is not set or empty, returns the $default value
*
* #param mixed $var
* #param mixed $default
*
* #return mixed
*/
function exst( & $var, $default = "")
{
$t = "";
if ( !isset($var) || !$var ) {
if (isset($default) && $default != "") $t = $default;
}
else {
$t = $var;
}
if (is_string($t)) $t = trim($t);
return $t;
}
A solution that I have found from playing around is to do:
if($x=&$_GET["myvar"] == "something")
{
// do stuff with $x
}
<?php
function myset(&$var,$value=false){
if(isset($var)):
return $var == $value ? $value : false;
endif;
return false;
}
$array['key'] = 'foo';
var_dump(myset($array['key'],'bar')); //bool(false)
var_dump(myset($array['key'],'foo'));//string(3) "foo"
var_dump(myset($array['baz'],'bar'));//bool(false)
This is similar to the accepted answer, but uses in_array instead. I prefer to use empty() in this situation. I also suggest using the new shorthand array declaration which is available in PHP 5.4.0+.
$allowed = ["something","nothing"];
if(!empty($_GET['myvar']) && in_array($_GET['myvar'],$allowed)){..}
Here is a function for checking multiple values at once.
$arrKeys = array_keys($_GET);
$allowed = ["something","nothing"];
function checkGet($arrKeys,$allowed) {
foreach($arrKeys as $key ) {
if(in_array($_GET[$key],$allowed)) {
$values[$key];
}
}
return $values;
}
Well, you could get by with just if($_GET['myvar'] == 'something') since that condition presumes that the variable also exists. If it doesn't, the expression will also result in false.
I think it's ok to do this inside conditional statements like above. No harm done really.
No official reference but it worked when I tried this:
if (isset($_GET['myvar']) == 'something')
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']);
Can someone give me an example of how to use the PHP ternary operator which will check for a variable using $_GET (which can be defined in the URL), if it's not in the URL then check if the var was set in another PHP file. If it wasn't set in the URL or another PHP file, then I want it to equal "default".
$myVar = isset($_GET["someVar"]) ? $_GET["someVar"] : (isset($someVar) ? $someVar : "default");
$value = isset($_GET['somevar']) ? $_GET['var'] : $default_value;
On the most recent PHP versions, there's a shortcut version of this:
$value = isset($_GET['somevar']) ?: $default_value; (not the same as the first version)
You can use $GLOBALS['nameofvar'] to see if a particular PHP variable has been defined as well, though this'll be problematic if you're doing the check inside a function.
Are you looking for something like this:
if(isset($_GET["MyVar"]))
{
$newVar = $_GET["MyVar"];
}
else if(isset($myVar))
{
$newVar = $myVar;
}
else
{
$newVar = "default";
}
or
$newVar = isset($_GET["MyVar"]) ? $_GET["MyVar"] : (isset($myVar) ? $myVar : "default");
I wonder if there any better ideas to solve the problem below,
I have a form with a number of input fields, such as,
<input name="pg_title" type="text" value="" />
<input name="pg_subtitle" type="text" value="" />
<input name="pg_description" type="text" value="" />
<input name="pg_backdate" type="text" value="" />
etc
But sometimes don't need certain input fields above in my form, for instance, I only need the page title for my db injection,
<input name="pg_title" type="text" value="" />
etc
And I have another php page to handle the $_POST data,
$pg_title = null;
$pg_subtitle = null;
$pg_description = null;
$pg_backdate = null;
if(isset($_POST['pg_title']) && !empty($_POST['pg_title']) ) $pg_title = $_POST['pg_title'];
if(isset($_POST['pg_subtitle']) && !empty($_POST['pg_subtitle']) ) $pg_subtitle = $_POST['pg_subtitle'];
if(isset($_POST['pg_description']) && !empty($_POST['pg_description']) ) $pg_description = $_POST['pg_description'];
if(isset($_POST['pg_backdate']) && !empty($_POST['pg_backdate']) ) $pg_backdate = $_POST['pg_backdate'];
Every time I will have to check if the $_POST of a certain input field is set and not empty, otherwise its variable will be set to null, so that I won't inject an empty space into my DB.
I find the isset and !empty in the if-condition are very repetitive when I have a long list of variables to handle.
Is there any default PHP function to 'shorten' the process above? Or do I have to write a user-defined function to handle this?
Or maybe there is another way to do this?
Just some extra code in my php page that handle the $_POST data,
$sql = "
UPDATE root_pages
SET
pg_url = ?,
pg_title = ?,
pg_subtitle = ?,
pg_backdate = ?,
pg_description = ?,
...
updated_by = ?
WHERE pg_id = ?
";
$result = $connection->run_query($sql,array(
$pg_url,
$pg_title,
$pg_subtitle,
$pg_backdate,
$pg_description,
...
$pg_id
));
as you see that $pg_subtitle, $pg_backdate, $pg_description, etc always present in my query. so if I get $pg_subtitle = '' instead of $pg_subtitle = null when there is no data in it, my db record will have an empty space for that column.
isset && !empty is redundant. The empty language construct is basically shorthand for !isset($foo) || !$foo, with !empty being equivalent to isset($foo) && $foo. So you can shorten your code by leaving out the isset check.
A much simpler way is:
$values = array('pg_title' => null, 'pg_subtitle' => null, …);
$values = array_merge($values, $_POST);
// use $values['pg_title'] etc.
If you don't want your default null values to be overwritten by falsey values, e.g. '', you can do something like this:
$values = array_merge($values, array_filter($_POST));
Just be aware that '0' is falsey as well.
You can use a simple function
function post_value_or($key, $default = NULL) {
return isset($_POST[$key]) && !empty($_POST[$key]) ? $_POST[$key] : $default;
}
Then use:
$pg_title = post_value_or('pg_title');
// OR with a default
$pg_title = post_value_or('pg_title', 'No Title');
empty($var) is an abbreviation for !( isset($var) && $var ).
So !empty($_POST['...']) will be sufficient for your situation — the isset call you have currently is redundant.
User-defined function, I 'm afraid. But they come out short enough. I have one lying around somewhere if you want to take a look, but it's really trivial as you can imagine.
Update:
Here's one I found:
define('PARAM_INT', 0);
define('PARAM_STR', 1);
function get_param($name, $default = null, $type = PARAM_INT) {
$value = $default;
if (isset($_POST[$name])) {
$value = $_POST[$name];
}
else if (isset($_GET[$name])) {
$value = $_GET[$name];
}
switch($type) {
case PARAM_INT:
$value = (int)$value;
break;
case PARAM_STR:
break;
default:
// error your heart out here
}
return $value;
}
Of course now all the cool kids do it with filter_var, but the idea is the same.
+1 for array_merge() but I think that nevertheless short form for:
if (isset($_POST['some_var']) and !empty($_POST['some_var'])) $some_var = $_POST['some_var'];
else $some_var = NULL;
should be:
$some_var = $_POST['some_var'] ? $_POST['some_var'] : NULL;
yes, it causes "undefined index" notice, but it checks for both existance and emptiness
EDIT: and returns NULL of course, as OP asked.
During a small research, I've found an interesting "Control Flow Function" for this case, I've never used before: NULLIF()
So you can perform this task without PHP. Just wrap all variables in it:
NULLIF('".$_REQUEST['some_var']."', '')
in your query instead of '".$_REQUEST['some_var']."'
If variable is empty or doesn't exist it will be NULLIF('', '') as far as '' == '' it will return NULL. Otherwise it will return first arg == your variable.
Consider using the available-by-default filter extension's filter_input function. You'll avoid the missing index Notice and get data sanitization at the same time.
I do not have enough rep to comment. However, the suggestion that vladkras made to use:
$some_var = $_POST['some_var'] ? $_POST['some_var'] : NULL;
is not E_ALL compliant. You should be checking array keys before accessing them using either empty() or isset() as others have suggested. Especially for user input.
Also, his second suggestion to use the MySQL function "NULLIF()" as in the following manner:
NULLIF('".$_REQUEST['some_var']."', '')
is even worse. Inserting unsanitized user input directly into a SQL query is a primary vector for a SQL injection attack.
I'm always making myself unpoular with that. But the best approach is to get over the micro optimization mantra and use the syntax construct which was devised for that #.
Factually I'm lying. I'm all too often using isset() myself. (But at least I know it's not very bright.)
And for new projects I'm now using object-oriented superglobals, which combine filtering and implicit isset tests into $_POST, $_GET, $_REQUEST wrappers. $_REQUEST->ascii["title"] or $_GET["raw"] don't bring up debug messages anymore.
This function check if variable is set, is not empty, eventually if has any value.
/**
* #param var - testing variable
* #param value
* #return boolean
*/
function is(&$var, $value = null){
if(!is_null($value)){ return IsSet($var) && $var == $value; }
return IsSet($var) && !empty($var);
}
echo $_GET['id']; // this produce Warning
echo is($_GET['id'])?'1':'0'; // return false
echo $_GET['id']; // after first using function is(), will not be produce Warning!!!
is($_GET['id']); // return false
IsSet($_GET['id']); // return false
$_GET['id'] = 7;
is($_GET['id'], 7); // return true;
I have (or not) a variable $_GET['myvar'] coming from my query string and I want to check if this variable exists and also if the value corresponds to something inside my if statement:
What I'm doing and think is not the best way to do:
if(isset($_GET['myvar']) && $_GET['myvar'] == 'something'): do something
My question is, exist any way to do this without declare the variable twice?
That is a simple case but imagine have to compare many of this $myvar variables.
Sadly that's the only way to do it. But there are approaches for dealing with larger arrays. For instance something like this:
$required = array('myvar', 'foo', 'bar', 'baz');
$missing = array_diff($required, array_keys($_GET));
The variable $missing now contains a list of values that are required, but missing from the $_GET array. You can use the $missing array to display a message to the visitor.
Or you can use something like that:
$required = array('myvar', 'foo', 'bar', 'baz');
$missing = array_diff($required, array_keys($_GET));
foreach($missing as $m ) {
$_GET[$m] = null;
}
Now each required element at least has a default value. You can now use if($_GET['myvar'] == 'something') without worrying that the key isn't set.
Update
One other way to clean up the code would be using a function that checks if the value is set.
function getValue($key) {
if (!isset($_GET[$key])) {
return false;
}
return $_GET[$key];
}
if (getValue('myvar') == 'something') {
// Do something
}
As of PHP7 you can use the Null Coalescing Operator ?? to avoid the double reference:
// $_GET['myvar'] isn't set...
echo ($_GET['myvar'] ?? '') == 'hello' ? "hello!\n" : "goodbye!\n";
// $_GET['myvar'] is set but != 'hello'
$_GET['myvar'] = 'farewell';
echo ($_GET['myvar'] ?? '') == 'hello' ? "hello!\n" : "goodbye!\n";
// $_GET['myvar'] is set and == 'hello'
$_GET['myvar'] = 'hello';
echo ($_GET['myvar'] ?? '') == 'hello' ? "hello!\n" : "goodbye!\n";
Output:
goodbye!
goodbye!
hello!
Code demo on 3v4l.org
In general, the expression
$a ?? $b
is equivalent to
isset($a) ? $a : $b
Note that in the code example it is necessary to place parentheses around $_GET['myvar'] ?? '' as == has higher precedence than ?? and thus
$_GET['myvar'] ?? '' == 'hello'
would evaluate to:
$_GET['myvar'] ?? ('' == 'hello')
which would be true as long as $_GET['myvar'] was set and "truthy" (see the manual) and false otherwise (since '' == 'hello' is false).
Precedence code demo on 3v4l.org
If you're looking for a one-liner to check the value of a variable you're not sure is set yet, this works:
if ((isset($variable) ? $variable : null) == $value) { }
The only possible downside is that if you're testing for true/false - null will be interpreted as equal to false.
As mellowsoon suggest, you might consider this approach:
required = array('myvar' => "defaultValue1", 'foo' => "value2", 'bar' => "value3", 'baz' => "value4");
$missing = array_diff($required, array_keys($_GET));
foreach($missing as $key => $default ) {
$_GET[$key] = $default ;
}
You put the default values and set the not recieved parameters to a default value :)
My question is, exist any way to do this without declare the variable twice?
No, there is no way to do this correctly without doing two checks. I hate it, too.
One way to work around it would be to import all relevant GET variables at one central point into an array or object of some sort (Most MVC frameworks do this automatically) and setting all properties that are needed later. (Instead of accessing request variables across the code.)
Thanks Mellowsoon and Pekka, I did some research here and come up with this:
Check and declare each variable as null (if is the case) before start to use (as recommended):
!isset($_GET['myvar']) ? $_GET['myvar'] = 0:0;
*ok this one is simple but works fine, you can start to use the variable everywhere after this line
Using array to cover all cases:
$myvars = array( 'var1', 'var2', 'var3');
foreach($myvars as $key)
!isset($_GET[$key]) ? $_GET[$key] =0:0;
*after that you are free to use your variables (var1, var2, var3 ... etc),
PS.: function receiving a JSON object should be better (or a simple string with separator for explode/implode);
... Better approaches are welcome :)
UPDATE:
Use $_REQUEST instead of $_GET, this way you cover both $_GET and $_POST variables.
!isset($_REQUEST[$key]) ? $_REQUEST[$key] =0:0;
why not create a function for doing this, convert the variable your want to check into a real variable, ex.
function _FX($name) {
if (isset($$name)) return $$name;
else return null;
}
then you do _FX('param') == '123', just a thought
I use all time own useful function exst() which automatically declare variables.
Example -
$element1 = exst($arr["key1"]);
$val2 = exst($_POST["key2"], 'novalue');
/**
* Function exst() - Checks if the variable has been set
* (copy/paste it in any place of your code)
*
* If the variable is set and not empty returns the variable (no transformation)
* If the variable is not set or empty, returns the $default value
*
* #param mixed $var
* #param mixed $default
*
* #return mixed
*/
function exst( & $var, $default = "")
{
$t = "";
if ( !isset($var) || !$var ) {
if (isset($default) && $default != "") $t = $default;
}
else {
$t = $var;
}
if (is_string($t)) $t = trim($t);
return $t;
}
A solution that I have found from playing around is to do:
if($x=&$_GET["myvar"] == "something")
{
// do stuff with $x
}
<?php
function myset(&$var,$value=false){
if(isset($var)):
return $var == $value ? $value : false;
endif;
return false;
}
$array['key'] = 'foo';
var_dump(myset($array['key'],'bar')); //bool(false)
var_dump(myset($array['key'],'foo'));//string(3) "foo"
var_dump(myset($array['baz'],'bar'));//bool(false)
This is similar to the accepted answer, but uses in_array instead. I prefer to use empty() in this situation. I also suggest using the new shorthand array declaration which is available in PHP 5.4.0+.
$allowed = ["something","nothing"];
if(!empty($_GET['myvar']) && in_array($_GET['myvar'],$allowed)){..}
Here is a function for checking multiple values at once.
$arrKeys = array_keys($_GET);
$allowed = ["something","nothing"];
function checkGet($arrKeys,$allowed) {
foreach($arrKeys as $key ) {
if(in_array($_GET[$key],$allowed)) {
$values[$key];
}
}
return $values;
}
Well, you could get by with just if($_GET['myvar'] == 'something') since that condition presumes that the variable also exists. If it doesn't, the expression will also result in false.
I think it's ok to do this inside conditional statements like above. No harm done really.
No official reference but it worked when I tried this:
if (isset($_GET['myvar']) == 'something')