Why isset(null) throws an error but empty(null) not? - php

I just came across a strange situation. When I try the following code in $ php -a, I receive an error:
php > var_dump(isset(null));
PHP Fatal error: Cannot use isset() on the result of an expression
(you can use "null !== expression" instead) in php shell code on line
1
But when I do the same thing with empty(), everything is ok:
php > var_dump(empty(null));
bool(true)
Can anyone explain why I receive an error when I try isset(null)?
Update
Thank you all for your answers. I asked this question just to make sense of why isset() is behaving differently from empty().
To me, both of them are php functions and both accept a parameter. So, as any other function in php, calling isset(null) should be a valid statement. Aren't we passing null as a value to isset() function? So why php consider it as an expression?

Testing if an expression is "set" doesn't make sense. As per the manual, isset is used to
Determine if a variable is set and is not NULL.
If you want to check if an expression is null, use is_null, or as the error message suggests, null !== expression.
The manual for empty suggests something similar:
Determine whether a variable is considered to be empty.
until you read slightly further down, in the changelog:
5.5.0 empty() now supports expressions, rather than only variables.
Prior to this, empty(null) would have thrown an error along the lines of
Parse error: syntax error, unexpected ')', expecting :: (T_PAAMAYIM_NEKUDOTAYIM) in ... on line ...

Ok, I found something that I didn't know before in php which could be the answer to this question. According to the manual, isset() is not a function, but rather a language construct like if ... else, foreach and while:
Note: Because this [referring to isset()] is a language construct and not a function, it cannot be called using variable
functions.
There are a few more of these language constructs that can be easily confused with functions, including:
unset()
empty()
die()
include()
So now it makes sense why isset(null) doesn't work. We are trying to use a construct that expects a variable inside the parenthesis. Providing anything else other than a variable will result in syntax error during parsing of the code.

Related

isset fatal error in 5.6 but fine in 7

