Command to return value if variable exists? - php

I often find myself writing something like this:
$val = (isset($dog->owner->name)) ? $dog->owner->name : "no owner";
Because PHP throws an error if you try to evaluate a variable that does not exist, the following will not work (PHP 5.3 and above for the new shorthand ternary syntax):
$val = ($dog->owner->name) ?: "no owner";
You can achieve the above if you turn off E_USER_NOTICE reporting, which is not something I want to do.
Is there a PHP command that will return the value of a variable if it is defined?

PHP doesn't have anything like this, but you can create your own. The key is passing by reference:
function getVar(&$var, $default=null) {
if( isset($var) ) return $var;
else return $default;
}
$blah = getVar($blah, "my default value");

No there is no command to check if the variable has a value assigned without doing what you've already done. You're going to have to either perform a check or explicitly make sure your variable has a value. Add the owner's name as a parameter in the class constructor or give it a default assignment on object creation. You can also create a method that performs this task so you can reuse the code.

You can try Error control operaors #
#$val = $dog->owner->name ?: "no owner";
echo $val, "\r\n";
And you will get what you want.

Related

PHP - Differenciate an undefined variable from a null variable [duplicate]

Is there a single function that can be created to tell whether a variable is NULL or undefined in PHP? I will pass the variable to the function (by reference if needed) but I won't know the name of the variable until runtime.
isset() and is_null() do not distinguish between NULL and undefined.
array_key_exists requires you to know the name of the variable as you're writing your code.
And I haven't found a way to determine the name of a variable without defining it.
Edit
I've also realized that passing a variable by reference automatically defines it.
Elaboration
Through the collection of these answers and comments I've determined that the short answer to my question is "No". Thank you for all the input.
Here are some details on why I needed this:
I've created a PHP function called LoadQuery() that pulls a particular SQL query from an array of queries and then prepares it for submission to MySQL. Most-importantly I scan the query for variables (like $UserID) that I then replace with their values from the current scope. In creating this function I needed a way to determine if a variable had been declared, and was NULL, empty, or had a value. This is why I may not know the name of the given variable until runtime.
Using modified example from PHP - Differenciate an undefined variable from a null variable
we can differentiate it:
$v1 = null;
echo (isset($v1) ? '$v1 set' : '$v1 not set') . PHP_EOL;
echo (is_null($v1) ? '$v1 null' : '$v1 not null') . PHP_EOL;
echo (empty($v1) ? '$v1 empty' : '$v1 not empty') . PHP_EOL;
echo (array_key_exists('v1', get_defined_vars()) ? '$v1 defined' : '$v1 not defined') . PHP_EOL;
echo PHP_EOL;
echo (isset($v2) ? '$v2 set' : '$v2 not set') . PHP_EOL;
echo (#is_null($v2) ? '$v2 null' : '$v2 not null') . PHP_EOL;
echo (empty($v2) ? '$v2 empty' : '$v2 not empty') . PHP_EOL;
echo (array_key_exists('v2', get_defined_vars()) ? '$v2 defined' : '$v2 not defined') . PHP_EOL;
prints:
$v1 not set
$v1 null
$v1 empty
$v1 defined
$v2 not set
$v2 null
$v2 empty
$v2 not defined
we can use array_key_exists(..., get_defined_vars()) and is_null(...) to detect both situations
You can't wrap this kind of logic in a function or method as any variable defined in a function signature will be implicitly "set". Try something like this (contains code smell)
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
error_reporting(E_ALL);
set_error_handler("exception_error_handler");
try {
if (null === $var) {
// null your variable is, hmmm
}
} catch (ErrorException $e) {
// variable is undefined
}
In PHP typically variables that have not been set or that have been unset are considered null. The meaning of null is "no value". There is a distinct difference between "no value" and a value left blank. For instance, if a user submitted a form with foo=&bar=baz, $_GET['foo'] is set to the value of empty string "", which is distinctly different from null which would be the value for any key other than 'foo' and 'bar'.
That all being said, you can find out if a variable was never set or unset, although they will always evaluate to true with is_null (is_null is the negative of isset with the exception that it will throw notices if the value was never set).
One way is if you have the variable in an array of some sort:
echo array_key_exists( $variableName, $theArray ) ? 'variable was set, possibly to null' : 'variable was never set';
If you need to check a global variable, use the $GLOBALS array:
echo array_key_exists( $variableName, $GLOBALS ) ? 'variable exists in global scope' : 'this global variable doesn\'t exist';
The alternative method I've come up with for figuring out whether the variable was set is a bit more involved, and really unnecessary unless this is a feature that you absolutely have to have (in which case you should be able to build it without too much difficulty).
It relies on the fact that is_null triggers a notice when a variable hasn't been set. Add an error handler that converts errors into Exceptions, and use a try...catch... block to catch the exception that's thrown and set a flag in the catch statement. Just after the catch block execute your code that relies on this feature.
It's a dirty-nasty-hack if you ask me, and completely unnecessary, as null should be considered the same as an unset variable.
Essentially the answer is no. There is not a single function you can create that will tell whether a runtime variable is null or is undefined. (by 'runtime variable' I mean a variable who's name you don't yet know at the time of coding. See Elaboration in the question above).
Relevant Observations:
There's no way to retrieve the name of a variable at runtime without giving it a value and hence declaring it.
If you pass a variable by reference, instead of by value, you're automatically declaring it. So then in the function you can't go back and determine whether it was declared before you passed it.
You can use array_key_exists('variable_name', $GLOBALS) as #zzzzBov stated, to see if a variable has been declared, but only if you know the name of the variable at coding time.
Possible 'Dirty' Solutions
As #Phil (and #zzzzBov) explained you could use a messy trick of capturing error messages that would get thrown when you reference an undeclared variable.
I also considered a method where you: Make note of all the keys in $GLOBALS, then store a unique value in your target variable (recording it's original value first for later use). And then search $GLOBALS looking for that unique value to determine the name of the variable AND (by comparing with your earlier look at $GLOBALS) determine if the variable existed before. But this also seems messy and unreliable.
You can get an array of the defined variables in the current scope with:
get_defined_vars();
This only works with globally defined variables. Because of scoping it won't work with local variables in functions or with class properties, but of course it's only one line so you could just copy it into a function.
function isNullOrUndefined($variable_name) {
global $$variable_name;
if (!isset($$variable_name) || is_null($$variable_name)) {
return true;
}
return false;
}
$foo = "foo";
$bar = null;
isNullOrUndefined("foo") //false
isNullOrUndefined("bar") //true
isNullOrUndefined("baz") //true
In PHP 5.2 or greater, I guess it is possible as follows:
// checking a variable (before and after it is defined)
$var_status1 = #is_defined( $variable, __LINE__, __FILE__ ); // don't put any additional code on this line
$variable = NULL;
$var_status2 = #is_defined( $variable, __LINE__, __FILE__ ); // don't put any additional code on this line
function is_defined( $var, $line, $file ) {
$e = error_get_last();
if ( $e !== NULL && $e['type'] === 8 && $e['line'] === $line && $e['file'] === $file ) {
return 'Undefined';
} else {
return 'Defined';
}
}
echo $var_status1 . '<br>';
echo $var_status2 . '<br>';
Note: I did not have time to test this solution in all possible situations (I just use it in a plugin I developed), so everyone is invited to find a flaw here.
what about this?
try {
$undefined_var
} catch (Exception $ex) {
$is_undefined = true;
}
if(empty($is_undefined)){ ... }

Function to Avoid Variable Undefined

I am trying to write a function to avoid getting variable undefined error. Right now, i have a code like this:
function check($str){
if(isset($str)){
$s = $str;
} else {
$s = "";
}
}
check($_GET['var']);
The get var is not set. I am getting a variable undefined error on my screen. How do i alter my function to not throw this error and just return "" if it is not set? I don't want to have to code 100 if statements to avoid getting variable undefined. Thanks.
We already have in PHP a construct to check that. It is called isset(). With it you can check whether a variable exists. If you would like to create it with some default values if it doesn't exist yet, we also have syntax for it. It's null-coalescing operator.
$_GET['var'] = $_GET['var'] ?? '';
// or since PHP 7.4
$_GET['var'] ??= '';
Although I'm not sure if it is the right way of doing it, for the sake of providing an answer you can pass the variable by reference, this allows you to get away with passing undefined variables and check if it is set inside the function..
function check(&$str){
if(!isset($str)){
$str = "not set";
}
}
check($_GET['var']);
echo $_GET['var'];

What is the best way to know is $_GET['example']=="somevalue"?

if((isset($_GET[example]))&&($_GET['example']=='somevalue')){ ... }
OR
if((!empty($_GET[example]))&&($_GET['example']=='somevalue')){ ... }
OR just
if($_GET['example']=='somevalue'){ ... }
I am asking that why I have seen many example where people check first if $_GET['example'] is set and then if $_GET['example']=='somevalue' ( first and second example above ).
I don't understand why not just use the last solution ( if $_GET['example']=='somevalue' then $_GET['example'] is obviously set ).
This question refers to any other variable ( $_POST, $_SERVER, ecc ).
if((isset($_GET[example]))&&($_GET['example']=='somevalue')){ ... }
Is the right one, you want to know that the "variable" exists (or is set) in order to use it. Empty just checks wether it has data of any kind or not.
For example:
<?php
$foo= 0;
if (empty($foo)) { // True because $foo is empty
echo '$foo is either 0, empty, or not set at all';
}
if (isset($foo)) { // True because $foo is set
echo '$foo is set even though it is empty';
}
if (isset($var)) { // FALSE because $var was not declared before
...
}
?>
The differences between isset and empty are subtle but important. They are most relevant when used alone. If you are checking that a variable exists and is a truethy value (e.g. any string that is not all spaces or 0s) you can use either interchangeably.
When to use isset
Use isset when it's important to know if the variable has been defined and is not null:
if (isset($maybeExistsMaybeNull)) {
// variable defined and is not NULL
}
When to use !empty
Use !empty when it's important to know if the variable has be defined and is truthy
if (!empty($mightBeEmpty)) {
// variable defined, and isn't "", " ", 0, "0" etc.
}
!empty is a great shorthand for exists and is something.
When to use array_key_exists
Use array_key_exists when it's important to know if the key exists and the value is of no importance:
if (array_key_exists('something', $array)) {
// $array['something'] exists, could be literally anything including null
}
When not to use isset
If your code looks like this:
if (isset($something) && $something) {
// code is shorter with !empty
}
When not to use !empty
If your code looks like this:
if (!empty($something) && $something === "") {
// you meant isset. this is unreachable.
}
Then you're writing code that can't be executed
Code that throws errors is error prone
Avoid writing code that issues notices/warnings that you are ignoring. For example in the question:
if((isset($_GET[example]))&&($_GET['example']=='somevalue')){ ... }
The first use of example is an undeclared constant. Or is it undeclared - what if you've got define('example', "foo"); somewhere else in the code.
if($_GET['example']=='somevalue'){ ... }
If the url doesn't contain ?example=.. that's going to issue a notice too.
Writing code without displaying errors means you can very easily miss mistakes like the first.
In context: isset and !empty are equivalent
For the example given, these two language constructs act exactly the same.
There is no case where one will act differently than the other, neither will issue a notice if the variable is undefined, and no measurable difference in performance between the two.
As others have said for checking things like $_GET and $_POST you would ideally want to use:
if ( isset($_GET['example']) && $_GET['example'] =='somevalue' ) {
// process data
}
So you always want to firstly make sure that the variable has been set (and not set to null) or in other words exists. Then proceed to check if the variable contains the data that you were expecting. If you try to make reference to a variable which doesn't exist (by not checking isset()) php will give you a notice saying 'undefined variable...etc etc'.
If you wanted to find out if a variable is set but are not concerned too much by what then you could use:
if ( !empty($_GET['example']) ) {
// process data
}
But I would be careful about using empty() on strings in this regard as empty can behave strangely with string data like '0' or ' '.
So I would always do the first one, to a) make sure the variable exists and b) is what you were expecting it to be.
This is something that you'll probably do a lot of and it helps to put together a class/functions which handles this checking for you so you dont have to do it everytime.
function checkValue($key, $value) {
if(array_key_exists($key, $_REQUEST)){
if ($_REQUEST[$key] == $value) {
return true;
} else {
return false;
}
} else {
return false;
}
}
I just use Request as a default instead of switching out (though it is preferable to switch in some cases between POST and GET for security (imo)).
Now you can just call this function anywhere
if (checkValue('Item', 'Tom') === true){} etc
the best is
if((isset($_GET[example]))&&('somevalue'==$_GET['example'])){ ... }
The difference between
'somevalue'==$_GET['example']
AND
$_GET['example']=='somevalue'
If you mistype the == and type = instead, the first notaion will raise an error to notify you.
if((isset($_GET[example]))&&($_GET['example']=='somevalue')){ ... }

