# [RFC] Allow non-variable arguments to empty() and isset()

- Thread: https://externals.io/message/59804
- Original archive: https://news-web.php.net/php.internals/59804
- Started by Nikita Popov on 2012-04-12T21:42:45+00:00
- Messages: 30
- Page 1 of 2: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/59804.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #59804 — Nikita Popov — 2012-04-12T21:42:45+00:00

URL: https://externals.io/message/59804#59804

Hi internals!

As per the comments I created an RFC, proposing to allow arbitrary
expressions to be passed to empty() and isset():

https://wiki.php.net/rfc/empty_isset_exprs

The patch is available as a PR:

https://github.com/php/php-src/pull/54

Nikita

PS: I added isset() too, to address the consistency concerns mentioned on IRC.

---

## #59805 — Galen Wright-Watson — 2012-04-12T22:42:34+00:00

URL: https://externals.io/message/59804#59805 · In reply to: #59804

On Thu, Apr 12, 2012 at 2:42 PM, Nikita Popov <nikita.ppv@googlemail.com>wrote:

>
> As per the comments I created an RFC, proposing to allow arbitrary
> expressions to be passed to empty() and isset():
>
> https://wiki.php.net/rfc/empty_isset_exprs
>
> The patch is available as a PR:
>
> https://github.com/php/php-src/pull/54
>
> Nikita
>
> PS: I added isset() too, to address the consistency concerns mentioned on
> IRC.
>
> Just to be clear, under the new behavior, calling "empty" or "isset" on
undefined variables and undefined array indices shouldn't produce a notice
when `E_NOTICE` is set, correct? Basically, the change isn't regressive.

    <?php
    error_reporting(E_ALL);
    echo empty($foo) ? "\$foo isn't set\n" : "foo: $foo\n";
    # result: "$foo isn't set", and no "Undefined variable" notice.

From my reading of the patch this is true, but I want to make sure I'm not
missing something. If this is so, how about adding appropriate regression
tests to empty_with_expr.phpt and empty_with_isset.phpt?

---

## #59874 — Nikita Popov — 2012-04-13T12:12:19+00:00

URL: https://externals.io/message/59804#59874 · In reply to: #59805

On Fri, Apr 13, 2012 at 12:42 AM, Galen Wright-Watson
<ww.galen@gmail.com> wrote:
> Just to be clear, under the new behavior, calling "empty" or "isset" on
> undefined variables and undefined array indices shouldn't produce a notice
> when `E_NOTICE` is set, correct? Basically, the change isn't regressive.
Yup, that's right. So the change is BC-safe :)

> If this is so, how about adding appropriate regression
> tests to empty_with_expr.phpt and empty_with_isset.phpt?
The normal empty()/isset() behavior (including the suppression of the
notice) is tested in a few other tests, that's why I didn't add
additional tests for it there :)

Nikita

---

## #60372 — Patrick ALLAERT — 2012-04-30T07:50:44+00:00

URL: https://externals.io/message/59804#60372 · In reply to: #59804

Hi,

2012/4/12 Nikita Popov <nikita.ppv@googlemail.com>:
> PS: I added isset() too, to address the consistency concerns mentioned on IRC.

I would have voted +1 if it didn't contain the isset() change. None of
the examples used in the isset_with_expr.phpt test seems logic to me.

Care to explain the consistency concerns here?

Patrick

---

## #60376 — Nikita Popov — 2012-04-30T12:39:32+00:00

URL: https://externals.io/message/59804#60376 · In reply to: #60372

> Hi,
>
> 2012/4/12 Nikita Popov <nikita.ppv@googlemail.com>:
> > […]
>
> I would have voted +1 if it didn't contain the isset() change. None of
> the examples used in the isset_with_expr.phpt test seems logic to me.
>
> Care to explain the consistency concerns here?
The concerns came from laruence, so maybe he could drop a comment here
:) Basically, empty() and isset() are very similar in their nature, so
changing only one of them might seem inconsistent.

Personally I don't see much use in allowing expressions in isset().
People being confused by empty(trim($_GET['foo'])) not working is
quite common, but I've never heard of somebody trying to use isset()
on a function call. The name already makes clear that it's intended
for use on variables.

So, I'm not quite sure what I'm supposed to do about this. Should I
add two vote options, one for empty() only, one for both?

Nikita

---

## #60377 — Nikita Popov — 2012-04-30T13:05:45+00:00

URL: https://externals.io/message/59804#60377 · In reply to: #60372

