Я создаю систему меню на PHP и MySQL. У меня будет несколько разных меню, и каждое меню будет иметь набор пунктов меню, связанных с ним.
На сайте у меня также есть разные права доступа, некоторые пользователи могут видеть все пункты меню, а некоторые элементы скрыты от некоторых пользователей. Мне любопытно, как я могу обработать разрешения чистым способом, который позволит легко добавлять больше типов пользователей в будущем.
То, что у меня пока есть, примерно так:
-------------------
|Menus
-------------------
|id| |display name|
-------------------
----------------------------------------------------------
|Menu items
----------------------------------------------------------
|id| |menu_id| |label| |link| |parent| |sort| |permission|
----------------------------------------------------------
Я думаю, что permission
столбец может быть строкой через запятую, которую я могу сопоставить с идентификатором разрешения текущего пользователя. Это также может быть ссылка на некоторую другую таблицу, которая определяет все возможные комбинации существующих в настоящее время разрешений.
Одно из решений также может заключаться в том, чтобы просто хранить несколько пунктов меню, где единственным отличием является разрешение, хотя это может привести к дублированию хранилища и, возможно, затруднит администрирование.
Я хотел бы услышать некоторые мысли о том, как структурировать это и что можно считать чистым, динамичным и дерьмовым.
Спасибо.
источник
Ответы:
Я смоделирую это, используя диаграмму ER.
PERMISSION
- это доступ, предоставленный дляROLE
данного объектаMENU_ITEM
.USER
может иметь много ролей.Затем вы можете создать представление, чтобы вам не приходилось каждый раз записывать объединения:
Затем каждый раз, когда вы хотите узнать, к каким пунктам меню пользователь имеет доступ, вы можете запросить его:
РЕДАКТИРОВАТЬ:
Поскольку пользователю может быть предоставлено несколько ролей, разрешения ролей могут перекрываться, то есть две разные роли могут иметь доступ к одному и тому же пункту меню. Когда вы определяете роль, вы заранее не знаете, будет ли она иметь какие-то общие права с другими ролями. Но поскольку речь идет об объединении множеств, имеет значение только то, является ли данное разрешение частью набора, а не сколько раз оно появляется, отсюда и
distinct
условие в представлении.источник
Наличие списка, разделенного запятыми, означает сравнение подстрок каждый раз, когда вы выполняете запрос к меню. Это не идеально.
Вам нужно нормализовать таблицу:
Если вы все еще хотите , разделенный запятыми список (по некоторым причинам), вы можете вытащить его с вещами , такими , как
group_concat
в MySQLwm_concat
в оракула или аналогичные функции на других языках.Преимущество для этого многократное.
Во-первых, практичность звонка. Выполнение подстроки для произвольно большой строки (если вы исправите ее размер, у вас могут возникнуть проблемы с заполнением строки, так что вы начнете получать разрешения, подобные
a
вместоanother_permission
), означает сканирование строки в каждой строке. Это не то, что базы данных выбраны.Во-вторых, запрос, который вы пишете, становится намного проще. Чтобы определить, существует ли разрешение «foo» в списке, разделенном запятыми, необходимо проверить «foo».
Однако это даст ложный положительный результат, если у вас также есть разрешение «foobar». Так что теперь вам нужно пройти тест как
но это даст ложный минус, если 'foo' находится в начале или конце строки. Это приводит к чему-то вроде
Вы заметите, что вполне вероятно, что вам нужно будет сделать несколько сканирований строки. Этот путь ведет к безумию.
Обратите внимание, что со всем этим вам не хватает практической способности связывать параметры (все еще возможно, просто становится еще более уродливым).
Нормализация поля дает вам большую гибкость и удобочитаемость в вашей базе данных. Вы не пожалеете об этом.
источник
Этот классический подход к этому
User -> UserGroup
и затем ассоциируетсяMenu -> MenuItem -> UserGroup
. Использование целочисленного значения для взвешивания уровня разрешения.Когда вам нужно отобразить меню для текущего пользователя. Вы можете запросить базу данных, как это.
Это будет выбирать только те меню, которые видны текущему пользователю на основе условия для
option1
.В качестве альтернативы, если вы сохраняете сведения о группе текущего пользователя в текущем сеансе, то объединение не требуется.
Когда вы говорите о желании сохранить несколько разрешений для каждого пункта меню. Я был бы осторожен, чтобы не перепутать роли пользователей и бизнес-логику.
источник