उपयोगकर्ता अनुमतियों के साथ मेनू आइटम संग्रहीत करना


11

मैं PHP और MySQL में एक मेनू सिस्टम बना रहा हूँ। मेरे पास कई अलग-अलग मेनू होंगे और प्रत्येक मेनू में मेनू से जुड़े आइटम होंगे।

साइट पर, मेरे पास अलग-अलग उपयोगकर्ता अनुमतियां हैं, कुछ उपयोगकर्ता सभी मेनू आइटम देख सकते हैं और कुछ आइटम कुछ उपयोगकर्ताओं से छिपे हुए हैं। मैं इस बात को लेकर उत्सुक हूं कि मैं साफ-सुथरे तरीके से अनुमतियों को कैसे संभाल सकता हूं जो भविष्य में अधिक प्रकार के उपयोगकर्ताओं को आसानी से जोड़ने की अनुमति देगा।

इस प्रकार मेरे पास अभी तक कुछ इस तरह है:

-------------------
|Menus
-------------------
|id| |display name|
-------------------

----------------------------------------------------------
|Menu items
----------------------------------------------------------
|id| |menu_id| |label| |link| |parent| |sort| |permission|
----------------------------------------------------------

मैं सोच रहा हूं कि permissionस्तंभ या तो एक अल्पविराम से अलग स्ट्रिंग हो सकता है जिसे मैं वर्तमान उपयोगकर्ता की अनुमति आईडी के खिलाफ मैच कर सकता हूं। यह किसी अन्य तालिका का संदर्भ भी हो सकता है जो वर्तमान में मौजूद अनुमतियों के सभी संभावित संयोजनों को परिभाषित करता है।

एक समाधान केवल कई मेनू आइटमों को संग्रहीत करने के लिए हो सकता है जहां एकमात्र अंतर अनुमति है, हालांकि यह डुप्लिकेट भंडारण और शायद एक दर्द को प्रशासित करेगा।

मैं इस संरचना को कैसे और स्वच्छ, गतिशील और भद्दा माना जा सकता है, इस पर कुछ विचार सुनना पसंद करूंगा।

धन्यवाद।


क्या उपयोगकर्ताओं में कुछ सामान्य है? आमतौर पर आप मेनू आइटम को कार्यात्मक समूहों में समूहित करते हैं और उपयोगकर्ताओं को उन समूहों को सौंपते हैं (उदाहरण के लिए - व्यवस्थापक उपयोगकर्ता, DB उपयोगकर्ता, व्यापारी आदि)। तब आप सिर्फ ग्रुपिंग का प्रबंधन करते हैं, प्रौद्योगिकी की पसंद पर निर्भर करता है - इसे सक्रिय निर्देशिका जैसी किसी चीज का उपयोग करके प्रबंधित किया जा सकता है।
माइकल

1
आपको यहाँ बहुत अच्छे उत्तर मिल रहे हैं, लेकिन आप एसीएल के बारे में क्या पढ़ना चाहते हैं। en.wikipedia.org/wiki/Access_control_list
Reactgular

जवाबों:


18

मैं इसे ईआर आरेख का उपयोग करके मॉडल करूंगा।

  • A PERMISSION, ROLEकिसी दिए गए पर दी गई पहुंच है MENU_ITEM
  • एक रोल पूर्व-निर्धारित अनुमतियों का एक सेट है जिसे एक नाम दिया गया है
  • A के USERपास इसके लिए कई ROLE हो सकते हैं।
  • उपयोगकर्ताओं के बजाय भूमिकाओं के लिए अनुमतियाँ होने से अनुमतियों का प्रशासन बहुत आसान हो जाता है।

यहां छवि विवरण दर्ज करें

फिर आप एक दृश्य बना सकते हैं ताकि आपको हर बार जॉइन न करना पड़े:

create or replace view v_user_permissions
select
    distinct mi.id, mi.menu_id. mi.label. mi.link, mi.parent, mi.sort, u.user_id
from
    user u
    join user_role ur on (u.user_id = ur.user_id)
    join role ro on (ur.role_id = role.role_id)
    join permission per on (ro.role_id = per.role_id)
    join menu_item mi on (per.metu_item_id = mi.metu_item_id)

फिर हर बार जब आप जानना चाहते हैं कि उपयोगकर्ता के लिए कौन से मेनू आइटम हैं, तो आप इसे क्वेरी कर सकते हैं:

select * from v_user_permissions up where up.user_id = 12736 order by up.sort

संपादित करें:

चूंकि एक उपयोगकर्ता को कई भूमिकाएं दी जा सकती हैं, इसलिए भूमिकाओं की अनुमतियां ओवरलैप हो सकती हैं, अर्थात दो अलग-अलग भूमिकाओं में एक ही मेनू आइटम तक पहुंच हो सकती है। जब आप किसी भूमिका को परिभाषित करते हैं तो आप पहले से नहीं जानते हैं कि इसमें अन्य भूमिकाओं के साथ कुछ अनुमतियाँ होंगी या नहीं। लेकिन चूंकि यह सेटों के मिलन के बारे में है, इसलिए यह केवल मायने रखता है कि दी गई अनुमति सेट का हिस्सा है या नहीं, यह कितनी बार दिखाई देती है, इसलिए distinctदृश्य में खंड।


बहुत अच्छे धन्यवाद। देख नहीं सकता कि मैं सिर्फ अपने आप को क्यों नहीं खींच सकता। मुझे लगता है कि मैं अवरुद्ध और गैर अनुभवी था :)
स्पैन

Ack, मुझे लगा कि मैं समझ गया हूं लेकिन जाहिर है कि नहीं। किसी एकल मेनू आइटम के लिए मेरे पास कई अनुमतियाँ कैसे हो सकती हैं?
अवधि

1
@span क्योंकि किसी उपयोगकर्ता की कई भूमिकाएँ हो सकती हैं और भूमिकाओं की अनुमतियां ओवरलैप हो सकती हैं, अर्थात दो अलग-अलग भूमिकाओं में एक ही मेनू आइटम तक पहुँच हो सकती है। जब आप किसी भूमिका को परिभाषित करते हैं तो आप पहले से नहीं जानते हैं कि क्या भूमिका अन्य के साथ दी जाएगी जो इसके साथ कुछ अनुमतियाँ हैं। लेकिन चूंकि यह समस्या सेटों के मिलन के बारे में है, इसलिए यह केवल इस बात पर निर्भर करता है कि दी गई अनुमति सेट का हिस्सा है या नहीं, कितनी बार यह प्रकट होता है।
ट्यूलेंस कोर्डोवा

धन्यवाद, मैं आपके उत्तर को तब तक पढ़ता रहूँगा जब तक मैं इसे प्राप्त नहीं करता;) मुझे लगता है कि मेरी गलती यह सोचने में थी कि मेनू आइटम को अलग करने के लिए भूमिका के साथ एक एकल अनुमति का उपयोग किया जा सकता है। ऐसा लगता है कि मुझे मेनू आइटम के प्रत्येक 'प्रकार' के लिए अनुमति चाहिए। एक बार फिर, आपकी सहायता के लिए धन्यवाद! मैं कुछ वेन रेखाचित्र खींचते हैं और अगर मैं ठीक से \ o / उसके चारों ओर मेरे सिर प्राप्त कर सकते हैं देखेंगे
अवधि

5

अल्पविराम से अलग होने की सूची का मतलब है कि हर बार जब आप मेनू के खिलाफ क्वेरी करते हैं तो एक तुलनात्मक तुलना करना। यह आदर्श से कम है।

आपको तालिका को सामान्य करने की आवश्यकता है:

---------------------------------------------
|Menu items
---------------------------------------------
|id| |menu_id| |label| |link| |parent| |sort|
---------------------------------------------

+---------------------------+
| menu_permission           |
|---------------------------|
| |menu_permission_id| (pk) |
| |menu_id| (fk)            |
| |permission|              |
+---------------------------+

आप अभी भी अल्पविराम पृथक सूची (किसी कारण के लिए) चाहते हैं, आप इसे बाहर चीजों के साथ इस तरह के रूप खींच सकते group_concatमें mysql wm_concat में ओरेकल या अन्य भाषाओं में समान कार्य करता है।

इसके लिए लाभ कई गुना है।

सबसे पहले, कॉल की व्यावहारिकता है। एक मनमाने ढंग से बड़ी स्ट्रिंग के खिलाफ एक विकल्प करना (यदि आप इसे आकार को ठीक करते हैं, तो आपको स्ट्रिंग को भरने के साथ बाद में समस्याएं हो सकती हैं, इसलिए आपको aइसके बजाय अनुमतियां मिलनी शुरू हो जाती हैं another_permission) का अर्थ है प्रत्येक पंक्ति पर स्ट्रिंग को स्कैन करना। यह ऐसा कुछ नहीं है जिसे डेटाबेस के लिए ऑप्टिमाइज़ किया जाता है।

दूसरा, आपके द्वारा लिखी गई क्वेरी बहुत सरल हो जाती है। यह निर्धारित करने के लिए कि अनुमति 'फू' कॉमा से अलग की गई सूची में मौजूद है, आपको 'फू' की जांच करनी होगी।

... permission like "%foo%" ...

हालांकि, यह एक गलत सकारात्मक देगा यदि आपके पास 'फ़ॉबर' की अनुमति है। इसलिए अब आपको टेस्ट करने की जरूरत है

... permission like "%,foo,%" ...

लेकिन यह एक गलत नकारात्मक देगा यदि 'फू' स्ट्रिंग के आरंभ या अंत में है। जिसके कारण कुछ ऐसा होता है