> Hi,
>
> 2012/4/12 Nikita Popov <nikita.ppv@googlemail.com>:
> > […]
>
> I would have voted +1 if it didn't contain the isset() change. None of
> the examples used in the isset_with_expr.phpt test seems logic to me.
>
> Care to explain the consistency concerns here?
>
> Patrick

I changed the vote to have three options: "Both empty() and isset()",
"Only empty()" or "None"

https://wiki.php.net/rfc/empty_isset_exprs#vote

Nikita

---

## #60380 — Pierre Joye — 2012-04-30T20:26:53+00:00

URL: https://externals.io/message/59804#60380 · In reply to: #60377

hi,



> I changed the vote to have three options: "Both empty() and isset()",
> "Only empty()" or "None"
>
> https://wiki.php.net/rfc/empty_isset_exprs#vote

Please post a top thread to notice everyone about this new vote with a
short explanation.

Yes, I told you that on IRC a good dozen times since you sent this
mail here, but there are good reasons why we do so. For one, many do
not follow any single thread on internals and I would not have noticed
that mail if I was not on IRC today. So please do it, or the votes
result, no matter the outcome, cannot be accepted.

Thanks for your understanding,
-- 
Pierre

@pierrejoye | http://blog.thepimp.net | http://www.libgd.org

---

## #60398 — Ferenc Kovacs — 2012-05-01T16:43:46+00:00

URL: https://externals.io/message/59804#60398 · In reply to: #60376

On Mon, Apr 30, 2012 at 2:39 PM, Nikita Popov <nikita.ppv@googlemail.com>wrote:

> On Mon, Apr 30, 2012 at 9:50 AM, Patrick ALLAERT <patrickallaert@php.net>
> wrote:
> > […]
> on IRC.
> > […]
> The concerns came from laruence, so maybe he could drop a comment here
> :) Basically, empty() and isset() are very similar in their nature, so
> changing only one of them might seem inconsistent.
>
> Personally I don't see much use in allowing expressions in isset().
> People being confused by empty(trim($_GET['foo'])) not working is
> quite common, but I've never heard of somebody trying to use isset()
> on a function call. The name already makes clear that it's intended
> for use on variables.


albeit I'm not laruence, but I also supported the idea to keep consistency
across the allowed params of empty and isset.
here is my reasoning:
- both isset and empty are language constructs, which many people use
almost interchangeability, changing one of them in a way that the same
expression works with one of them, but blows up with a parse error seems
wrong to me.
- maybe you think that isset doesn't really make sense with expressions,
but don't forget that this patch would also allow constants to be used with
empty/isset, and imo isset(some_constant); would be useful and maybe more
straightforward for the people new to the language.

-- 
Ferenc Kovács
@Tyr43l - http://tyrael.hu

---

## #60399 — Etienne Kneuss — 2012-05-01T16:52:09+00:00

URL: https://externals.io/message/59804#60399 · In reply to: #60398

Hi,


>
> albeit I'm not laruence, but I also supported the idea to keep consistency
> across the allowed params of empty and isset.
> here is my reasoning:
> - both isset and empty are language constructs, which many people use
> almost interchangeability, changing one of them in a way that the same
> expression works with one of them, but blows up with a parse error seems
> wrong to me.
> - maybe you think that isset doesn't really make sense with expressions,
> but don't forget that this patch would also allow constants to be used with
> empty/isset, and imo isset(some_constant); would be useful and maybe more
> straightforward for the people new to the language.


So isset(UNDEFINEDCONSTANT) will be isset("UNDEFINEDCONSTANT") which will/should
1) yield a notice, which is unnexpected for isset
2) return true, which is also unexpected.

I don't see much point in that.

Best regards,

-- 
Etienne Kneuss
http://www.colder.ch

---

## #60400 — Patrick ALLAERT — 2012-05-01T17:24:05+00:00

URL: https://externals.io/message/59804#60400 · In reply to: #60398

2012/5/1 Ferenc Kovacs <tyra3l@gmail.com>:
> On Mon, Apr 30, 2012 at 2:39 PM, Nikita Popov <nikita.ppv@googlemail.com>wrote:
> - both isset and empty are language constructs, which many people use
> almost interchangeability, changing one of them in a way that the same
> expression works with one of them, but blows up with a parse error seems
> wrong to me.

I wish that more wrong usages could blow up with parse errors way
before waiting for the incorrect line to be run.
While there is some valid use cases for empty() I see none for
isset(), it must remain a targeted and specific construct IMHO.

> - maybe you think that isset doesn't really make sense with expressions,

exact :)

> but don't forget that this patch would also allow constants to be used with
> empty/isset.

That is not a very good think IMO.

