I had the same problem. I had a function that needs to generate a random number from 0 to 2^32-1 (representing it as a 8-digit hexadecimal string). mt_rand() only generates numbers from 0 to 2^31-1.
This fails:
return hexdec(mt_rand(0,4294967295));
I resolved this with a single line of code:
return sprintf("%04X%04X", (mt_rand(0,65535)), (mt_rand(0,65535)));
What this does is exactly what you suggested, breaking the randomization into parts. It generates two random numbers, each from 0 to 2^16-1 (65,535) (hex 0000 to FFFF), and then concatenates them together using sprintf to zero-pad the results as hexadecimal strings.
Every single number from 0 to 2^32-1 (hex 00000000 to FFFFFFFF) is possible. If you wanted a 48-bit random hexadecimal number (hex 000000000000 to FFFFFFFFFFFF), you could extend this like so:
return sprintf("%04X%04X%04X", (mt_rand(0,65535)), (mt_rand(0,65535)), (mt_rand(0,65535)));
This works for me!