This snippet of code causes a PHP fatal error in 5.6, but works fine in 7.0 and above. There is no documented change to isset that I could find stating that it works with arrays as constants.
<?php
class Test
{
const A = [1];
}
echo isset(Test::A[0]);
Does anyone know of any documentation stating this was an actual change? Is it safe to use isset with arrays as constants?
PHP 5.6.30 error:
Fatal error: Cannot use isset() on the result of an expression (you can use "null !== expression" instead)
isset() is a language construct and not a function, so perhaps this paragraph (from http://php.net/manual/en/migration70.incompatible.php) applies:
PHP 7 now uses an abstract syntax tree when parsing source files. This
has permitted many improvements to the language which were previously
impossible due to limitations in the parser used in earlier versions
of PHP, but has resulted in the removal of a few special cases for
consistency reasons, which has resulted in backward compatibility
breaks.

Why can't I assign a variable inside of isset? - php

Recently, I've attempted to be tricky and assign a variable inside of an isset function. I tried to do it like so
if(isset($accountid =$_POST['Recipient']))
{
// my code here ...
}
However, when I do this I receive the error
syntax error, unexpected '=', expecting ',' or ')'
Here is the documentation for isset if you want to reference it in your answer.
bool isset ( mixed $var [, mixed $... ] )
This isn't the hugest deal - but I'd be interested to know why I can't do something along those lines!
isset is a language construct and not a true function. It is mentioned in the docs:
Warning
isset() only works with variables as passing anything else will result
in a parse error. For checking if constants are set use the defined()
function.
You are trying to pass a statement, this might be the reason. Here is a note I found in php.net manual for isset().
http://php.net/manual/en/function.isset.php
isset() only works with variables as passing anything else will result in a parse error.
You're putting an operation that doesn't return a pointer to a variable in a function that expects one.

empty() doesn't work with codeigniter input class

This is really weird.
Whenever I call something like
if(empty($this->input->post("foo")){//blabla}
The whole PHP is "down" and I get a blank page from the website (even when I don't pass through this empty(input) line).
I know this is not the right method and it is stupid, I change the code to
if(!$this->input->post("foo")){//blabla}
Better I guess ?
Seriously, how come the empty(input) breaks down the entire PHP page ? (I can't get any echo "something").
From the manual:
Note:
empty() only checks variables as anything else will result in a parse
error. In other words, the following will not work:
empty(trim($name)).
Update:
From php 5.5, empty() supports expressions too.
Changelog:
5.5.0 empty() now supports expressions, rather than only variables.
You cannot use empty with functions, and neither do you need to. empty is a special construct that only works on variables and triggers a fatal error otherwise. See The Definitive Guide To isset And empty.
You dont need to use empty with input class because if the post variable does not exists or contains null value input class returns false which automatically fails the if condition and your else block would work...

Why does empty expect T_PAAMAYIM_NEKUDOTAYIM when a non-variable is given?

<?php
define('foo', 'bar');
if (empty(foo)) {
echo 'qux';
}
http://codepad.org/G1TSK1c6
Parse error: syntax error, unexpected ')', expecting T_PAAMAYIM_NEKUDOTAYIM on line 4
I know that empty() only allows variables to be passed as an argument, but why does it expect a T_PAAMAYIM_NEKUDOTAYIM (i.e. ::) when I give it a constant?
The next logical thing the parser wants is a :: because foo is not a variable.
if (empty(foo::$bar)) {
}
Is the only thing, that works when empty() is not passed a variable. Your example is evaluated as empty(bar) where the parser assumes bar to be a class name and now expects a static member variable.
Saw this one while doing some research, although I know this is a bump I thought I would clarify this better.
empty() is not a function, but a language construct. This means that the underlaying parser code is different from that of parsing arguments sent to regular functions or methods. This may seem inconsistent at first when you experience serve error messages like that one, however lets break it down a little.
empty() is expecting to check something thats variable; a constant is not variable so that is not included in the list of possible syntaxes that can be passed to this construct, which makes perfect sense as you would otherwise be doing something illogical (checking for emptiness in a constant value).
The only other possible variables we have in PHP is good old variables and class properties as they are interchangeable, the relevant syntaxes can be represented like this:
<name> ::= [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
<variable> ::= $ <name>
<property> ::= <name> :: <name> || $ <name> :: <name> || $ <name> -\> <name>
This means that if you are passing a constant, PHP will read this as the class name and therefore is expecting the double colon token '::', hence why the error makes perfect sense.
Hope this was somewhat insightful ;-)
I looked into this, tried it on my local PHP installation and guess what? It worked without a hitch (PHP 5.5.6). After trying the same code on different versions of PHP, I found that it does not work on all versions of PHP < 5.5.x and works otherwise.
So then I took to PHP's documentation, more specifically its changelog from 5.4.x to 5.5.x, and found this:
http://www.php.net/manual/en/migration55.new-features.php#migration55.new-features.empty
empty() supports arbitrary expressions
Passing an arbitrary expression instead of a variable to empty() is now supported. For example:
if (empty(TRUE)) {
echo "This will NOT be printed.\n";
}
if (empty(FALSE)) {
echo "This will be printed.\n";
}
The above example will output:
This will be printed.
So if you're running PHP >= 5.5.x, then this will not be a problem.
You can test the code on different versions of PHP using this service: http://sandbox.onlinephpfunctions.com/. I could not, for the life of me, figure out how to save code samples (I always failed the captcha, even though it's dead simple - I think something MAY be broken on their end).
empty() expects variables and not constants. You should use defined() for constants.
Just a though, but I think this error is thrown when parsing the code.
foo, is not a variable, nor a string, therefore, in the context of parsing, the next solution may be class attribute., but it is not because there is no ::, but it should be because constants should not be used here, and it remains to be a class attribute or method.

PHP Fatal Error. Does empty() try to alter the results passed into it?

Ran into a strange problem in PHP today and I'm wondering if someone can explain it. While comparing two arrays I initially tried something like this:
echo empty(array_diff( array('foo','bar') , array('bar','foo') ))
This results in the following error:
Fatal Error: Can't use function return value in write context
Rewriting this as...
$dif = array_diff( array('foo','bar') , array('bar','foo') );
echo empty($dif);
...works perfectly. Empty should just be evaluating the value passed in to it, not writing to it, so what's going wrong here? Tested in both PHP 5.2.10 and PHP 5.3.2.
I've resolved the issue by using !count() instead of empty(), but I'm curious why it doesn't work in the first place. Is empty() trying to alter the result from array_diff?
Check the manual on empty():
Note: empty() only checks variables as anything else will result in a parse error. In other words, the following will not work: empty(trim($name)).
empty(), like e.g. echo() and die(), is a language construct, and therefore has different rules than a normal function (in which your example would work fine).

Categories