For the same reason: this patch would also allow writing: empty( false
) or empty( null ) which are both clueless.
The fact that this patch would now allow syntactically doubtful things
doesn't mean they should be encouraged nor propagated to isset().

Cheers,
Patrick

---

## #60403 — Ferenc Kovacs — 2012-05-01T18:34:23+00:00

URL: https://externals.io/message/59804#60403 · In reply to: #60400

On Tue, May 1, 2012 at 7:24 PM, Patrick ALLAERT <patrickallaert@php.net>wrote:

> 2012/5/1 Ferenc Kovacs <tyra3l@gmail.com>:
> > […]
>
> I wish that more wrong usages could blow up with parse errors way
> before waiting for the incorrect line to be run.
>

One could argue that then you should pick a compiled language.


> While there is some valid use cases for empty() I see none for
> isset(), it must remain a targeted and specific construct IMHO.
>

I agree that there is less valid use-cases, but I feel that keeping the two
method consistent about this is more important.


>
> > […]
>
> exact :)
>
> > […]
> with
> > […]
>
> That is not a very good think IMO.
>
> For the same reason: this patch would also allow writing: empty( false
> ) or empty( null ) which are both clueless.
>

how is that different than for example writing is_null(null) ?


> The fact that this patch would now allow syntactically doubtful things
> doesn't mean they should be encouraged nor propagated to isset().
>

we are already have that all over the place, I don't think that this
particular patch will change anything about that.
could you elaborate on this part a little bit?
I mean you can write "stupid" code right now ($null=null;isset($null);
instead of isset(null);), I can't see how would this patch worsen the
situation. If anything, the silly code could be understood easier, as you
wouldn't need to debug the value of the $null variable passed in.
So I think that
1, we already too late to prevent that kind of code
2. even if we could, I don't think that the currently discussed patch would
really encourage that kind of code
3, there are/could be valid use-cases for isset
4, isset and empty should work the same way in regards of the argument
parsing.

ofc. this is only my opinion, if I am the minority here, then it is fine
too, I just wanted to explain what was the reasoning behind that discussion.

-- 
Ferenc Kovács
@Tyr43l - http://tyrael.hu

---

## #60405 — Ferenc Kovacs — 2012-05-01T19:51:55+00:00

URL: https://externals.io/message/59804#60405 · In reply to: #60399

>
>
> So isset(UNDEFINEDCONSTANT) will be isset("UNDEFINEDCONSTANT") which
> will/should
> 1) yield a notice, which is unnexpected for isset
> 2) return true, which is also unexpected.
>
> I don't see much point in that.
>
>
yep, and if we allow expressions then it is the expected behavior, but you
are right that this is will change the current standard that isset/empty
can't raise a notice.
but this isn't specific to isset, empty will also follow the same pattern.

-- 
Ferenc Kovács
@Tyr43l - http://tyrael.hu

---

## #60408 — Xinchen Hui — 2012-05-02T01:31:10+00:00

URL: https://externals.io/message/59804#60408 · In reply to: #60405

Sent from my iPhone

在 2012-5-2，3:52，Ferenc Kovacs <tyra3l@gmail.com> 写道：

> > […]
> yep, and if we allow expressions then it is the expected behavior, but you
> are right that this is will change the current standard that isset/empty
> can't raise a notice.
> but this isn't specific to isset, empty will also follow the same pattern.
>
This is really a issue .

Thanks
> --
> Ferenc Kovács
> @Tyr43l - http://tyrael.hu

---

## #60414 — Laruence — 2012-05-02T08:46:11+00:00

URL: https://externals.io/message/59804#60414 · In reply to: #60372

> Hi,
>
> 2012/4/12 Nikita Popov <nikita.ppv@googlemail.com>:
> > […]
>
> I would have voted +1 if it didn't contain the isset() change. None of
> the examples used in the isset_with_expr.phpt test seems logic to me.
Hi:
     isset and empty are generally think as a pair,  and the both even
share one ZEND_OP: ZEND_ISSET_ISEMPTY_VAR

    so I think if you want to change empty, you should also change isset.

thanks
>
> Care to explain the consistency concerns here?
>
> Patrick
>
> --
> 
> 
>



-- 
Laruence  Xinchen Hui
http://www.laruence.com/

---

## #60415 — Pierre Joye — 2012-05-02T09:10:15+00:00

URL: https://externals.io/message/59804#60415 · In reply to: #60414

hi,



>    so I think if you want to change empty, you should also change isset.

An expression is not set per se. isset goals, by design, from the very
1st day, is to test the existence of a variable and a variable only.

empty() on the other hand, tests if something is empty, and only if it
is empty. The result of an expression can be empty.

