That's funny how Stefan Gehrig his answer is actually the correct one. You don't need to convert a string into a "011010101" string to store it in BINARY field in a database. Anyway since this is the first answer that comes up when you google for "php convert string to binary string". Here is my contribution to this problem.
The most voted answer by Francois Deschenes goes wrong for long strings (either bytestrings or bitstrings) that is because
base_convert() may lose precision on large numbers due to properties related to the internal "double" or "float" type used. Please see the Floating point numbers section in the manual for more specific information and limitations.
From: https://secure.php.net/manual/en/function.base-convert.php
To work around this limitation you can chop up the input string into chunks. The functions below implement this technique.
<?php
function bytesToBits(string $bytestring) {
if ($bytestring === '') return '';
$bitstring = '';
foreach (str_split($bytestring, 4) as $chunk) {
$bitstring .= str_pad(base_convert(unpack('H*', $chunk)[1], 16, 2), strlen($chunk) * 8, '0', STR_PAD_LEFT);
}
return $bitstring;
}
function bitsToBytes(string $bitstring) {
if ($bitstring === '') return '';
// We want all bits to be right-aligned
$bitstring_len = strlen($bitstring);
if ($bitstring_len % 8 > 0) {
$bitstring = str_pad($bitstring, intdiv($bitstring_len + 8, 8) * 8, '0', STR_PAD_LEFT);
}
$bytestring = '';
foreach (str_split($bitstring, 32) as $chunk) {
$bytestring .= pack('H*', str_pad(base_convert($chunk, 2, 16), strlen($chunk) / 4, '0', STR_PAD_LEFT));
}
return $bytestring;
}
for ($i = 0; $i < 10000; $i++) {
$bytestring_in = substr(hash('sha512', uniqid('', true)), 0, rand(0, 128));
$bits = bytesToBits($bytestring_in);
$bytestring_out = bitsToBytes($bits);
if ($bytestring_in !== $bytestring_out) {
printf("IN : %s\n", $bytestring_in);
printf("BITS: %s\n", $bits);
printf("OUT : %s\n", $bytestring_out);
var_dump($bytestring_in, $bytestring_out); // printf() doesn't show some characters ..
die('Error in functions [1].');
}
}
for ($i = 0; $i < 10000; $i++) {
$len = rand(0, 128);
$bitstring_in = '';
for ($j = 0; $j <= $len; $j++) {
$bitstring_in .= (string) rand(0,1);
}
$bytes = bitsToBytes($bitstring_in);
$bitstring_out = bytesToBits($bytes);
// since converting to byte we always have a multitude of 4, so we need to correct the bitstring_in to compare ..
$bitstring_in_old = $bitstring_in;
$bitstring_in_len = strlen($bitstring_in);
if ($bitstring_in_len % 8 > 0) {
$bitstring_in = str_pad($bitstring_in, intdiv($bitstring_in_len + 8, 8) * 8, '0', STR_PAD_LEFT);
}
if ($bitstring_in !== $bitstring_out) {
printf("IN1 : %s\n", $bitstring_in_old);
printf("IN2 : %s\n", $bitstring_in);
printf("BYTES: %s\n", $bytes);
printf("OUT : %s\n", $bitstring_out);
var_dump($bytes); // printf() doesn't show some characters ..
die('Error in functions [2].');
}
}
echo 'All ok!' . PHP_EOL;
Note that if you insert a bitstring that is not a multitude of 8 (example: "101") you will not be able to recover the original bitstring when you converted to bytestring. From the bytestring converting back, uyou will get "00000101" which is numerically the same (unsigned 8 bit integer) but has a different string length. Therefor if the bitstring length is important to you you should save the length in a separate variable and chop of the first part of the string after converting.
$bits_in = "101";
$bits_in_len = strlen($bits_in); // <-- keep track if input length
$bits_out = bytesToBits(bitsToBytes("101"));
var_dump($bits_in, $bits_out, substr($bits_out, - $bits_in_len)); // recover original length with substr