475

I would think the following piece of code should work, but it doesn't (Edited: Now works in PHP 5.5+):

if (!empty($r->getError()))

Where getError() is simply:

public function getError()
{
    return $this->error;
}

Yet I end up with this error:

can't use method return value in write context

What does this mean? Isn't this just a read?

thanksd
  • 54,176
  • 22
  • 157
  • 150
Extrakun
  • 19,057
  • 21
  • 82
  • 129
  • 2
    Probably in PHP 5.5 you will be permitted to pass expressions to `empty`: https://wiki.php.net/rfc/empty_isset_exprs – Carlos Campderrós Jul 31 '12 at 07:44
  • 2
    [The Definitive Guide To PHP's isset And empty](http://kunststube.net/isset/) – deceze Jul 31 '12 at 08:04
  • Ok i find [porneL's Answer](http://stackoverflow.com/a/4328049/476) correct too this my code `if ( !$e->find('div') ) ` that check if current HTML DOM element are empty or not . I use it inside loop to print out only single Div without inner Div inside it . – Salem Jun 22 '15 at 18:17

8 Answers8

782

empty() needs to access the value by reference (in order to check whether that reference points to something that exists), and PHP before 5.5 didn't support references to temporary values returned from functions.

However, the real problem you have is that you use empty() at all, mistakenly believing that "empty" value is any different from "false".

Empty is just an alias for !isset($thing) || !$thing. When the thing you're checking always exists (in PHP results of function calls always exist), the empty() function is nothing but a negation operator.

PHP doesn't have concept of emptyness. Values that evaluate to false are empty, values that evaluate to true are non-empty. It's the same thing. This code:

$x = something();
if (empty($x)) …

and this:

$x = something();
if (!$x) …

has always the same result, in all cases, for all datatypes (because $x is defined empty() is redundant).

Return value from the method always exists (even if you don't have return statement, return value exists and contains null). Therefore:

if (!empty($r->getError()))

is logically equivalent to:

if ($r->getError())
Kornel
  • 97,764
  • 37
  • 219
  • 309
  • 30
    This is a much better answer than the one currently selected. – SystemParadox Sep 09 '11 at 14:20
  • 1
    empty() equals !$x for most purposes, not for all var types. – gcb Oct 03 '11 at 04:21
  • 20
    @gcb: no, the PHP manual explicitly says it's identical: *"empty() is the opposite of `(boolean) var`, except that no warning is generated when the variable is not set."* – Kornel Oct 04 '11 at 23:33
  • 17
    The not generating a warning part is pretty important... empty($var) will return true if it's 0, '', array(), NULL, or not even defined. It's good practice, particularly so you can log your *real* warnings without the files filling up – landons Nov 15 '11 at 14:15
  • 3
    Ok, great answer, but what's the right way to avoid this, does anyone know? – Javatar Jan 20 '13 at 22:34
  • 1
    @Javatar: The last line of porneLs answer shows how to avoid the PHP-exception in question - in most cases. To solve it in all cases you have to check $r for its existence & type explicitly to gain the same robustness of using empty(): "if (isset($r) AND is_object($r) AND $r->getError()) { ..then.. }" – gue Feb 23 '14 at 23:20
  • Instead checking for !empty($r->getError()) can we use "null!==$r->getError()" ? What do you think? – Eugen Mihailescu Apr 10 '14 at 16:22
  • 3
    @EugenMihailescu in general that's ok, but it's not strictly equivalent to empty(), because `""`, `0`, etc. are "empty", but not null. – Kornel Apr 11 '14 at 11:19
  • 1
    Not really true. `if (empty($x['non_existing_index']))` and `if (!$x['non_existing_index'])` produce different results. – bancer Jun 26 '14 at 12:11
  • This is the sort of thing that earns PHP its reputation, and no amount of charmed circle legalism around a subject, as in this upvoted answer, will fix this. We may wish we could always use php7, but realities intrude. I think there are two sensible solutions if at least 5.3 is present. Use an intermediate value per George Claghom, Luke P M. Or, there is the Elvis operator, so $val = function()) ?: false; should be good, to give something we can trust to further php logic. If trust is the word.... – narration_sd May 27 '16 at 04:12
  • No need to keep fighting about true being something and false not being nothing, your answer was very clear but as a precision, is it because of the referencing that if you return an array from your function you can do `if( empty(foo()[ 'bar' ]) ){ echo 'foo bar'; }` but if you call only the function it crash `if( empty(foo()) ){ echo 'foo dies'; }` – Louis Loudog Trottier Apr 02 '17 at 06:57
  • So if there is no empty why mislead developers by calling the function empty? – Dr Deo Feb 21 '19 at 10:07
  • This answer is wrong in that `empty($a)` is not an alias for `!isset($a)` E.g. `$a = false;` then `!isset($a)` will be false, while `empty($a)` will be true. They are quite different. IMHO `empty()` is *the* most useful function in PHP. So much so that I port it to JavaScript. – geoidesic Nov 28 '19 at 11:31
  • 1
    @geoidesic You've misread the answer, which states `!isset($thing) || !$thing`. Note the second part after `||` that you're missing in your comment. – Kornel Dec 02 '19 at 15:08
331

Note: This is a very high voted answer with a high visibility, but please note that it promotes bad, unnecessary coding practices! See @Kornel's answer for the correct way.

Note #2: I endorse the suggestions to use @Kornel's answer. When I wrote this answer three years ago, I merely meant to explain the nature of the error, not necessarily endorse the alternative. The code snippet below is not recommended.


It's a limitation of empty() in PHP versions below 5.5.

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)).

