PHPのお勉強!

PHP TOP

empty

(PHP 4, PHP 5, PHP 7, PHP 8)

empty変数が空であるかどうかを検査する

説明

empty(mixed $var): bool

変数が空であるかどうかを検査します。 変数が空であるとみなされるのは、変数が存在しない場合や 変数の値が false に等しい場合です。 empty() は、変数が存在しない場合でも警告を発しません。

パラメータ

var

チェックする変数

変数が存在しなくても警告は発生しません。 つまり、empty() は本質的に !isset($var) || $var == false と同じことを簡潔に記述しているだけです。

戻り値

var が存在しない、 または空や0の値が設定されている場合、 つまり boolean のコンテキストで false と見なされる場合、 true を返します。 詳細は boolean への変換 を参照ください。 それ以外の場合は false を返します。

例1 簡単な empty() / isset() の比較

<?php
$var
= 0;

// $var が空なのでtrueと評価されます
if (empty($var)) {
echo
'$var is either 0, empty, or not set at all';
}

// $var が設定されているのでtrueと評価されます
if (isset($var)) {
echo
'$var is set even though it is empty';
}
?>

例2 文字列のオフセットに対する empty()

<?php
$expected_array_got_string
= 'somestring';
var_dump(empty($expected_array_got_string['some_key']));
var_dump(empty($expected_array_got_string[0]));
var_dump(empty($expected_array_got_string['0']));
var_dump(empty($expected_array_got_string[0.5]));
var_dump(empty($expected_array_got_string['0.5']));
var_dump(empty($expected_array_got_string['0 Mostel']));
?>

上の例の出力は以下となります。

bool(true)
bool(false)
bool(false)
bool(false)
bool(true)
bool(true)

注意

注意: これは、関数ではなく 言語構造のため、可変関数名前付き引数 を用いてコールすることはできません。

注意:

オブジェクトのアクセス不能なプロパティに対して empty() を使用した場合は、もしオーバーロードメソッド __isset() が宣言されていればそれをコールします。

参考

  • isset() - 変数が宣言されていること、そして null とは異なることを検査する
  • __isset()
  • unset() - 指定した変数の割当を解除する
  • array_key_exists() - 指定したキーまたは添字が配列にあるかどうかを調べる
  • count() - 配列または Countable オブジェクトに含まれるすべての要素の数を数える
  • strlen() - 文字列の長さを得る
  • PHP 型の比較表

add a note

User Contributed Notes 36 notes

up
227
Nanhe Kumar
10 years ago
<?php
/**
* @author : Nanhe Kumar <nanhe.kumar@gmail.com>
* List of all empty values
**/

$testCase = array(
1 => '',
2 => "",
3 => null,
4 => array(),
5 => FALSE,
6 => NULL,
7=>'0',
8=>0,

);

foreach (
$testCase as $k => $v) {
if (empty(
$v)) {
echo
"<br> $k=>$v is empty";
}
}
/**
Output
1=> is empty
2=> is empty
3=> is empty
4=>Array is empty
5=> is empty
6=> is empty
7=>0 is empty
8=>0 is empty
**/
?>
up
3
mmulej at gmail dot com
1 year ago
Tests on
- Win 11
- Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz 2.21 GHz
- 64Gb RAM,
- PHP 8.1.10 (in Tinkerwell)
repeatedly show `empty` > `count` > `=== []`, but the margin is small and not worth the micro-optimizations.

Note: Same results (with `$n = 10000000`) for PHP v7.4.33 using onlinephp(dot)io sandbox tool.

<?php

$test
= range(0, 1000);
$test2 = [];
$n = 1000_000_000;

