I'm coding an url shortener function for a project in which I'm learning php, here is the code (btw I suppose that global
here is not a good thing to do :P):
$alphabet = array(1 => "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z",
"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",
"0","1","2","3","4","5","6","7","8","9","_","-");
function shorten($id){
global $alphabet;
$shortenedId = "";
while($id>0){
$remainder = $id % 64;
$id = $id / 64;
$shortenedId = $alphabet[$remainder].$shortenedId;
}
return $shortenedId;
}
The code is taken from this Wikipedia article and adapted to php. My problem is that when I pass a multiple of 64 to the function I get a wrong (for my purpose) result, for instance 128 returns b which is not correct, it should have been aaa, but that's too long for a 3-digit number.
Also I'm starting to think that there's something wrong in this code, if I pass 1'000'000'000'000 as $id
I get nItOq... I feel it's wrong because a url shortening service like bit.ly returns a 6 number id if I use it, and I don't think that this algorithm is better than theirs.
So, two questions:
- do you spot any bug in the above code?
- how to manage 64-multiple ids? Do I have to just ignore them and pass to the next one?
These two functions are very convenient, thanks to @malhal:
You can use the
pack
.It will result in
D62P0WqzFCo=
, it is correct, because the$int
is an int64 and uses 64 bits. The Base64 uses 6 bits for each character, so they need ~11 characters.To decode use:
It will return
1129717211140920362
. ;)It was based in the answer on the Stackoverflow in Portuguese.
In case you're looking for the opposite function to take a base64 number and convert to base10, here's some PHP based off of the JavaScript in this answer: How to convert base64 to base10 in PHP?
Paul Greg created some PHP code that converts from Base-10 to another base. This can be tested and the code downloaded here:
http://www.pgregg.com/projects/php/base_conversion/base_conversion.php
I'm using this approach to convert the database row id's to Base-64. Once these numbers have been shortened they can be used in the URL. [details]
Just a couple of little tweaks needed, the main two were to make the the alphabet zero indexed rather than one-indexed, and to subtract the remainder from the id before dividing
and here's a further modified version which... well I just like
EDIT: sorted concatenation to be the same as the OPs
By the way, check out the base_convert() function (http://php.net/manual/en/function.base-convert.php):
36 is the longest base it can convert to, though. But in the comments section I found this:
Maybe it will help?