2016-08-31 3 views
2

У меня проблема. Как я должен выполнять разрешения, которые можно постоянно добавлять/изменять?Какие существуют флаги/разрешения?

Теперь у меня есть это:

  • моя схема таблицы базы данных имеет полю flags
  • я могу выбрать то, что мне нужно с помощью, например, SELECT * from some_table WHERE flags&'.FLAG_CLOSED|FLAG_ACTIVE.'='.FLAG_CLOSED|FLAG_ACTIVE;
  • все флаги являются константами внутри кода

образец кода, только для выяснения того, что я имею в виду (это не настоящий код, он даже не проверен):

class Sample { 

    const FLAG_ACTIVE = 0x01; 
    const FLAG_CLOSED = 0x02; 
    const FLAG_DELETED = 0x04; 

    private $db; 

    public function __construct(...) { 
     /* ... */ 
    } 

    public function getClosed() { 
     $flags = self::FLAG_ACTIVE | self::FLAG_CLOSED; 
     $query = 'SELECT * FROM `test` WHERE `flags`&'.$flags.'='.$flags; 
     $stmt = $this->db->query($query); 
     return $stmt->fetch(\PDO::FETCH_ASSOC); 
    } 
} 

Легко получить результат фильтрации только через одно полевое сравнение, но это так раздражает, чтобы изменить его внутри кода.

Другой способ сделать дополнительную таблицу, которая должна иметь флаг и значение. Но что будет более эффективным? Если значение имеет значение на основе битового поля (т. Е. 1, 2, 4, 8 и т. Д.) Или что-то еще, например «ЗАКРЫТО», «АКТИВНО»?

В двух случаях таблицы строка выглядит следующим образом:

id, description, flags 
=============== 
1, 'test', 0x12 
1, 'test', 'CLOSED,ACTIVE' 

во втором случае мне нужно фильтровать `WHERE флаги, как«% ЗАКРЫТО%»и флаги, как '% ACTIVE%?

О, это другой способ реализации флагов. Сделать таблицу с Id и Flag. Нравится:

Id, flag 
======== 
1, CLOSED 
1, ACTIVE 

Может быть, здесь существует более эффективная реализация?

p.s. sry для неудобства, это первый вопрос, быть терпеливым

p.p.s. Мне не нужно точно повторять эту схему, я просто прошу совета, как это сделать более эффективным образом, это может быть абсолютно простая реализация без каких-либо значений битовых полей.

+2

Если вы действительно хотите это сделать, взгляните на тип данных 'SET'.Но я рекомендую вам просто создать таблицу, в которой каждый флаг находится в отдельной строке, а не комбинировать их как биты, потому что битовые поля, подобные этому, не могут быть проиндексированы. – Barmar

+0

@Barmar, спасибо за совет, это выглядит, что мне нужно, но могу ли я продлить SET с помощью новых флагов без каких-либо проблем, например, предположим, что таблица имеет 700 тыс. Записей? Могу ли я получить все значения SET из базы данных? и как насчет эффективности, хотя я могу использовать кеш ... – Wizard

+0

Пока вы не меняете порядок элементов 'SET', вы можете без проблем расширять его. 'SET' реализуется внутри как бит-поле так же, как и вы. – Barmar

ответ

2

Не используйте для этого одно поле флага, используйте таблицу с отдельной строкой для каждого флага.

CREATE TABLE flags (
    thing_id INT, 
    flag VARCHAR(32), 
    PRIMARY KEY (thing_id, flag), 
    FOREIGN KEY (thing_id) REFERENCES things (id), 
    INDEX (flag) 
); 

Ряды будут выглядеть следующим образом:

thing_id flag 
1  active 
1  closed 
2  closed 
3  deleted 
3  active 

Тогда, чтобы найти все вещи с определенным флагом, вы присоединитесь к таблице:

SELECT t.* 
FROM things AS t 
JOIN flags as f ON f.thing_id = t.id 
WHERE f.flag = 'closed'; 

Чтобы получить все флаги вещи, в использование GROUP_CONCAT

Если вы хотите предотвратить создание флагов, которые не должны существовать, вы можете сделать столбец flag внешним ключом в таблице flag_names.

+0

Спасибо за ответ. Это все (и даже больше) то, что мне нужно услышать. Очень ценю. – Wizard

+0

В качестве предложения - его можно улучшить с некоторыми ограничениями, если значение будет int (1,2,4 ... 32). И мы можем получить все флаги без 'concat', но с' sum'. Предел - мы не можем иметь более 32/64 флагов на 'вещь', без поддержки bigint. В большинстве случаев этого достаточно. – Wizard

+0

На самом деле наша компания имела таблицу с числовым столбцом 'flags', и мы перешли на этот метод, когда мы переполнили его. Для всех приложений, которые были написаны для использования числовых флагов, мы добавили хранимую функцию для преобразования. – Barmar