$t1 = microtime(true); for ($x = 0; $x < $n; $x++) if (count($test)) {}
$t2 = microtime(true); for ($x = 0; $x < $n; $x++) if (count($test2)) {}
$t3 = microtime(true); for ($x = 0; $x < $n; $x++) if ($test === []) {}
$t4 = microtime(true); for ($x = 0; $x < $n; $x++) if ($test2 === []) {}
$t5 = microtime(true); for ($x = 0; $x < $n; $x++) if (empty($test)) {}
$t6 = microtime(true); for ($x = 0; $x < $n; $x++) if (empty($test2)) {}
$t7 = microtime(true);

echo
"count(\$test): " . ($t2 - $t1) . " sec\n";
echo
"count(\$test2): " . ($t3 - $t2) . " sec\n";
echo
"\$test === []: " . ($t4 - $t3) . " sec\n";
echo
"\$test2 === []: " . ($t5 - $t4) . " sec\n";
echo
"empty(\$test): " . ($t6 - $t5) . " sec\n";
echo
"empty(\$test2): " . ($t7 - $t6) . " sec\n";

?>

Results:
<?php
count
($test): 18.034885168076 sec
count
($test2): 17.133869886398 sec
$test
=== []: 20.059770107269 sec
$test2
=== []: 14.204195022583 sec
empty($test): 13.583840847015 sec
empty($test2): 12.971315145493 sec
?>
up
88
Janci
15 years ago
Please note that results of empty() when called on non-existing / non-public variables of a class are a bit confusing if using magic method __get (as previously mentioned by nahpeps at gmx dot de). Consider this example:

<?php
class Registry
{
protected
$_items = array();
public function
__set($key, $value)
{
$this->_items[$key] = $value;
}
public function
__get($key)
{
if (isset(
$this->_items[$key])) {
return
$this->_items[$key];
} else {
return
null;
}
}
}

$registry = new Registry();
$registry->empty = '';
$registry->notEmpty = 'not empty';

var_dump(empty($registry->notExisting)); // true, so far so good
var_dump(empty($registry->empty)); // true, so far so good
var_dump(empty($registry->notEmpty)); // true, .. say what?
$tmp = $registry->notEmpty;
var_dump(empty($tmp)); // false as expected
?>

The result for empty($registry->notEmpty) is a bit unexpeced as the value is obviously set and non-empty. This is due to the fact that the empty() function uses __isset() magic functin in these cases. Although it's noted in the documentation above, I think it's worth mentioning in more detail as the behaviour is not straightforward. In order to achieve desired (expexted?) results, you need to add __isset() magic function to your class:

<?php
class Registry
{
protected
$_items = array();
public function
__set($key, $value)
{
$this->_items[$key] = $value;
}
public function
__get($key)
{
if (isset(
$this->_items[$key])) {
return
$this->_items[$key];
} else {
return
null;
}
}
public function
__isset($key)
{
if (isset(
$this->_items[$key])) {
return (
false === empty($this->_items[$key]));
} else {
return
null;
}
}
}

$registry = new Registry();
$registry->empty = '';
$registry->notEmpty = 'not empty';

var_dump(empty($registry->notExisting)); // true, so far so good
var_dump(empty($registry->empty)); // true, so far so good
var_dump(empty($registry->notEmpty)); // false, finally!
?>

It actually seems that empty() is returning negation of the __isset() magic function result, hence the negation of the empty() result in the __isset() function above.
up
68
steven at nevvix dot com
13 years ago
When you need to accept these as valid, non-empty values:
- 0 (0 as an integer)
- 0.0 (0 as a float)
- "0" (0 as a string)

<?php
function is_blank($value) {
return empty(
$value) && !is_numeric($value);
}
?>

This is similar to Rails' blank? method.
up
13
info at ensostudio dot ru
3 years ago
Multiple empty():
<?php
/**
* Multiple empty().
*
* @param mixed[] $vars Variables to test
* @return bool
*/
function multi_empty(& ...$vars)
{
// no callback is supplied, all empty values will be removed
return array_filter($vars) === [];
}
?>
example:
<?php
$notEmptyVar
= 1;
$emptyVar = null;
// $undefinedVar - not defined

