Estoy creando un sistema de menús en PHP y MySQL. Tendré varios menús diferentes y cada menú tendrá un conjunto de elementos de menú conectados.
En el sitio, también tengo diferentes permisos de usuario, algunos usuarios pueden ver todos los elementos del menú y algunos elementos están ocultos para algunos usuarios. Tengo curiosidad por saber cómo podría manejar los permisos de una manera limpia que permita agregar fácilmente más tipos de usuarios en el futuro.
Lo que tengo hasta ahora es algo como esto:
-------------------
|Menus
-------------------
|id| |display name|
-------------------
----------------------------------------------------------
|Menu items
----------------------------------------------------------
|id| |menu_id| |label| |link| |parent| |sort| |permission|
----------------------------------------------------------
Estoy pensando que la permission
columna podría ser una cadena separada por comas que puedo comparar con la identificación de permiso del usuario actual. También podría ser una referencia a alguna otra tabla que defina todas las combinaciones posibles de los permisos existentes actualmente.
Una solución también podría ser simplemente almacenar múltiples elementos de menú donde la única diferencia es el permiso, aunque esto conduciría a un almacenamiento duplicado y quizás una molestia de administrar.
Me encantaría escuchar algunas ideas sobre cómo estructurar esto y lo que podría considerarse limpio, dinámico y horrible.
Gracias.
fuente
Respuestas:
Lo modelaré usando un diagrama ER.
PERMISSION
es el acceso otorgado a unROLE
en un determinadoMENU_ITEM
.USER
pueden otorgar muchos ROLES.Luego, puede crear una vista para no tener que escribir las combinaciones cada vez:
Luego, cada vez que desee saber a qué elementos de menú tiene acceso un usuario, puede consultarlo:
EDITAR:
Dado que un usuario puede tener múltiples roles otorgados, los permisos de los roles pueden superponerse, es decir, dos roles distintos pueden tener acceso al mismo elemento del menú. Cuando define un rol que no sabe de antemano si tendrá algunos permisos en común con otros roles. Pero dado que se trata de la unión de conjuntos, solo importa si un permiso dado es parte del conjunto, no cuántas veces aparece, de ahí la
distinct
cláusula en la vista.fuente
Tener una lista separada por comas significa hacer una comparación de subcadenas cada vez que realiza una consulta en el menú. Esto es menos que ideal.
Necesitas normalizar la tabla:
Si aún desea la lista separada por comas (por alguna razón), se puede tirar hacia fuera con cosas tales como
group_concat
en MySQLwm_concat
en Oracle o funciones similares en otros idiomas.La ventaja de esto es múltiple.
Primero, está la practicidad de la llamada. Hacer una subcadena contra una cadena arbitrariamente grande (si arregla el tamaño, puede tener problemas más adelante al llenar la cadena para que comience a obtener permisos como en
a
lugar deanother_permission
) significa escanear la cadena en cada fila. Esto no es algo para lo que las bases de datos estén optimizadas.Segundo, la consulta que escribes se vuelve mucho más simple. Para determinar si el permiso 'foo' existe en una lista separada por comas, debe verificar 'foo'.
Sin embargo, esto dará un falso positivo si también tiene el permiso 'foobar'. Entonces ahora necesitas hacerte una prueba como
pero eso dará un falso negativo si 'foo' está al principio o al final de la cadena. Eso lleva a algo como
Notarás que es muy probable que necesites hacer múltiples escaneos de la cadena. Este camino lleva a la locura.
Tenga en cuenta que con todo esto le falta la capacidad práctica para hacer el enlace de parámetros (aún posible, simplemente se pone aún más feo).
La normalización del campo le brinda mucha más flexibilidad y legibilidad en su base de datos. No te arrepentirás.
fuente
Ese enfoque clásico de esto es
User -> UserGroup
y luego asociado aMenu -> MenuItem -> UserGroup
. Usando un valor entero para pesar el nivel de permiso.Cuando necesita mostrar un menú para el usuario actual. Puede consultar la base de datos de esta manera.
Eso solo seleccionará los menús que son visibles para el usuario actual en función de la condición para
option1
.Alternativamente, si almacena los detalles del grupo del usuario actual en la sesión actual, no es necesario unirse.
Cuando habla de querer almacenar múltiples permisos por elemento de menú. Tendría cuidado de no confundir los roles de usuario y la lógica empresarial.
fuente