Правильный способ хранения 32-битного двоичного файла в Laravel

В данный момент я использую

/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::create('test_binary', function (Blueprint $table) {
        $table->increments('id');
        $table->char('binary_number', 32)->charset('binary'); // From: https://stackoverflow.com/a/62615777/5675325
        $table->timestamps();

    });
}

для хранения 32-битных двоичных чисел, таких как 00000000000000000000000000000010, которые являются результатом

$binaryString = str_pad(base_convert(2, 10, 2),32,'0',STR_PAD_LEFT);

и хранятся в такой таблице

введите здесь описание изображения

В сеялке есть что-то вроде

'binary_number' => str_pad(base_convert(2, 10, 2),32,'0',STR_PAD_LEFT),

Что касается типа BINARY в БД (как показано на предыдущем изображении), apokryfos предложил

Я думаю, что bit — это то, что вам здесь нужно, хотя я не совсем уверен, что Laravel поддерживает поэтому вам может понадобиться использовать DB::raw("b'000000010'") для вставки данных в битовые столбцы

Ярек Ткачик согласен с частью (I'm not fully sure that Laravel supports that)

Наличие поля битового типа означает, что вам нужно использовать необработанные значения в качестве обходного пути всякий раз, когда вы вставляете/обновляете это поле. (...)

DB::table('table')->insert(['bit_field' => DB::raw(0)]); // inserts 0

и он предлагает OP измениться на tinyint, если он может (для случая столбца, который может иметь значение 0 или 1).

Это может указывать на то, что если кто-то хочет иметь дело с битом размером 32 через миграции Laravel, он захочет использовать целое число большего размера, чем tinyint.

Итак, если бы я хотел иметь int размером 32, указывает Алексей Мезенин

Вы не можете сделать это, но вы можете использовать различные типы целых чисел:

$table->bigInteger()
$table->mediumInteger()
$table->integer()
$table->smallInteger()
$table->tinyInteger()

Что должно случиться с

$table->char('binary_number', 32)->charset('binary');

затем разместить 32-битные двоичные числа в качестве значений и как вставлять/извлекать такие записи?


person Tiago Martins Peres 李大仁    schedule 26.03.2021    source источник
comment
Неправильно хранить избыточно то, что можно легко вычислить. Сохраните только id и используйте формулу, если вам нужна ее битовая версия. Или объясните причину избыточности.   -  person Rick James    schedule 31.03.2021


Ответы (1)


Входные данные в вашей базе данных должны быть типа целого числа без знака размером 32 бита или 4 байта.

$table->unsignedInteger();

Таким образом, сохранение значения не должно быть проблемой, у вас просто есть двоичное значение для переключения на десятичное с помощью bindec() или простой SUM с использованием метода констант.

Для части запроса, скажем, вы хотите, чтобы результаты имели 3-й бит равным 1.

$query->whereRaw('BIT_COUNT(4 & fieldName) = 1')

я привык назначать константы для тех значений в соответствующей модели, которые помогают поддерживать код и отлаживать.

class User extends Model {
const NOTIFICATION_FRIEND = 1; //2^0 or 0000 ... 0000 0001
const NOTIFICATION_CLIENT = 2; //2^1 or 0000 ... 0000 0010
const NOTIFICATION_APP = 4; //2^2 or 0000 ... 0000 0100
const NOTIFICATION_VENDOR = 8; //2^3 or 0000 ... 0000 1000
//...
// up to a max of 32nd one wich is 2147483648 (or 2^31)
}

Итак, запрос выглядит так

$usersToBeNotified = $currentUser->friends()
    ->whereRaw('BIT_COUNT('.User::NOTIFICATION_FRIEND .' & notification_preferences) = 1')
    ->get();

Чтобы построить целое число, которое будет храниться в форме, просто просуммируйте константы.

$user->notification_preferences  = User::NOTIFICATION_FRIEND + User::NOTIFICATION_APP;
person N69S    schedule 01.04.2021