multi_empty($emptyVar); // true
multi_empty($emptyVar, $undefinedVar); // true
multi_empty($notEmptyVar , $emptyVar); // false
multi_empty($notEmptyVar , $emptyVar, $undefinedVar); // false
?>
up
17
chrisdmiddleton at gmail dot com
10 years ago
If you want to use empty() to evaluate an expression (not a variable), and you don't have PHP 5.5+, you can do it by wrapping the call to empty in a function, like so:
<?php
function is_empty($var) {

return empty(
$var);

}
?>
Then you can do something like
<?php
if(is_empty(NULL)) {
/* ... */
}
?>
without issue, since the local variable $var is being tested rather than the expression in the function call itself.
up
15
Claudio Galdiolo
7 years ago
Warning: an "empty" object is NOT considered to be empty
<?php
$var
= new stdClass(); // "empty" object
var_dump(empty($var)); // bool(false)
?>

I don't know if there is a standard way to test for "empty" objects, I personally use array casting:
<?php
$var
= new stdClass(); // "empty" object
$var = (array) $var; // cast to empty array
var_dump(empty($var)); // bool(true)
?>
up
11
markmanning at gmail dot com
5 years ago
I normally count() an array, so I wanted to see how empty() would stack up.

<?php
$test
= array();
$test2 = array();
for (
$x = 0; $x < 1000; $x++) $test[] = $x;

$ts = microtime(true);
for (
$x = 0; $x < 100000000; $x++)
{
if (
count($test))
{
}
}

echo
"Time taken: " . (microtime(true) - $ts) . " sec\n";
?>

For 100,000,000 comparisons, here are the results against PHP 7.2.16 on my hardware:

count($test): 2.697 sec
count($test2): 2.596 sec
$test === array(): 2.579 sec
$test2 === array(): 2.552 sec
empty($test): 3.085 sec
empty($test2): 3.113 sec

In short, it doesn't matter what method is used although empty() is actually just ever so slightly slower despite it being a language construct. YMMV.
up
12
tom at tomwardrop dot com
16 years ago
In reply to "admin at ninthcircuit dot info",