Function to set default value of associative array if the key is not present

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');

Using reference to nonexistent value sets variable to NULL?

When passing a non-existent value by reference, PHP creates the value and sets it to NULL. I noticed it when memory increases were occurring while checking empty values in some functions. Take the following function:
function v(&$v,$d=NULL){return isset($v)?$v:$d;}
$bar = v($foo, $default);
This would be shorthand for:
if(isset($foo))
{
$bar = $foo;
}
else
{
$bar = $default;
}
However, when passing non-existent variables PHP creates them. In the case of variables - they are removed as soon as the method/function ends - but for checking super global arrays like $_GET or $_POST the array element is never removed causing extra memory usage.
$request_with = v($_SERVER['HTTP_X_REQUESTED_WITH']);
Can anyone explain why this happens and if it is a PHP todo fix or a feature for some other crazy use of values?
XeonCross' function v is a shorthand for the often used:
$val= isset($arr['elm']) ? $arr['elm'] : 'default'
to avoid the dreaded 'Undefined index: elm' notice. A nice helper function would be:
function ifset(&$v1, $v2 = null) {
return isset($v1) ? $v1 : $v2;
}
as Xeoncross suggested, so you could write the much nicer
$val = ifset($arr['elm'],'default')
however, this has a lot of interesting (?) quirks in our beloved "language" that we call PHP:
inside the function ifset, $v1 seems UNSET, so it correctly returns the value $v2 and you might conclude that ifset works ok. But afterwards $arr['elm'] is silently set to NULL. So consider the following:
function wtf(&$v) {
if (isset($v))
echo "It is set";
else
echo "It is NOT set";
}
$p=[];
wtf($p['notexist']); => It is NOT set
$p; => [ 'notexist' => NULL ]
But this is another delusion, as the isset() function returns false for NULL values as well:
$x=NULL;
isset($x) => false... huh??
Did we expect this? well.. it is in the documentation, so this is by design as well. Welcome to the wonderful world of php.
The reason you have the memory leak, is because you're telling it to.
When you ask for a reference parameter, PHP will provide you with one. When you are calling a function with an unset variable, PHP will set the variable and then pass the reference to that new variable. When you call it with a superglobal, it creates the missing index. That's because you told it to.
However, I must ask why specifically do you need variable references? 99.9% of the time you don't really need them. I suspect that it'll work just fine to do:
function v($v, $d = null) { return isset($v) ? $v : $d; }
Or, if you really must use references (which you can't get around your original problem with), you should also return a reference:
function &v(&$v, $d = null) {
if (isset($v)) {
return $v;
}
return $d;
}
Otherwise it's pointless to take a reference and not return one...

Categories