14

I have give inputs which can be either 1 or 0

$no_required
$on_arrival
$schengen_visa
$uk_visa
$usa_visa

I have the Following Cases and i want to display unique message back to the user for each one of them

a b c d e
1 0 0 0 0   No Visa Required
0 1 0 0 0   Visa can be obtained on Arrival
0 0 1 0 0   You need Schengen Visa
0 0 0 1 0   You need UK visa
0 0 0 0 1   You need US visa
0 0 1 1 1   You need Either of the Visas
0 0 1 1 0   You need Schengen/UK visa
0 0 1 0 1   You need Schengen/US visa
0 0 0 1 1   You need USA/UK visa

Where A B C D E F are the above variables. Which is the best and optimized way to display the results.

3
  • How are you storing the data in your code, how about some code? (didnt mean to put this as answer) Commented Apr 2, 2013 at 12:08
  • @dirt its basically coming from the database. Commented Apr 2, 2013 at 12:10
  • 3
    Add the values up as binary values then run the switch on the addition, if my brain is working right there can't be two values the same. ie if a is 1 add to a variable total 1 if b is 1 add 2, if c is one add 4 then do your switch based on the value of total Commented Apr 2, 2013 at 12:10

4 Answers 4

17

The conditions you're showing can very nicely be modeled via bit masks:

$messages = [
    16 => 'No Visa Required',
    8  => 'Visa can be obtained ...',
    4  => ...
];

You then just have to format your separate variables into a bitmask:

$bitmask = ($no_required ? 16 : 0)
         | ($on_arrival  ? 8  : 0)
         | ...;

Then just pick the right message:

echo $messages[$bitmask];

Note: use of constants instead of magic numbers is pretty much mandatory here as well, so it'd look like this:

define('VISA_NONE',       1);
define('VISA_ON_ARRIVAL', 2);
...

$messages = [
    VISA_NONE         => 'No Visa Required',
    ...,
    VISA_US | VISA_UK => 'You need USA/UK visa'
];

// using multiplication instead of conditionals, as mentioned in the comments
$bitmask = $no_required * VISA_NONE
         | $on_arrival  * VISA_ON_ARRIVAL
         | ...;

echo $messages[$bitmask];

Wrap the whole thing in an appropriate class and you have yourself a nice, readable, maintainable, reusable piece of business logic:

class Visa {

    const NONE       = 1;
    const ON_ARRIVAL = 2;
    ...

    protected $messages = [];

    protected $visa;

    public function __construct() {
        $this->messages = [
            static::NONE            => 'No Visa Required',
            ...,
            static::US | static::UK => 'You need USA/UK visa'
        ];
    }

    /**
     * @param int  $type    One of the class constants.
     * @param bool $enabled Whether this type of visa is required.
     */
    public function set($type, $enabled) {
        $this->visa = $this->visa | $type * (int)(bool)$enabled;
    }

    public function getMessage() {
        return $this->messages[$this->visa];
    }

}


$visa = new Visa;
$visa->set($visa::NONE,       $no_required);
$visa->set($visa::ON_ARRIVAL, $on_arrival);

echo $visa->getMessage();
Sign up to request clarification or add additional context in comments.

10 Comments

Hopefully I will never have to maintain such a mess ;)
If the values are either 0 or 1, can't you just multiply them by each power of 2? Instead of conditionals.
@Guy Sure, you could also left shift or do a couple of other tricks. I was going for the most obvious solution for somebody apparently not well versed in binary operations. :)
@deceze, I see, just wanted to point that out since the OP asked for an optimized solution.
This is called overengineering:)
|
11
<?php
$messages = array('10000' => 'No Visa Required', '01000' => 'Visa can be obtained on Arrival');
$no_required = '0';
$on_arrival = '1';
$schengen_visa = '0';
$uk_visa = '0';
$usa_visa = '0';

$result = "$no_required$on_arrival$schengen_visa$uk_visa$usa_visa";
if(array_key_exists($result, $messages)){
 echo $messages[$result]; //Visa can be obtained on Arrival
}

?>

Comments

5

I think switch will be good option:

$val=$no_required.$on_arrival.$schengen_visa.$uk_visa.$usa_visa;

switch($val)
{
    case "10000":
        echo "No Visa Required";
        break;
    case "01000"   
        echo "Visa can be obtained on Arrival.";
        break;
    case "00100":
        echo "You need Schengen Visa";
        break;
         .
         .   //Continue to add cases .
}

Comments

3

A little tip:

Why don't you convert all those binary numbers into a integer value and then pass them through a switch statement?

<?php

    $integer_value = convert_binary_to_integer(a,b,c,d,e);

    // I'm not sure PHP provdies a function to convert binary numbers to integers number:
    // But you can write it yourself. It's pretty easy

    switch($integer_value) {
        case 16: // As the first combination of a,b,c,d,e corresponds to number 16 
             // do the appropriate action
        break;
            // ... and so on
    }
?>

Comments

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.