0

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

2
  • Write a script to generate all the combinations and insert them into a table. It is certainly not ideal, but not necessarily wasteful or inefficient. Why do you want to avoid this? An alternative method would be to generate all the combinations and store them as an array and do an isset() check on that array for the lookup. Commented Jan 5, 2016 at 6:26
  • Let us continue this discussion in chat. Commented Jan 6, 2016 at 0:20

2 Answers 2

1

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));
Sign up to request clarification or add additional context in comments.

4 Comments

I tried this out at it works great! The only problem is that this app will have many more values and the url lengths increases as these values increase. If I can keep it shot, that would be great. I ended up with an output like: "MXwyfDQwfDN8NHw1fDZ8N3wzNnw4fDl8MTB8MTF8Mzh8MTJ8MTN8MTR8MTV8Mzd8Mzl8MTZ8MTd8MTh8MTl8MjB8MzJ8MjF8MjJ8MjN8MjR8MjV8MjZ8Mjd8Mjh8Mjl8MzB8MzF8MzN8MzR8MzU=" for an array with 40 values.
yep.. but with 40 values and all possibilties I doubt you will find a more concise way to encode something that can be mapped without using a table and storing every permutation with a key which is what you were trying to avoid. If you found my answer useful please accept and/or upvote.
@billynoah, To limit the 'key' that you send to users that you have to be able to decode again later. imo, You have limited choices: 1) send the actual key encoded. This means 'base64' encoding to be reliable. 2) send a hash (salted sha1 is fine). However, you now need to store the `'hash' => 'link' somewhere. In a database is most likely?
@RyanVincent Yeah, it is appearing more likely that I will need to store something in the database. I am just concerned about all of the possible combinations and the database size...
1

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;
}

11 Comments

This doesn't work. Input an array like array(2,3,4) and you get the ID 'e' which decodes back to array(1,2,3)
@KoreanwGlasses: Will this work with larger arrays? The number of values can be much more than the three given in the example. I tried this with items 1 to 40, the id that I got was: ffffffffff and it contained 32 of the 40 values. I think I may have hit the upper limit. Is there a way to expand this without increasing the Url length by a lot more?
@ShadowZzz Yes there is. I will update the answer as soon as i can.
@KoreanwGlasses: Thanks for the update! I tried it out, but I am getting a different output from the input array that I provided. I have updated my question with a sample input, please let me know what is wrong. Thank You!
@ShadowZzz Try inputting an array of plain of old numbers instead of strings.
|

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.