Using str_replace is unnecessary. I would encourage the use of trim which would most likely be faster (haven't tested) and easier. Trim also takes care of other white space like line breaks and tabs. Actually, in most of the applications I code, I use a multi-dimensional array map function with trim on the Super Globals such as $_POST, $_GET and $_COOKIE as so far, there hasn't been an instance where I would want any user input to begin or end with whitespace. The good thing about doing this is that you never have to worry about 'trimming' your input which makes your code easier and more reliable (incase you forget to trim some input).
up
16
your dot brother dot t at hotmail dot com
9 years ago
(experienced in PHP 5.6.3) The `empty()` can't evaluate `__get()` results explicitly, so the `empty()` statement bellow always renders true
<?php
class Juice extends Liquid{
protected
$apple;
protected
$orange;
public function
__get($name) {
return
$this->$name;
}
public function
__construct($apple, $orange) {
$this->apple = $apple;
$this->orange = $orange;
}
}

class
Glass {
protected
$liquid;
public function
__get($name) {
return
$name == "liquid" ? $this->liquid : false;
}
public function
__construct() {
$this->juice = new Juice(3, 5);
}
}

$glass = new Glass();
var_dump(empty($this->liquid->apple));

/**
* The output is:
* bool(true)
*/
?>

The correct way is to force the evaluation of `__get()` first, by using extra braces around implicit statements like this:
<?php
var_dump
(empty(($this->liquid->apple)));

/**
* The output is:
* bool(false)
*/
?>

So if you are using packages that utilize object oriented designs and magic methods like `__get()`, it's a good practice to always use double braces for `empty()` calls.
up
10
marko dot crni at gmail dot com
14 years ago
Calling non existing object property, empty($object->prop), will trigger __isset(), the same way as isset($object->prop) does, but there is one difference. If __isset() returns TRUE, another call to __get() will be made and actual return value will be result of empty() and result of __get().
up
11
aidan1103 at yahoo dot com
14 years ago
empty() should not necessarily return the negation of the __isset() magic function result, if you set a data member to 0, isset() should return true and empty should also return true. A simpler implementation of the __isset magic function would be:

public function __isset($key) {
return isset($this->{$key});
}

I don't understand why this isn't included in stdClass and inherited by default.
up
19
martin dot aarhof at gmail dot com
12 years ago
<?php
$str
= ' ';
var_dump(empty($str)); // boolean false
?>

So remember to trim your strings first!

<?php
$str
= ' ';
$str = trim($str);
var_dump(empty($str)); // boolean true
?>
up
3
GazetteSDF
6 years ago
For the verification of a form, to "block" entries such as a simple space or other, I thought of this combination:

function isEmpty($string){
$val = preg_replace('#[^A-Za-z0-9]+#', '', $string) ;
$val = trim($string, '');
return ($string=='') ;
}

This protects entries like: ' ' ,' - ', '. - +', ... On entries like name, profession, ... it's helpful
up
10
ehsmeng
14 years ago
I can't use empty() in all situations because '0' is usually not considered empty to me. I did a quick benchmark over the most common ways of testing it. '' == var suffers from '' == 0 is true so that's just there for curiosity.

<?php
$microtimeref
= microtime(true);
$a = 0;
$b = 'asd';
for (
$i = 0; $i < 5000000; $i++)
{
if (
0 == mb_strlen ($b))
{
$a++;
}
}
echo
"Total time 0 == mb_strlen(var): <b>" . round(microtime(true) - $microtimeref,3) . 's</b><br />';
?>

The results:

Total time 0 == mb_strlen(var): 3.141s
Total time 0 === strlen(var): 2.904s
Total time 0 == strlen(var): 2.878s
Total time '' == var: 1.774s
Total time '' === var: 1.706s
Total time empty(var): 1.496s

Thus '' === var will be my zero length string test.
up
15
phpsort
13 years ago
I'm summarising a few points on empty() with inaccessible properties, in the hope of saving others a bit of time. Using PHP 5.3.2.
<?php
class MyClass {
private
$foo = 'foo';
}
$myClass = new MyClass;
echo
$myClass->foo;
?>
As expected, this gives "Fatal error: Cannot access private property MyClass::$foo".
But substitute the line
if (empty($myClass->foo)) echo 'foo is empty'; else echo 'foo is not empty';
and we get the misleading result "foo is empty".
There is NO ERROR OR WARNING, so this is a real gotcha. Your code will just go wrong silently, and I would say it amounts to a bug.
If you add two magic functions to the class:
public function __get($var) { return $this->$var; }
public function __isset($var) { return isset($this->$var); }
then we get the expected result. You need both functions.
For empty($myClass->foo), I believe PHP calls __isset, and if that is true returns the result of empty on the result of __get. (Some earlier posts wrongly suggest PHP just returns the negation of __isset).
BUT …
See the earlier post by php at lanar dot com. I confirm those results, and if you extend the test with isset($x->a->b->c) it appears that __isset is only called for the last property in the chain. Arguably another bug. empty() behaves in the same way. So things are not as clear as we might hope.
See also the note on empty() at
http://uk3.php.net/manual/en/language.oop5.overloading.php
Clear as mud!
up
7
mlibazisi mabandla
15 years ago
in cases when "0" is not intended to be empty, here is a simple function to safely test for an empty string (or mixed variable):

<?php
function _empty($string){
$string = trim($string);
if(!
is_numeric($string)) return empty($string);
return
FALSE;
}
?>
up
4
wranvaud at gmail dot com
7 years ago
Note that if your variable only has an "end of line" (aka carriage return), PHP_EOL it is not considered as empty. Since end of lines are not always easy to spot this can be confusing.
up