Cheers,
-- 
Pierre

@pierrejoye | http://blog.thepimp.net | http://www.libgd.org

---

## #60417 — Ferenc Kovacs — 2012-05-02T09:36:39+00:00

URL: https://externals.io/message/59804#60417 · In reply to: #60415

> hi,
>
> 
>
> > […]
>
> An expression is not set per se. isset goals, by design, from the very
> 1st day, is to test the existence of a variable and a variable only.
>

"Returns `TRUE` if var exists and has value other than NULL, `FALSE` otherwise."

$foo=null;
var_dump(isset($foo)); //prints bool(false)


>
> empty() on the other hand, tests if something is empty, and only if it
> is empty. The result of an expression can be empty.
>
>
an expression can also have a value of null.

-- 
Ferenc Kovács
@Tyr43l - http://tyrael.hu

---

## #60418 — Pierre Joye — 2012-05-02T09:43:03+00:00

URL: https://externals.io/message/59804#60418 · In reply to: #60417

hi,



> $foo=null;
> var_dump(isset($foo)); //prints bool(false)

No offset meant, but it is totally expected and well known, and as far
as I remember documented too. Assigning `NULL` to a variable unsets it
(so to say).

> > […]
>
> an expression can also have a value of null.

And `NULL` is empty. No issue here.

Cheers,
-- 
Pierre

@pierrejoye | http://blog.thepimp.net | http://www.libgd.org

---

## #60419 — Pierre Joye — 2012-05-02T09:43:33+00:00

URL: https://externals.io/message/59804#60419 · In reply to: #60418

> hi,
>
> 
>
> > […]
>
> No offset meant,

lapsus :) s,offset,offense,



-- 
Pierre

@pierrejoye | http://blog.thepimp.net | http://www.libgd.org

---

## #60420 — Anthony Ferrara — 2012-05-02T11:37:34+00:00

URL: https://externals.io/message/59804#60420 · In reply to: #60418

Pierre,


> hi,
>
> 
>
> > […]
>
> No offset meant, but it is totally expected and well known, and as far
> as I remember documented too. Assigning `NULL` to a variable unsets it
> (so to say).

Well, except that it doesn't unset it.  It only fails isset().  The
symbol still exists in the symbol table, and the zval is still
allocated.  That's one reason that isset() can return false, and
 `array_key_exists()` will return true.  But right now there's no way to
