siv1987 2,630 10/08/2020 11:09 PM Уже целый час мучаюсь, не пойму как теперь работают битовые опции. В IPB 3 был класс IPSBWOptions с методами freeze и thaw которые конвертировали значение integer в массив с опциями, и обратно. А как сейчас с этим работать не пойму. Вижу класс \IPS\Patterns\Bitwise, вижу что автоматическая поддержка битовых полей в есть ActiveRecord, но как с ними работать без ActiveRecord? Может кто имел дело Share this post Link to post
TemKa_SD 9 10/10/2020 01:46 AM (edited) Здравствуйте. Я работаю с ними. Вам что нужно сделать? Сохранение в group? public function get_access($g_wc3_access) { $access = []; $commands = \IPS\Db::i()->select( 'name, access', 'wc3_commands', ['enabled = 1 AND access != 0'] ); foreach (iterator_to_array($commands) as $v) { $access[$v['name']] = $v['access']; } $bw = new \IPS\Patterns\Bitwise( array( 'access' => ['access'] ), ['access' => $access]); $bw->values['access'] = $g_wc3_access; $bw->originalValues['access'] = $g_wc3_access; $bwArray = $bw->asArray(); foreach ($bwArray as $k => $v) { if (!\is_string($k)) unset($bwArray[$k]); } return ['bwArray' => $bwArray, 'access' => $access]; } Я написал такой вот метод для себя, всё работает. Edited October 10, 2020 by TemKa_SD Share this post Link to post
siv1987 2,630 10/10/2020 09:07 AM Мне нужно сохранить битовое значение нескольких полей в кастомную таблицу. @TemKa_SDнасколько я знаю из документации в конструкторе объекта Bitwise первый элемент битовое значение поле, второе маски ключей, у вас же все наоборот. На ночь глядя так и не смог разобраться, а утром проснувшись и еще раз взглянув на документацию кажется я понял как они работают. /* Битовая маска */ $bitOptions = array( 'mod_bitoptions' => array( 'gbw_soft_delete' => 1, 'gbw_un_soft_delete' => 2, 'gbw_soft_delete_see' => 4, 'gbw_soft_delete_reason' => 8, 'gbw_soft_delete_see_post' => 16, 'bw_mod_soft_delete' => 32, 'bw_mod_un_soft_delete' => 64, 'bw_mod_soft_delete_see' => 128, 'bw_mod_soft_delete_reason' => 256, 'bw_mod_soft_delete_see_post' => 512, )); /* Конструктор объекта Bitwise * @param Значение из бд $row['mod_bitoptions'] * @param Битовая маска для полей $bitOptions */ $bitwise = new \IPS\Patterns\Bitwise( array( 'mod_bitoptions' => $row['mod_bitoptions'] ), $bitOptions ); /* Устанавливаем нужные флажки для переменных */ $bitwise['gbw_soft_delete'] = true; $bitwise['gbw_un_soft_delete'] = true; $bitwise['bw_mod_soft_delete_see_post'] = true; /* Битовое значение для записи в бд */ $row['mod_bitoptions'] = $bitwise->values['mod_bitoptions']; У вас там какая-то каша в примере если честно. Даже если предположить что в wc3_commands хранится битовая маска, то это зачем 'access' => ['access']? И это тоже $bw->values['access'] = $g_wc3_access, ведь там хранится битовое значение полей массива, а вы его сами задаете. В общем логика странная, но спасибо за пример, он заставил меня еще раз взглянуть на документацию. Share this post Link to post
TemKa_SD 9 10/10/2020 10:21 AM @siv1987 Там у меня между масками есть пропуски, например: идет число 8, затем должно идти 16, но у меня 128 например, Bitwise автоматически заполняет, есть есть такие пропуски, так вот, я перебрал массив и вернул что мне нужно. Share this post Link to post
TemKa_SD 9 10/10/2020 03:26 PM @siv1987 Смотрите, давайте обсудим мой код, тоже интересно, правильно ли я всё сделал. 1. Я собираю все ключи и маски из БД, они хранятся у меня там, так как выводятся еще в приложении C++, поэтому, нет смысла держат их в переменной IPS. $commands = \IPS\Db::i()->select( 'name, access', 'wc3_commands', ['enabled = 1 AND access != 0'] ); https://prnt.sc/uwqdn9 2. Этот массив некорректен, его нужно преобразовать в ключ => маска: $access = []; foreach (iterator_to_array($commands) as $v) { $access[$v['name']] = $v['access']; } https://prnt.sc/uwqekg 3. Дальше передаем собранные данные в \IPS\Patterns\Bitwise $bw = new \IPS\Patterns\Bitwise( array( 'access' => ['access'] ), ['access' => $access]); https://prnt.sc/uwqfn2 - здесь вот я обвел, о чем говорил выше, он создает данные с отсутствующими масками, нужно их вырезать. https://prnt.sc/uwqgfc - здесь кстати у меня вопрос, сюда же должна залетать сумма всех масок которые нужны для проверки? Т.е вместо кода $bw = new \IPS\Patterns\Bitwise( array( 'access' => ['access'] ), ['access' => $access]); $bw->values['access'] = $g_wc3_access; $bw->originalValues['access'] = $g_wc3_access; Достаточно $bw = new \IPS\Patterns\Bitwise( array( 'access' => $g_wc3_access ), ['access' => $access]); Я проверил, вроде работает. Результат: https://prnt.sc/uwqj4j 4. Далее вырезаем выше упомянутые пустые ключи: $bwArray = $bw->asArray(); foreach ($bwArray as $k => $v) { if (!\is_string($k)) unset($bwArray[$k]); } https://prnt.sc/uwqjq0 5. Касательно этого return ['bwArray' => $bwArray, 'access' => $access]; $bwArray - битопшионс, массив с true/false значениями доступа. $access - нужен для формы https://prnt.sc/uwqkze https://prnt.sc/uwqlg4 ------------------ https://prnt.sc/uwqlth Share this post Link to post
siv1987 2,630 10/10/2020 09:22 PM Я так понимаю массив битовых масок у вас находится в базе данных. Метод у вас будет состоять из следующего кода: Получаем из бд масски и создаем из него массив $bitOptions где значение поле "access" а ключ поле "name" $bitOptions = iterator_to_array( \IPS\Db::i()->select( 'name, access', 'wc3_commands', ['enabled = 1 AND access != 0'] ) ); $bitOptions = array_column( $bitOptions, 'access', 'name' ); Создаем объект \IPS\Patterns\Bitwise, в качестве первого аргумента указываем старое int значение прежних настроек , а для второго аргумента наш массив $bitOptions $g_wc3_access это битовое целое число всех настроек. $access = new \IPS\Patterns\Bitwise( array( 'access' => $g_wc3_access ), ['access' => $bitOptions]); Возвращаем объект return $access; Объект Bitwise реализует класс ArrayAccess, а значит к нему можно обращаться как к обычному массиву (для полей формы) $access['ban'] = true; $access['autostart'] = true; В объекте автоматически будет вычисляться битовое значение всех его настроек которое можно получить из $access->values['access'] и сохранить его в базе данных. Удалять автокомплитные поля массива наверное не нужно, они нужны для правильной работы класса, и ничем по сути не мешают. Ну если вы генерируете форму из этих полей тогда просто их исключите при фетчинге foreach( $access->asArray() as $k => $v ) { if( !is_string( $k ) ) { continue; } } Share this post Link to post