19

I have three variables:

$var1
$var2
$var3

I'm actually looking for the best way to check if only one of these three variables is not empty and the two others are empty.

Is that possible to do this with one if only? If not, then what's the best way?

The variables all contain text.

7
  • First need to trim all var ` $var1 = trim($var1); $var2 = trim($var2); $var3 = trim($var3);` then check it. Commented Sep 14, 2016 at 7:29
  • Can you let us know what is the data type of the variable? Commented Sep 14, 2016 at 7:29
  • datatype is text. Commented Sep 14, 2016 at 7:35
  • I have answered the question. I guess else part in my answer should work for you. Commented Sep 14, 2016 at 7:36
  • 3
    A PHP question in the HNQ (Hot Network Questions)? What a time to be alive! :-) Commented Sep 14, 2016 at 13:44

8 Answers 8

36

You can convert variable into array and exclude empty variables using array_filter(). Then use count() after the filter.

if(count(array_filter(array($var1,$var2,$var3)))==1){
  //only 1 variable is not empty
}

Check Fiddle link

Sign up to request clarification or add additional context in comments.

7 Comments

you say //only 1 variable is empty. but i want only one NOT EMPTY. :)
down vote for using compact , [$var1,$var2,$var3] same result
doesn't seem to work for me....i wrote : if(count(array_filter(compact($var1,$var2,$var3)))==1){ what's the problem ?
@cske : Thank you very much !!
@cetipabo, if you like this answer please mark as correct.
|
25

Booleans return 0 and 1 with array_sum()

if (array_sum(array(empty($var1), empty($var2), empty($var3))) == 1)
{
    echo "one is empty" ;
}

ETA: This is a simpler way:

if (!empty($var1) + !empty($var2) + !empty($var3) == 1) {
    echo "1 is not empty" ;
}

ETA 2: We don't need the negative signs

if (empty($var1) + empty($var2) + empty($var3) == 2) {
    echo "1 is not empty" ;
}

4 Comments

If you want to make 100% sure it's an integer without casting every single variable, use like this: (0 + empty($var1) + empty($var2) + ...)
@DanFromGermany 0 + is not necessary because you don't add variables but result from the function call empty() which is 0 or 1
@DominiqueLorre the result from empty() is true or false, not 1 or 0. boolean evaluates to integer in arithmetic operations but this is not for granted 100% in all situations in every version. I know it's not necessary. What I want to say is, this is a method of an explicit cast. Like 0.0 + integer will translate to 0.0 + (float)integer and evaluate to float finally.
@DanFromGermany, in that case, I think Hanky Panky's answer is better. If true he uses 0 and if false he uses 1, so that's inverted, but the result is the same and you do not cast anything. He only uses integers.
10
$counter=0;
$counter+= empty($var1) ? 0:1;
$counter+= empty($var2) ? 0:1;
$counter+= empty($var3) ? 0:1;

if($counter==1)
   echo "Exactly 2 are empty";

Fiddle

Or you can simply do

var_dump(count(array_filter(array($var1,$var2,$var3)))==1);

Fiddle

3 Comments

Do you mean "Exactly 1 is empty"
Nope, i exactly mean exactly 2 are empty
@cetipabo if you are using this one, shouldn't it be marked as the answer?
7

I'd use XOR (exclusive or) for this, because it's intended for this purpose, so using a dirty workaround with an array is not as easy to understand.

if (!(!empty($var1) && !empty($var2) && !empty($var3)) && (!empty($var1) ^ !empty($var2) ^ !empty($var3))) {
    echo "Only one string is not empty\n";
}

And it's about 25% faster than the accepted answer.

$before = microtime(true);
for ($i = 0; $i < 100000; ++$i) {
    $var1 = 'Hello';
    $var2 = '';
    $var3 = '';

    if (!(!empty($var1) && !empty($var2) && !empty($var3)) && (!empty($var1) ^ !empty($var2) ^ !empty($var3))) {
        echo "Only one string is not empty\n";
    }

    $var4 = '';
    $var5 = '';
    $var6 = '';

    if (!(!empty($var4) && !empty($var5) && !empty($var6)) && (!empty($var4) ^ !empty($var5) ^ !empty($var6))) {
        echo "Only one string is not empty\n";
    }

    $var7 = 'Hello';
    $var8 = 'World';
    $var9 = '!';

    if (!(!empty($var7) && !empty($var8) && !empty($var9)) && (!empty($var7) ^ !empty($var8) ^ !empty($var9))) {
        echo "Only one string is not empty\n";
    }
}

$after = microtime(true);
echo ($after-$before)/$i . " sec for XOR\n";