check if a symbol exists since isset returns falls for a null value in
a symbol (and there's no other way to check it)...

Not saying it should change, just that it's a corner case that's not
accounted for in the API...

I voted for the ability to use an expression for isset() as well,
since I agree with Ferenc, it's a matter of consistency.  Sure, the
use-case for isset() is definitely weaker than for empty(), but at the
same token they are definitely related...

Anthony

> > […]
>
> And `NULL` is empty. No issue here.
>
> Cheers,
> --
> Pierre
>
> @pierrejoye | http://blog.thepimp.net | http://www.libgd.org

---

## #60421 — Ferenc Kovacs — 2012-05-02T11:38:43+00:00

URL: https://externals.io/message/59804#60421 · In reply to: #60418

> hi,
>
> 
>
> > […]
>
> No offset meant, but it is totally expected and well known, and as far
> as I remember documented too. Assigning `NULL` to a variable unsets it
> (so to say).
>
>
sure, as I quoted the documentation here.
I just wanted to emphasize, that isset not only checks if a variable is set
or not, but also checks the value of the variable, which makes your
argument ("An expression is not set per se. isset goals, by design, from
the very1st day, is to test the existence of a variable and a variable
only.") much weaker.



> > […]
>
> And `NULL` is empty. No issue here.
>

yeah, but that wasn't my point, I was saying that an expression can also
have a value of null, which can be checked by isset, so empty and isset
isn't any different in that regard for expressions.

-- 
Ferenc Kovács
@Tyr43l - http://tyrael.hu

---

## #60426 — Pierre Joye — 2012-05-03T05:39:09+00:00

URL: https://externals.io/message/59804#60426 · In reply to: #60420

hi Anthony,



> I voted for the ability to use an expression for isset() as well,
> since I agree with Ferenc, it's a matter of consistency.  Sure, the
> use-case for isset() is definitely weaker than for empty(),

No, it is not about consistency but goals and meaning. An expression
is not set or unset. Anyway, that's not something we can argue about
forever :-).

Cheers,
-- 
Pierre

@pierrejoye | http://blog.thepimp.net | http://www.libgd.org

---

## #60427 — Lester Caine — 2012-05-03T07:17:41+00:00

URL: https://externals.io/message/59804#60427 · In reply to: #60420

Anthony Ferrara wrote:
> I voted for the ability to use an expression for isset() as well,
> since I agree with Ferenc, it's a matter of consistency.  Sure, the
> use-case for isset() is definitely weaker than for empty(), but at the
> same token they are definitely related...

I just can't help feeling that it is the wrong use of both. If the function is 
returning a value, then it's returning a value that needs to be used somewhere 
so the work flow handles that. If the function returns nothing instead that just 
seems wrong and needs to be handled better. I'm used to getting back 'false' if 
the function failed and just check for that so why would there be any logical 
reason for using isset or empty to check a function return?

-- 
Lester Caine - G8HFL
-----------------------------
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk//
Firebird - http://www.firebirdsql.org/index.php

---

## #60437 — Patrick ALLAERT — 2012-05-03T18:10:59+00:00

URL: https://externals.io/message/59804#60437 · In reply to: #60427

2012/5/3 Lester Caine <lester@lsces.co.uk>:
> Anthony Ferrara wrote:
> > […]
>
>
> I just can't help feeling that it is the wrong use of both. If the function
> is returning a value, then it's returning a value that needs to be used
> somewhere so the work flow handles that. If the function returns nothing
> instead that just seems wrong and needs to be handled better. I'm used to
> getting back 'false' if the function failed and just check for that so why
> would there be any logical reason for using isset or empty to check a
> function return?

Use case:

// Function definition:
function getFriends()
{
    // SQL SELECT or Fetching from XML or Fetching from LDAP or ...
    return $resultsAsArray;
}

// Looping on results:
foreach ( getFriends() as $friend )
{
    echo $friend["name"], "\n";
}

// Case where the results are actually not iterated:
$amIAssocial = empty( getFriends() );

1. It it not wrong to return "nothing", like empty sets (empty
arrays), it is a valid case.
2. Returning "false" in the case there is no "results" would be a bad
idea: not only you would have to put a condition in the function
definition, but you would also require all iterations (e.g. foreach)
to be encapsulated in a condition statement to prevent looping on
"false".

---

## #60438 — Herman Radtke — 2012-05-03T20:29:29+00:00

URL: https://externals.io/message/59804#60438 · In reply to: #60437

> > […]
>
> Use case:
>
> // Function definition:
> function getFriends()
> {
>    // SQL SELECT or Fetching from XML or Fetching from LDAP or ...
>    return $resultsAsArray;
> }
>
> // Looping on results:
> foreach ( getFriends() as $friend )
> {
>    echo $friend["name"], "\n";
> }
>
> // Case where the results are actually not iterated:
> $amIAssocial = empty( getFriends() );

This is the exact same thing:
$amIAssocial = !getFriends();


Earlier, I sent this to Lester only:
Most people don't realize that an empty array is already falsy so they
feel the need to use empty. That is the only use-case the RFC gives
for making this change. From the RFC: "For example if func() is
expected to return an array, it feels more natural to verify it's
emptiness using empty() instead of !."
-- 
Herman Radtke
hermanradtke@gmail.com | http://hermanradtke.com

---

## #60439 — Lester Caine — 2012-05-03T20:42:09+00:00

URL: https://externals.io/message/59804#60439 · In reply to: #60437

Patrick ALLAERT wrote:
> 2012/5/3 Lester Caine<lester@lsces.co.uk>:
> > […]
>
> Use case:
>
> // Function definition:
> function getFriends()
> {
>      // SQL SELECT or Fetching from XML or Fetching from LDAP or ...
>      return $resultsAsArray;
> }
>
> // Looping on results:
> foreach ( getFriends() as $friend )
> {
>      echo $friend["name"], "\n";
> }
>
> // Case where the results are actually not iterated:
> $amIAssocial = empty( getFriends() );
>
> 1. It it not wrong to return "nothing", like empty sets (empty
> arrays), it is a valid case.
> 2. Returning "false" in the case there is no "results" would be a bad
> idea: not only you would have to put a condition in the function
> definition, but you would also require all iterations (e.g. foreach)
> to be encapsulated in a condition statement to prevent looping on
> "false".

OK I'm just so used to
if( $rs = $this->mDb->query( $query, $bindVars ) ) {
   while( $row = $rs->fetchRow() ) {
   }
}

So I can't see where 'empty( $rs->fetchRow() )' would fit into the work flow ...

-- 
Lester Caine - G8HFL
-----------------------------
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk//
Firebird - http://www.firebirdsql.org/index.php

---

Next page: https://externals.io/message/59804.md?page=2