... (permission like "foo,%" 
  or permission like "%,foo,%" 
  or permission like "%,foo" ) ...

आप ध्यान देंगे कि यह काफी संभावना है कि आपको स्ट्रिंग के कई स्कैन करने की आवश्यकता होगी। इस तरह पागलपन की ओर जाता है।

इन सभी के साथ ध्यान दें कि आपको पैरामीटर बाइंडिंग करने के लिए व्यावहारिक क्षमता की कमी है (अभी भी संभव है, बस और भी बदसूरत हो जाता है)।

फ़ील्ड को सामान्य करने से आपको अपने डेटाबेस में बहुत अधिक लचीलापन और सुगमता मिलती है। आप इसे पछतावा नहीं करेंगे।


आपके महान उत्तर के लिए धन्यवाद, इसने मुझे और ज्ञान दिया है और मैं इसके लिए बहुत अच्छा हूँ, हालांकि मुझे लगता है कि user61852 समाधान अभी के लिए सबसे अच्छा होगा।
अवधि

3

यह उस के लिए शास्त्रीय दृष्टिकोण है User -> UserGroupऔर फिर एक जुड़ा हुआ है Menu -> MenuItem -> UserGroup। अनुमति स्तर को तौलने के लिए पूर्णांक मान का उपयोग करना।

-------------------
|Menu
-------------------
|id| |display name|
-------------------

-------------------------------------------------------------
|Menu Item
-------------------------------------------------------------
|id| |menu_id| |label| |link| |parent| |sort| | min_option1
-------------------------------------------------------------

-------------------------------------------
| User
-------------------------------------------
|id| | username | password | user_group_id
-------------------------------------------

-------------------------------------------
| User Group
-------------------------------------------
|id| option1 | option2 | option2
-------------------------------------------

जब आपको वर्तमान उपयोगकर्ता के लिए एक मेनू प्रदर्शित करने की आवश्यकता होती है। आप डेटाबेस को इस तरह से क्वेरी कर सकते हैं।

SELECT * FROM `MenuItem`
    LEFT JOIN `UserGroup` ON (`MenuItem`.`user_group_id` = `UserGroup`.`id`)
    LEFT JOIN `User` ON (`UserGroup`.`id` = `User`.`user_group_id` AND `User`.`id` = $current_user_id)
        WHERE `MenuItem`.`menu_id` = $menu_id AND `UserGroup`.`option1` >= `MenuItem`.`min_option1`;

यह केवल उन मेनू का चयन करेगा जो वर्तमान उपयोगकर्ता के लिए स्थिति के आधार पर दिखाई देते हैं option1

वैकल्पिक रूप से, यदि आप वर्तमान सत्र में वर्तमान उपयोगकर्ता के समूह विवरण संग्रहीत करते हैं, तो किसी भी सम्मिलित होने की आवश्यकता नहीं है।

SELECT * FROM `MenuItem` WHERE `MenuItem`.`menu_id` = $menu_id AND `MenuItem`.`min_option1` >= $user_group_option1;

जब आप प्रति मेनू आइटम में कई अनुमतियों को संग्रहीत करने के बारे में बात करते हैं। मुझे सावधान रहना चाहिए कि उपयोगकर्ता भूमिकाओं और व्यावसायिक तर्क को भ्रमित न करें।


2
यह डिज़ाइन केवल प्रत्येक MenuItem को एक एकल उपयोगकर्ता समूह से बंधे रहने की अनुमति देगा, जिसका अर्थ है कि सीमित मेनू या डेटा दोहराव। वास्तव में आप आदर्श रूप से एक लिंक टेबल चाहते हैं। इसके अलावा, डीबी टेबल का नामकरण के रूप में आपका नाम मुझे दुखी करता है;)
एड जेम्स

@EdWoodcock ओह बहुत अच्छी बात है। मुझे एक अनुमति स्तर (इंट) के साथ जाना चाहिए और फिर उपयोगकर्ता के समूह स्तर से तुलना करनी चाहिए। मैं उसे बदल दूंगा। ध्यान दें, CakePHP के मेरे उपयोग के कारण बहुवचन नाम आदत। जो अजीब है, क्योंकि यह फ्रेमवर्क प्रश्नों में तालिकाओं के लिए एकवचन उपनामों का उपयोग करता है।
रिएक्टगुलर

@MatthewFoscarini कोई चिंता नहीं, मैं वास्तव में तब तक परेशान नहीं होता जब तक एक कोडबेस संगत है;)
एड जेम्स

1
बहुत बढ़िया जवाब। अगली बार जब मैं ऐसा करूंगा तो मैं इसे ध्यान में रखूंगा। अभी के लिए मुझे लगता है कि user61852 समाधान सबसे अच्छा होगा क्योंकि इसे मौजूदा कोड में कई बदलावों की आवश्यकता नहीं है। धन्यवाद!
अवधि
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.