// 3.2943892478943E-6 sec for XOR

$before = microtime(true);
for ($i = 0; $i < 100000; ++$i) {
    $var1 = 'Hello';
    $var2 = '';
    $var3 = '';

    if (count(array_filter(array($var1, $var2, $var3))) == 1) {
        echo "Only one string is not empty\n";
    }

    $var4 = '';
    $var5 = '';
    $var6 = '';

    if (count(array_filter(array($var4, $var5, $var6))) == 1) {
        echo "Only one string is not empty\n";
    }

    $var7 = 'Hello';
    $var8 = 'World';
    $var9 = '';

    if (count(array_filter(array($var7, $var8, $var9))) == 1) {
        echo "Only one string is not empty\n";
    }
}
$after = microtime(true);
echo ($after-$before)/$i . " sec for Arrays\n";

// 4.3078589439392E-6 sec for Arrays

*I had to update the answer because the name "exclusive or" is somewhat misleading in context of more than two expressions. Of course all commenters are right, and exclusive or is a binary operation therefore resolving from left to right. 1 ^ 1 ^ 1 == 1 resolves to 0 ^ 1 == 1 and is therefore true. Exclusive or does actually look for an odd number of trues.

I updated my answer with an easy-to-read workaround, but this definitely doesn't satisfy me and I have to admin that I resolved a huge misconception of boolean operators in my mind. The last time was a wrong assumption of AND and OR being resolved from left to right rather than first AND then OR.*

13 Comments

Strange, there was another answer with xor but it disappeared. Oh well, you get the +1
I secretly hacked SO to delete it, so I could earn all the reputation. Please don't tell anyone. It's our little secret.
@FabioPoloni: Try with three non-empty variables. 1 ^ 1 ^ 1 == 1
Of course you are all right. And this is probably the reason the first post using exclusive or disappeared.
The original XOR answers was mine, i deleted it because it simply does not work because true ^ true ^ true will result as true due to true & true being false and false ^ true being true, no point in keeping up an answer which gives wrong results and taken that i kept getting upvotes i deleted it, i did not want to spread false information :)
|
4

Try this one:

if (($var1 !== '' && $var2 == '' && $var3 == '') ||
    ($var2 !== '' && $var1 == '' && $var3 == '')  ||
    ($var3 !== '' && $var1 == '' && $var2 == '')) {
    echo 'variable is empty';
}

9 Comments

OP has 3 variables, only 1 is allowed to be empty. Your answer is like you have 3 variables and 2 of them are allowed to be empty.
it does mean it is incorrect, you can have 3 empty values and it wil stil return true
I guess OP had edited the question later on, it seems it was incorrect in the inital stage. Since there are more such answers similar to mine.
@cetipabo It's not doing the same thing 3 times. It's actually checking 3 different things. It's checking if var1 is the only non-empty variable, OR var2 is the only non-empty variable, OR var 3 is the only non-empty variable. So this answer is correct. It is probably the most straight-forward way to check that ONLY ONE variable is non-empty.
If you use the !== operator for the non-empty test, should you not be using === for the empty test? I am thinking that empty(...) would probably be safer if the variable can be strings or arrays.
|
2

Bitwise XOR is great for this:

$var1 ^ $var2 ^ $var3

You might have trouble if the variables don't cast to boolean easily, in which case you'd need to do empty($var) on each of them.

Boom. Zero ifs.

Update

Oops, if they are all not empty, true ^ true ^ true == true

You'll need to check against all of them being true:

($var1 ^ $var2 ^ $var3) && !($var1 && $var2 && $var3)

Comments

2

This is a situation where you should use arrays. You now only have 3 values, but what if you need 4? You'll need to change all your code!

$var = array();
$var[] = 'abc';
$var[] = '';
$var[] = 0;

// will return 1, empty values, false or 0 (falsy values) will not get counted:
echo count(array_filter($var)).' values found';
if( count(array_filter($var))==1 ){ echo 'exactly one value set'; }

If you do need to chek zero's or empty strings you can use other methods to count. The main principle of this code is that if you add more values, the logic itself doesn't need changing.

1 Comment

Haha, the answer in the link to the other methods. Fixed it, thatnks
1

Try this:

$temp_array = array($var1,$var2,$var3);
$temp_count = count(array_filter($temp_array, 'strlen'));
if($temp_count ==1){
    echo "1 variable is not empty";
}
else
{
    echo "total empty variable  is = ".$temp_count;
}

DEMO

1 Comment

OP has 3 variables, only 1 is allowed to be empty. Your answer is like you have 3 variables and 2 of them are allowed to be empty.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.