бесконечный цикл php

Эта функция дает мне бесконечный цикл

function getCats($parent,$level){ // retrieve all children of $parent $result = ""; $query = "SELECT title,parent_id from t_cats where parent_id = '$parent'"; if($rs = C_DB::fetchRecordset($query)){ while($row = C_DB::fetchRow($rs)){ $result .= str_repeat($parent,$level).$row['title']."\n"; getCats($row['parent_id'],$level+1); } } return $result; } 

вот моя таблица db

 CREATE TABLE `db`.`t_cats` ( `ID` int(10) unsigned NOT NULL auto_increment, `datasource_id` int(10) unsigned default '0', `version` char(10) character set latin1 default 'edit', `status` char(10) character set latin1 default 'new', `modified_date` datetime default NULL, `modified_by` int(10) unsigned default '0', `title` char(255) character set latin1 default NULL, `parent_id` int(11) default NULL, PRIMARY KEY (`ID`), KEY `idx_datasource_id` (`datasource_id`) ) ENGINE=MyISAM AUTO_INCREMENT=50 DEFAULT CHARSET=utf8; 

Я просто хочу, чтобы мой список категорий был рекурсивным.

Но что я делаю неправильно?


РЕДАКТИРОВАТЬ:

 function getCats($parent,$level){ // retrieve all children of $parent $result =""; $query = "SELECT title,parent_id from t_cats where parent_id = '$parent'"; if($rs = C_DB::fetchRecordset($query)){ while($row = C_DB::fetchRow($rs)){ $result.= str_repeat($parent,$level).$row['title']."\n"; getCats($row['id'],$level + 1 ); } } return $result; } 

Эта строка выглядит неправильно:

 getCats($row['parent_id'],$level+1); 

Вы должны называть его текущим идентификатором ребенка – в тот момент, когда вы вызываете его с тем же идентификатором снова и снова. Что-то вроде этого (вам нужно выбрать идентификатор из таблицы):

 getCats($row['id'], $level + 1); 

Изменить: вам нужно обновить свой запрос, чтобы выбрать id :

 $query = "SELECT id, title, parent_id from t_cats where parent_id = '$parent' AND id != parent_id"; 

Я также добавил немного, чтобы остановить его попадание в цикл, если элемент является его собственным родителем.

Я нашел эту статью SitePoint « Хранение иерархических данных в базе данных » очень полезной. Это все примеры PHP, и это улучшит производительность того, что вы пытаетесь сделать резко .

Может быть, один из элементов в db сам по себе является родителем?

Я не знаю C_DB, но я бы сказал, что $ rs, возвращаемый fetchrecordset, является ссылкой, что означает, что каждый вызов getCats использует те же $ rs. Именно то, что он будет делать, непредсказуемо, в зависимости от того, как реализована функция fetchRow.

Если вы хотите это сделать (и рекурсивное закрытие – это боль в SQL, я знаю), вы должны открыть новое соединение внутри getCats. и использовать отдельный доступ для каждого доступа.

правильный ответ, предоставленный greg …

2 примечания стороны:

  1. в случае бесконечных циклов, глубина рекурсии трека (здесь вы можете удобно использовать $level ) или общий счет вызова (если вы ленивы, так как это oneliner, обращающийся к глобальному счетчику) и прекратить рекурсию с исключением, когда она достигает максимальное значение (в общем, 10 уже достаточно, чтобы увидеть проблему, но, конечно, это может меняться) … а затем получить отладочный вывод … например, $query или что-то вроде "calling getCats($parent,$level)" … показал бы вам проблему в мгновение ока в этом случае … 🙂

  2. вы должны свести к минимуму количество запросов … обход дерева таким образом довольно неэффективен … особенно, если база данных находится на другом компьютере …

Greetz

back2dos

Erm не должно быть:

 $query = "SELECT title,parent_id from t_cats where id = '$parent'"; 

И не:

 $query = "SELECT title,parent_id from t_cats where parent_id = '$parent'";