You'd have to change to this

// Not recommended, just illustrates the issue
$err = $r->getError();
if (!empty($err))
Community
  • 1
  • 1
Peter Bailey
  • 105,256
  • 31
  • 182
  • 206
  • 156
    This is insanely counterproductive. – David Murdoch Dec 23 '10 at 20:26
  • 47
    Note: The same is true with `isset()`. ie: `isset($this->foo->getBar())` will result in the same issue. – catchdave Jun 24 '11 at 23:45
  • 7
    porneL's answer explains this in more detail, with a better solution – SystemParadox Sep 09 '11 at 14:21
  • 5
    @SystemParadox - Depends on what you mean by "better". porneL's answer is arguably more thorough with a "cleaner" solution, but also doesn't actually explain the origin of the error either. – Peter Bailey Sep 12 '11 at 22:22
  • `if ($r->getError() != '')` would also work, though not as thorough – Dirk Hartzer Waldeck Dec 08 '11 at 14:38
  • 2
    Agreed, porneL's answer is a lot better than this answer. – Tek May 06 '12 at 16:20
  • 4
    Because it's not wrong, @deceze. It's not the best answer, you won't get any argument from me there. I even voted up porneL's myself. It's a *very old* answer but it's not *wrong*. Regarding the high votes: remember, porneL's arrived nearly a full 17 months after this one. – Peter Bailey Jul 31 '12 at 20:30
  • I was going insane when I was trying to fix a bug in my application until I saw this post and then I realized my php version was 5.3. After I upgraded my version to 5.5, It worked like a charm. This is a life saving answer even after its been so long. Thank you. – Bikal Basnet Jan 18 '15 at 17:24
38

Prior to PHP 5.5, the the PHP docs used to say:

empty() only checks variables as anything else will result in a parse error

In PHP < 5.5 you weren't able use empty() directly on a function's return value. Instead, you could assign the return from getError() to a variable and run empty() on the variable.

In PHP >= 5.5 this is no longer necessary.

Mike
  • 23,542
  • 14
  • 76
  • 87
George Claghorn
  • 26,261
  • 3
  • 48
  • 48
19

I usually create a global function called is_empty() just to get around this issue

function is_empty($var)
{ 
 return empty($var);
}

Then anywhere I would normally have used empty() I just use is_empty()

Luke P M
  • 558
  • 5
  • 9
  • 2
    It's better not to do this and stick to the standards (as annoying as they might be). – tonyhb Aug 16 '11 at 09:52
  • 1
    @dynamism could you explain why not? – Janis Veinbergs Sep 19 '11 at 14:57
  • 1
    Because convenience functions can be a pain to read in someone else's code. Plus, in a MVC/HMVC architecture it can mess your structure. At the end of the day, PHP coders should know it's limitations and be able to understand small workarounds without convenience functions. – tonyhb Sep 26 '11 at 20:24
  • 14
    Wow, you've just invented a *negation function*. You know PHP has `!` operator for this? :) – Kornel Oct 04 '11 at 23:34
4

As pointed out by others, it's a (weird) limitation of empty().

For most purproses, doing this is equal as calling empty, but this works:

if ($r->getError() != '')
Jani Hartikainen
  • 42,745
  • 10
  • 68
  • 86
2

The issue is this, you want to know if the error is not empty.

public function getError() {
    return $this->error;
}

Adding a method isErrorSet() will solve the problem.

public function isErrorSet() {
    if (isset($this->error) && !empty($this->error)) {
        return true;
    } else {
        return false;
    }
}

Now this will work fine with this code with no notice.

if (!($x->isErrorSet())) {
    echo $x->getError();
}
1

I'm not sure if this would be a common mistake, but if you do something like:

$var = 'value' .= 'value2';

this will also produce the same error

Can't use method return value in write context

You can't have an = and a .= in the same statement. You can use one or the other, but not both.

Note, I understand this is unrelated to the actual code in the question, however this question is the top result when searching for the error message, so I wanted to post it here for completeness.

Mike
  • 23,542
  • 14
  • 76
  • 87
-3

The alternative way to check if an array is empty could be:

count($array)>0

It works for me without that error

Tunaki
  • 132,869
  • 46
  • 340
  • 423
quardas
  • 651
  • 3
  • 10
  • 23