Tworzę system menu w PHP i MySQL. Będę miał kilka różnych menu i do każdego menu będzie podłączony zestaw elementów menu.
Na stronie mam również różne uprawnienia użytkowników, niektórzy użytkownicy mogą zobaczyć wszystkie elementy menu, a niektóre elementy są ukryte przed niektórymi użytkownikami. Jestem ciekawy, jak mogę obsłużyć uprawnienia w czysty sposób, który pozwoli na łatwe dodawanie większej liczby użytkowników w przyszłości.
Do tej pory mam coś takiego:
-------------------
|Menus
-------------------
|id| |display name|
-------------------
----------------------------------------------------------
|Menu items
----------------------------------------------------------
|id| |menu_id| |label| |link| |parent| |sort| |permission|
----------------------------------------------------------
Myślę, że permission
kolumna może być ciągiem oddzielonym przecinkami, który mogę dopasować do identyfikatora bieżącego użytkownika. Może to być również odniesienie do innej tabeli, która definiuje wszystkie możliwe kombinacje obecnie istniejących uprawnień.
Jednym rozwiązaniem może być po prostu przechowywanie wielu pozycji menu, w których jedyną różnicą jest pozwolenie, chociaż prowadziłoby to do podwójnego przechowywania i być może uciążliwe.
Bardzo chciałbym usłyszeć, jak to ustrukturyzować i co można uznać za czyste, dynamiczne i kiepskie.
Dzięki.
źródło
Odpowiedzi:
Będę go modelować za pomocą schematu ER.
PERMISSION
to dostęp przyznany dlaROLE
danegoMENU_ITEM
.USER
Może mieć wiele ról przyznane jej.Następnie możesz utworzyć widok, abyś nie musiał zapisywać złączeń za każdym razem:
Następnie za każdym razem, gdy chcesz wiedzieć, do jakich elementów menu ma dostęp użytkownik, możesz zapytać:
EDYTOWAĆ:
Ponieważ użytkownik może mieć przydzielone wiele ról, uprawnienia ról mogą się nakładać, tzn. Dwie różne role mogą mieć dostęp do tego samego elementu menu. Kiedy definiujesz rolę, nie wiesz wcześniej, czy będzie ona miała jakieś uprawnienia wspólne z innymi rolami. Ale ponieważ chodzi o połączenie zbiorów, ważne jest tylko to, czy dane pozwolenie jest częścią zestawu, a nie ile razy się pojawia, stąd
distinct
klauzula w widoku.źródło
Posiadanie listy oddzielonej przecinkami oznacza wykonanie porównania podciągów za każdym razem, gdy wykonujesz zapytanie względem menu. To mniej niż idealne.
Musisz znormalizować tabelę:
Jeśli nadal chcesz oddzielonej przecinkami listę (z jakiegoś powodu), można wyciągnąć go z rzeczy, takich jak
group_concat
w MySQLwm_concat
w oracle lub podobne funkcje w innych językach.Zaletą tego jest wielokrotność.
Po pierwsze, praktyczność połączenia. Wykonanie podłańcucha przeciwko dowolnie dużemu ciągowi (jeśli poprawisz jego rozmiar, możesz później mieć problemy z wypełnieniem łańcucha, aby zacząć uzyskiwać uprawnienia jak
a
zamiastanother_permission
), oznacza skanowanie łańcucha w każdym rzędzie. Nie jest to opcja, dla której bazy danych są zoptymalizowane.Po drugie, zapytanie, które piszesz, staje się znacznie prostsze. Aby ustalić, czy uprawnienie „foo” istnieje na liście oddzielonej przecinkami, musisz sprawdzić, czy występuje „foo”.
Daje to jednak fałszywie pozytywny wynik, jeśli masz również pozwolenie „foobar”. Więc teraz musisz mieć taki test
ale da to fałszywy wynik ujemny, jeśli „foo” znajduje się na początku lub na końcu łańcucha. To prowadzi do czegoś takiego
Zauważysz, że jest prawdopodobne, że będziesz musiał wykonać wiele skanów ciągu. Ta droga prowadzi do szaleństwa.
Zauważ, że w przypadku wszystkich tych elementów brakuje praktycznej zdolności do wiązania parametrów (nadal jest to możliwe, staje się jeszcze bardziej brzydkie).
Normalizacja pola daje znacznie większą elastyczność i czytelność w bazie danych. Nie pożałujesz.
źródło
To klasyczne podejście do tego jest
User -> UserGroup
następnie powiązaneMenu -> MenuItem -> UserGroup
. Użycie wartości całkowitej do ważenia poziomu uprawnień.Kiedy musisz wyświetlić menu dla bieżącego użytkownika. Możesz wykonać zapytanie do bazy danych w ten sposób.
Spowoduje to wybranie tylko menu widocznych dla bieżącego użytkownika na podstawie warunku dla
option1
.Alternatywnie, jeśli przechowujesz dane grupy bieżącego użytkownika w bieżącej sesji, wówczas nie jest wymagane łączenie.
Gdy mówisz o chęci przechowywania wielu uprawnień na element menu. Uważam, aby nie pomylić ról użytkowników i logiki biznesowej.
źródło