Estou criando um sistema de menus em PHP e MySQL. Terei vários menus diferentes e cada menu terá um conjunto de itens de menu conectados a ele.
No site, eu também tenho permissões de usuário diferentes, alguns usuários podem ver todos os itens de menu e alguns itens estão ocultos para alguns usuários. Estou curioso para saber como lidar com as permissões de maneira limpa, permitindo que mais tipos de usuários no futuro sejam adicionados facilmente.
O que tenho até agora é algo como isto:
-------------------
|Menus
-------------------
|id| |display name|
-------------------
----------------------------------------------------------
|Menu items
----------------------------------------------------------
|id| |menu_id| |label| |link| |parent| |sort| |permission|
----------------------------------------------------------
Eu estou pensando que o permission
coluna poderia ser uma seqüência separada por vírgula que eu possa corresponder ao ID de permissão do usuário atual. Também poderia ser uma referência a alguma outra tabela que define todas as combinações possíveis das permissões existentes no momento.
Uma solução também poderia ser simplesmente armazenar vários itens de menu em que a única diferença é a permissão, embora isso levasse a armazenamento duplicado e talvez um pouco de administração.
Eu adoraria ouvir algumas reflexões sobre como estruturar isso e o que poderia ser considerado limpo, dinâmico e ruim.
Obrigado.
fonte
Respostas:
Vou modelá-lo usando um diagrama de ER.
PERMISSION
é o acesso concedido aROLE
um dadoMENU_ITEM
.USER
pode ter muitos ROLEs concedidos a ele.Em seguida, você pode criar uma exibição para não precisar gravar as junções sempre:
Então, sempre que quiser saber a quais itens de menu um usuário tem acesso, você pode consultá-lo:
EDITAR:
Como um usuário pode ter várias funções concedidas, as permissões das funções podem se sobrepor, ou seja, duas funções distintas podem ter acesso ao mesmo item de menu. Quando você define uma função, não sabe de antemão se ela terá algumas permissões em comum com outras funções. Mas como se trata da união de conjuntos, importa apenas se uma determinada permissão faz parte do conjunto ou não, quantas vezes ela aparece, daí a
distinct
cláusula na exibição.fonte
Ter uma lista separada por vírgula significa fazer uma comparação de substring cada vez que você faz uma consulta no menu. Isso é menos que o ideal.
Você precisa normalizar a tabela:
Se você ainda deseja que a lista separada por vírgula (por alguma razão), você pode retirá-lo com coisas como
group_concat
no mysqlwm_concat
no oracle ou funções similares em outras línguas.A vantagem disso é múltipla.
Primeiro, há a praticidade da ligação. Fazer uma substring em uma string arbitrariamente grande (se você corrigir o tamanho, poderá ter problemas mais tarde ao preencher a string para começar a obter permissões como em
a
vez deanother_permission
) significa digitalizar a string em cada linha. Isso não é algo para o qual os bancos de dados são otimizados.Segundo, a consulta que você escreve se torna muito mais simples. Para determinar se a permissão 'foo' existe em uma lista separada por vírgulas, é necessário verificar se há 'foo'.
No entanto, isso dará um falso positivo se você também tiver a permissão 'foobar'. Então agora você precisa fazer um teste como
mas isso dará um falso negativo se 'foo' estiver no início ou no final da string. Isso leva a algo como
Você notará que é bem provável que você precise fazer várias varreduras da string. Este caminho leva à loucura.
Observe com tudo isso que você não tem a capacidade prática de fazer a ligação de parâmetros (ainda possível, apenas fica ainda mais feia).
A normalização do campo oferece uma flexibilidade e legibilidade muito maiores no seu banco de dados. Você não vai se arrepender.
fonte
Essa abordagem clássica para isso é
User -> UserGroup
e depois é associada aMenu -> MenuItem -> UserGroup
. Usando um valor inteiro para pesar o nível de permissão.Quando você precisa exibir um menu para o usuário atual. Você pode consultar o banco de dados assim.
Isso selecionará apenas os menus visíveis ao usuário atual com base na condição para
option1
.Como alternativa, se você armazenar os detalhes do grupo do usuário atual na sessão atual, nenhuma associação será necessária.
Quando você fala sobre o desejo de armazenar várias permissões por item de menu. Tome cuidado para não confundir as funções do usuário e a lógica de negócios.
fonte