ShadowZzz
ShadowZzz

Reputation: 415

Condense multiple values into short Url

I am trying to create something where a user may select various options and be taken to a page based on the selected options. However, the users must be able to come to the unique page using a short URL in the future.

Example of what I am trying to do:

[ ] 1st val
[x] 2nd val
[x] 3rd val
[x] 4th val
[ ] 5th val

Stored in database as: ID = 123DF3 VAL = 2,3,4

User visits: http://website.com/123DF3/

Gets page: You have selected 2, 3 & 4.

Is there a way to do this without having to store every possible combination of the option values in a database (wasteful and inefficient)?

Example:

ID = 123DF3  VAL = 2,3,4
ID = 223FR5  VAL = 2,4,3
ID = 323FG4  VAL = 4,3,2
ID = 253FR7  VAL = 4,2,3
ID = 623GR6  VAL = 3,4,2
ID = 724FR8  VAL = 3,2,4

etc... with increasing possibilities as the amount of values increase.


The alternative is to have every variable in a URL, but it makes the URL very long if there are a lot if values (Eg. http://website.com?v=1,2,3,4,5,6...).

I want to try to avoid this method if possible, but will have to resort to it if I can not come up with a creative way to overcome the above issue.

Sample Input:

array(40) { [0]=> string(1) "1" [1]=> string(1) "2" [2]=> string(2) "40" [3]=> string(1) "3" [4]=> string(1) "4" [5]=> string(1) "5" [6]=> string(1) "6" [7]=> string(1) "7" [8]=> string(2) "36" [9]=> string(1) "8" [10]=> string(1) "9" [11]=> string(2) "10" [12]=> string(2) "11" [13]=> string(2) "38" [14]=> string(2) "12" [15]=> string(2) "13" [16]=> string(2) "14" [17]=> string(2) "15" [18]=> string(2) "37" [19]=> string(2) "39" [20]=> string(2) "16" [21]=> string(2) "17" [22]=> string(2) "18" [23]=> string(2) "19" [24]=> string(2) "20" [25]=> string(2) "32" [26]=> string(2) "21" [27]=> string(2) "22" [28]=> string(2) "23" [29]=> string(2) "24" [30]=> string(2) "25" [31]=> string(2) "26" [32]=> string(2) "27" [33]=> string(2) "28" [34]=> string(2) "29" [35]=> string(2) "30" [36]=> string(2) "31" [37]=> string(2) "33" [38]=> string(2) "34" [39]=> string(2) "35" }

**Note: The the values may not be ordered

Upvotes: 0

Views: 91

Answers (2)

KoreanwGlasses
KoreanwGlasses

Reputation: 284

Here's an idea:

  1. Create a binary number based on what values were chosen. (e.g. (2,3,4) -> 1110; (1,3,4,6) -> 101101)
  2. Convert that number to hex (e.g. 1110 -> E)

Then when your user types in .../E, you convert E to 1110, and you know that values 2,3,4 were selected. This is fast, clean, and requires nothing to be placed in your database

Here's an implementation:

function getID($selectedValues) {
    $bits = 0;
    foreach ($selectedValues as $v)
        $bits += 1<<($v-1);
    return dechex($bits);
}

function getSelectedValues($id) {
    $bits = hexdec($id);
    for ($i = 0; $i < 32; $i++)
        if ( ($bits & (1<<$i)) != 0 )
            $selectedValues[] = $i + 1;
    return $selectedValues;
}

Heres another implementation that can take an arbitrary number of values:

function getID($selectedValues) {
    $bits = array(0,0); // Max no of values = no of 0's * 32. Adjust accordingly.
    foreach ($selectedValues as $v)
        $bits[floor($v/32)] += 1 << ($v - floor($v / 32) * 32 - 1);
    foreach ($bits as $dec)
        $hex[] = dechex($dec);
    return implode('-',$hex);
}

function getSelectedValues($id) {
    $subIDs = explode('-',$id);
    $i = 0;
    foreach($subIDs as $hex) {
        $bits = hexdec($hex);
        for ($j = 0; $j < 32; $j++)
            if ( ($bits & (1<<$j)) != 0 )
                $selectedValues[] = $j + 32 * $i + 1;
        $i++;
    }
    return $selectedValues;
}

Upvotes: 1

You Old Fool
You Old Fool

Reputation: 22941

The shortest and easiest to parse is probably base64_encode() / base64_decode():

ENCODE:

$values = array(2,3,4);
$key = base64_encode(implode('|',$values);

OUTPUT:

MnwzfDQ=

DECODE: (http://example.com/MnwzfDQ=)

$url = $_SERVER['REQUEST_URL'];
$key = basename($url);
$values = explode('|',base64_decode($key));

Upvotes: 1

Related Questions