بسم الله الرحمن الرحيم
السلام عليكم ورحمة الله وبركاته
أعلم أنه قد تم التطرق إلى هذا الأمر عدة مرات وبأساليب مختلفة، ولم أر ضيراً في الإدلاء بدلو صغير جداً في الموضوع، فعسى أن لا يضيق خادم الموقع ولا قلوب كاتبيه الكبيرة عن مثل هذه المشاركة.
الكلام عن الأقسام المتفرعة بغير تناه يكون على ثلاثة مقامات:
الأول بنية الجداول في قاعدة البيانات، وهذه قد استقر القول فيها على الاكتفاء بجدول واحد له بنية مشابهة للتالي:
كود:
CREATE TABLE `cats` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(50) NOT NULL default '',
`parent` int(11) NOT NULL default '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1256 AUTO_INCREMENT=9 ;
وكما نرى فإن الحقول الثلاثة المذكورة هي أهم ما هنالك، ويمكن أن تزيد عليها ما يحتاجه برنامجك كوصف للقسم أو تاريخ إضافة ونحو ذلك.
الثاني قراءة الأقسام من الجداول وتنظيمها في الذاكرة، وهنا كان أكثر الاختلاف في الخوارزميات التي قرأتها في هذا الموقع الجميل، وفيما يلي الطريقة التي أفضلها:
الصف (Class) الرئيس هو Cat ويعرف على النحو التالي:
كود PHP:
class Cat {
var $id;
var $name;
var $parentid;
var $children;
function Cat($i, $n, $p) {
}
function addChild(&$child) {
}
function display() {
}
}
ويستخدم هذا الصف من داخل البرنامج على النحو التالي:
كود PHP:
if (!isset($catid)) $catid=0;
$cats = new Cat(0, 'All categories', -1);
$catQ = array();
$sel_stmnt = "SELECT id, name, parent FROM $cats_table";
$results= mysql_query($sel_stmnt);
while ($record = mysql_fetch_row($results)) {
list($cid, $cname, $cparent) = $record;
if (! $cats->addChild($child=new Cat($cid, $cname, $cparent)))
array_push($catQ, $child);
}
while (count($catQ)>0)
if (! $cats->addChild($child=array_shift($catQ)))
array_push($catQ, $child);
وطبعاً يدور في خلد البعض سؤال ملح وهو: ما ذا يوجد داخل صناديق الدوال المشار إليها أعلاه؟
والجواب كالتالي:
دالة البناء:
كود PHP:
function Cat($i, $n, $p) {
$this->id=$i;
$this->name=$n;
$this->parentid=$p;
$this->children = array();
}
دالة الإضافة:
كود PHP:
function addChild(&$child) {
global $catid, $childrenbag, $parentsbag;
if ($added=($child->parentid==$this->id))
$this->children[$child->id]=$child;
else foreach ($this->children as $cid => $cchild)
if ($added = $this->children[$cid]->addChild($child)) break;
if ($added) {
if ($this->id == $catid) $childrenbag[] = $child->id;
if ($child->id == $catid) $parentsbag[]=$this->id;
}
return $added;
}
أود التنبيه إلى أن المتغيرين $parentsbag و $childrenbag ليسا أساسيين في الطريقة المقترحة لكنهما يوفران أداتين مفيدتين جداً يمكن استخدامهما في مواضع أخرى من البرنامج، كما في طريقة العرض الشجرية مثلاً، وعلى العموم، في حال استخدامها يجب التصريح عنهما قبل تعريف الصف.
المقام الثالث: هو عرض الأقسام، وهو أمر سهل ميسور بعد أن أصبحت الأقسام وتفريعاتها موجودة عندنا مرتبة، فيمكن أن تختار طريقة العرض الشجرية أو طريقة القائمة المنسدلة، أيهما أنسب لك، وذلك باستدعاء:
كود PHP:
echo $cats->display();
على سبيل المثال، هذا التعريف لدالة display يعرض الأقسام على شكل تفريع شجري شهير، ويستخدم ثلاثة صور لتمثيل العقد: واحدة لتمييز القسم المختار، وأخرى لتمييز أبناء هذا القسم وإن دنوا، والثالثة لتمييز آبائه وإن علوا، وصوراً أخرى للمسارات والخطوط.
كود PHP:
function display() {
global $catid, $catchildren, $childrenbag, $parentsbag, $treestring;
if ($A=($this->id==$catid)) $catchildren =true;
if ((in_array($this->id, $parentsbag)) || ($A) || (in_array($this->id, $childrenbag))) {
$treestring .= '<table class="treeview" cellpadding="0" cellspacing="0" ><tr><td><img src="'.(($A)?'c':(($catchildren)?'o':'p')).'folder.gif" alt="" /></td>';
$treestring .= '<td> <span class="linkcat" onClick="loadCat('.($this->id).')">'.($this->name).'</span></td></tr>';
if (count($this->children)>0) {
foreach ($this->children as $key=>$catchild) {
if ((in_array($catchild->id, $parentsbag)) || ($catchild->id==$catid) || (in_array($catchild->id, $childrenbag))) {
$treestring .= '<tr><td'.(($key==max(array_keys($this->children))|| ($catchild->id==$catid) || (in_array($catchild->id,$parentsbag)))?'><img src="imgs/tvln':' class="tvnlastnode"><img src="tvnln').'.gif" alt="" /></td><td>';
$catchild->display();
$treestring .= '</td></tr>';
}
}
}
$treestring .= '</table>';
}
if ($this->id ==0) return $treestring;
}
}
وهذا أوان الإمساك عن فضول الكلام، ففيما تقدم الكفاية، والمرجو من القراء الكرام المسامحة على ما زاد عن الحد.
والله تعالى أعلم.
أخوكم : أحمد