احاول بناء شجرة لتسجيل فئات (categories) لمكتبة كتب
و تركيبة قواعد البيانات تكون
ID - Name - ParentID
و بهذه الطريقة يكون لدينا عمق غير محدود
و الحصول على المسار عن طريق حلقة
هل هذه الطريقة صحيحة ؟ و هل يوجد طريقة افضل ؟
1- ستتمكن من عمل عدد لا نهائى من المستويات و ال nodes
2- Nested set model متوفر على شكل Class بالفعل و يمكنك البدأ بإستخدامه فوراً
3- التعامل بالنظام الحالى يجعل المستويات عددها محدود , حيث ستضطر لعمل عدد كبير جداً من الحلقات التكراريه لكل node لتحصل على ال children of parents
4- التعامل بال nested set model يوفر ال resources المستخدمه فى معالجة البيانات حيث معرفة ال children تتم عبر قيم ال left و right و ليس عبر الحلقات التكرارية
المشكلة ليست فى قاعدة البيانات
المشكلة فى عمل البيانات المخرجه منها على شكل tree
تخيل لديك tree فيها 100 node , هل ستقوم بعمل foreach 100 مره ؟
و بذكرنا الرقم 100 فنحن لدينا عدد نهائى و ليس غير نهائى
حاول بنفسك :)
هذا هو دور العمود الذى إقترحته Level والذى يحدد العمق فيمكن تقوم بحلقة تكرارية واحدة داخل method مع إرسال العمق فتعود لك بما تريد, خاصة إن لغة PHP تسمح لك بذلك بمرونتها العالية!
ممكن تضيف level لتسجيل مستوى العمق
ممكن تضيف Order لإعادة ترتيب أبناء كل عقدة على أساسه
ممكن تضيف publish للظهور العناصر أو إخفاءها
.....
ممكن تضيف level لتسجيل مستوى العمق
هل احتاج هذا حقا ؟ يمكنني كتابة كود استرجاع عن طريق ParentID و معرفة العمق عن طريق هذا
ممكن تضيف publish للظهور العناصر أو إخفاءها
هذه وضعتها في جدول الكتب , و لم اضعها هنا بسبب عني التقسيم واضح و محدد
ماذا لو أحببت عدم عرض مجموعة بما تحتوية من كتب؟ أو حتى عقدة بما تحتوية من مجموعات؟!
إن لم تحتاج ذلك فى تطبيقك فلا يهم يمكن أن تتجاهل ذلك
أما عن level فراجع https://arabia.io/go/7368/2...
بالإمكان إضافة حقل للجدول IsVisible أو IsActive من النوع منطقي bit ليعبر عن حالة العقدة إن كانت قابلة للظهور أو مخفية
كما بإمكانك أن تضع حقل عام من النوع نص أو رقم بحيث يحتوي على قيمة ثنائية من واحدات وأصفار تمثل أعلام Flags
بحيث أنت تمثل الخانة الأولى لتمثيل الظهور أو الإخفاء
الخانة الثانية لتمثيل أن العقدة قابلة لإضافة أولاد لها أم لا
الخانة الثالثة لتمثيل هل العقدة قابلة للنقل
وهكذا كم خلال حقل واحد تستطيع أن تمثل كثير من الحالات
بدلا من تمثيل كل حالة في حقل
توفر عليك أنه كلما احتجت لحالة جديدة من إضافة حقل جديد
فالحقل Flags سيوفر عليك الكثير
مع أني أعمل على مشروع يعتمد في معظم أجزاءه على البنية الشجرية
فإني قد وجدت أن حقلي ID و ParentID قد أعطوني المرونة الكاملة للتحكم
أولا أقوم في قاعدة المعطيات بإنشاء علاقة واحد إلى متعدد تربط ParentID مع ID لنفس الجدول مما يجعل كل سطر مرتبط بأولاده من خلال هذه العلاقة
وبنفس الوقت يمكن الوصول إلى السطر الأب من خلال نفس العلاقة
هذه من جهة
أما من جهة العرض فلكوني أستخدم رخصة DevExpress للـ WPF
فإن عناصر العرض مثل GridControl و TreeListView
https://www.devexpress.com/...
قد زودوها بخاصيتين وهي أن تحدد لهم مصدر البيانات و الحقل الـذي يمثل ID و الحقل الذي يمثل ParentID
وهو يقوم بتشكيل الشجرة تلقائيا ولا يحتاج أي تدخل من قبل المبرمج لعمل حلقات
وأما على الصعيد البرمجي فلكوني أستخدم Linq to SQL
فإنه يقوم تلقائيا بإدراج خاصية ضمن صنف الجدول وتكون اسمها نفس الاسم مع إضافة s وتحوي دائما الأولاد
وكذلك خاصية تحمل نفس الاسم مع إضافة 1 لتمييزها عن اسم الصنف نفسه ويكون حاويا للسطر الأب
وبهذا أصبحت أتحكم بشكل كامل ومرن بالشجرة
شكرا للرد المفصل , انا اقدر هذا حقا
و لكن عن ماذا Nested Set Model ؟ هل يجب ان اغيرها ؟
ام ان ParentID و ID كافية للغرض الذي اريده
و ايضا هل هذه يمكنني الحصول على عمق غير نهائي ؟
لذلك فصلت في الإجابة وعرضت كل الجوانب لتعلم أني استغنيت عن البنى الأخرى الأكثر تعقيدا
ولاحظ هنا أنه لا يتطلب مني أي جهد سوى أن أضيف أسطر جديدة وتعيين قيمة الـ ParentID هي الكفيلة بإظهارها في موضعها الطبيعي
قبل أن أفطن لمسألة إنشاء العلاقة كان الأمر مربك ويتطلب مني تدخل وفحص وحلقات وتحقق
ولكن وجود العلاقة قام بكل شيء
فقيود هذه العلاقة تمنعك من حذف سطر (والتي تمثل عقدة شجرة) طالما أن له أولاد لأن العلاقة تكشف أن هناك أسطر مرتبطة به
إلا إذا حددت له في قيد الحذف أن يقوم بحذف كل الأسطر المرتبطة فحينها حذفك لأي عقدة سيحذف جميع الأفرع والعقد التابعة لها
أيضا عند إنشاء سطر جديد فإنه سيعين عليك تحديد الأب أو أنك تضع شرط الحقل ParentID أن يقبل عدم التعيين بالسماح بـ Null
حينها سيتوجب عليك أن تتأكد من تعيين قيمة وإلا اعتبرها جذر لشجرة جديدة
أي الخلاصة أصبح موضعة العقدة في أي مكان و الوصول إليها سهلا من خلال الحقلين ID و ParentID فقط
و تغيير مكان أي عقدة أو عقد لا يحتاج سوى تغيير قيمة الحقل ParentID
قبل أن أفطن لمسألة إنشاء العلاقة كان الأمر مربك ويتطلب مني تدخل وفحص وحلقات وتحقق
هذا صحيح , شكرا للأشارة الى هذه النقطة , الان وضحت المسألة لي
و لكن بالنسبة للعمق الغير نهائي ؟
لديك عمق يصل إلى أعلى قيمة يستوعبه نوع الحقل ParentID أو لعدد الأسطر التي تستوعبه القاعدة أيهما أقل
فلو كان من النوع int
فلديك عمق يصل إلى مليارين وزيادة طالما تسمح القاعدة بإضافة هذا العدد من الأسطر
أما إن كان العدد محدودا فهو يكون أقصى عمق
لأنه بإمكانك أن تضيف سطر وكل سطر جديد تنسبه للذي قبله
و هكذا تتوسع الشجرة عمقا مع كل سطر جديد يضاف
التعليقات