Lowercase:
sprintf('%06x', mt_rand(0, 16777215))
Uppercase:
sprintf('%06X', mt_rand(0, 16777215))
(demo)
Reference:
16777215 is 166-1. It's likely that you'll get dupes so you need to store previous values somewhere (typically a database) and check for uniqueness.
Another solution is to generate all 17 million codes at once, shuffle them and pick one each time.
First time:
$all_codes = range(0, 16777215);
shuffle($all_codes);
$sql = 'INSERT INTO all_codes (id, code, taken) VALUES (?, ?, ?)';
foreach ($all_codes as $index => $code) {
$values = [
$index+1,
sprintf('%06X', $code),
false
];
$your_database_library->query($sql, $values);
}
This script is pure non-optimised brute force so you'll need to increase PHP memory limit (it needs like half GB) but it's a one-time task.
Then, every time you need a code (let's assume MySQL):
SELECT id, code
FROM all_codes
WHERE used = 0
ORDER BY 1
LIMIT 1
FOR UPDATE;
UPDATE all_codes
SET used = 1
WHERE id = ?;
Alternatively, you could store them in sequence and pick randomly among the unused, making sure to implement a solution that's fast in your DBMS (because you're randomising every time) but that looks like more work :)