Выборка комментариев с одним вложенным уровнем

Sanu0074
На сайте с 31.08.2012
Offline
110
558

Должно получиться дерево вида:

array(5){
[1]=>array(99){
'field'=>'...',
'field'=>'...',
'field'=>'...',
.............
//если есть у него p_id (родительский коммент), то создается вложенный массив 'childs'
'childs'=array(99){
'field'=>'...',
'field'=>'...',
// и тд..
}
}
}

Но у меня получается такое

array(4) {
[1]=>
array(14) {
["id"]=>
string(1) "5"
["section"]=>
string(5) "match"
["el_id"]=>
string(3) "773"
["p_id"]=>
string(1) "0"
["avt_id"]=>
string(4) "8189"
["adr_id"]=>
NULL
}
[2]=>
array(14) {
["id"]=>
string(1) "4"
["section"]=>
string(5) "match"
["el_id"]=>
string(3) "773"
["p_id"]=>
string(1) "0"
["avt_id"]=>
string(4) "8189"
["adr_id"]=>
NULL
}
[3]=>
array(14) {
["id"]=>
string(1) "3"
["section"]=>
string(5) "match"
["el_id"]=>
string(3) "773"
["p_id"]=>
string(1) "0"
["avt_id"]=>
string(4) "8189"
["adr_id"]=>
NULL
}
[5]=>
array(1) {
["childs"]=>
array(1) {
[0]=>
array(14) {
["id"]=>
string(1) "6"
["section"]=>
string(5) "match"
["el_id"]=>
string(3) "773"
["p_id"]=>
string(1) "5"
["avt_id"]=>
string(4) "8189"
["adr_id"]=>
string(4) "9898"
}
}
}
}

Выборку и сортировку делаю так:

    public function getFromEl($id){
$sql = "SELECT c.*,"
. "u.login AS avt_login,u.opt_avatar AS avt_ava, "
. "u2.login AS adr_login,u2.opt_avatar AS adr_ava "
. "FROM comments c "
. "LEFT JOIN users u ON u.id=c.avt_id "
. "LEFT JOIN users u2 ON u2.id=c.adr_id "
. "WHERE c.el_id=$id ORDER BY c.date_create DESC";
$q = $this->user->dbh->query($sql);
$r = $q->fetchAll(PDO::FETCH_ASSOC);
if(count($r)>0){
return $this->mapTree($r);
}
return NULL;
}

private function mapTree($dataset) {
$tree = array();
foreach ($dataset as $id=>&$node) {
if (!$node['p_id']) {
$tree[$id] = &$node;
} else {
$dataset[$node['p_id']]['childs'][$id] = &$node;
}
}
return $tree;
}

Так же еще получаю "Undefined index: p_id" в строке: $dataset[$node['p_id']]['childs'][$id] = &$node;

Помогите разобраться!

p.s. скрин структуры таблицы

[umka]
На сайте с 25.05.2008
Offline
456
#1

Одним запросом вы рекурсивную выборку не сделаете.

Делайте несколькими или храните в базе дерево в другом виде.

Лог в помощь!
Sanu0074
На сайте с 31.08.2012
Offline
110
#2

[umka], суть в том чтобы полученный массив в цикле перебрать, mapTree() и делает то самое дерево.

не могу понять причом выборка к дереву

edogs software
На сайте с 15.12.2005
Offline
775
#3

Уберите &$node - не к делу, да и используете Вы это не вполне верно, используйте просто $node

В чем именно у Вас претензия? В Вашем же примере "как получается" есть childs, в последнем элементе.

Нотис с p_id у Вас видимо возникает при null-евых значениях p_id, судя по структуре таблицы они разрешены.

Разработка крупных и средних проектов. Можно с криптой. Разумные цены. Хорошее качество. Адекватный подход. Продаем lenovo legion в спб, дешевле магазинов, новые, запечатанные. Есть разные. skype: edogssoft
Sanu0074
На сайте с 31.08.2012
Offline
110
#4

edogs, p_id - везде нули, NULL не может там быть это 100%

Почему &$node - не к делу?

И вот допустим три коммента, два дочерних

array(2) {

[2]=>
array(14) {
["id"]=>
string(2) "19"
["section"]=>
string(5) "match"
["el_id"]=>
string(3) "773"
["p_id"]=>
string(1) "0"
["avt_id"]=>
string(4) "8189"
["adr_id"]=>
NULL
["date_create"]=>
string(19) "2015-03-09 12:47:43"
["like_p"]=>
string(1) "0"
["like_m"]=>
string(1) "0"
["text"]=>
string(16) "ыаывавыа"
["avt_login"]=>
string(4) "sanu"
["avt_ava"]=>
string(11) "i6ZCbsol1z4"
["adr_login"]=>
NULL
["adr_ava"]=>
NULL
}
[19]=>
array(1) {
["childs"]=>
array(2) {
[0]=>
array(14) {
["id"]=>
string(2) "21"
["section"]=>
string(5) "match"
["el_id"]=>
string(3) "773"
["p_id"]=>
string(2) "19"
["avt_id"]=>
string(4) "8189"
["adr_id"]=>
string(4) "8189"
["date_create"]=>
string(19) "2015-03-09 12:47:50"
["like_p"]=>
string(1) "0"
["like_m"]=>
string(1) "0"
["text"]=>
string(8) "12123123"
["avt_login"]=>
string(4) "sanu"
["avt_ava"]=>
string(11) "i6ZCbsol1z4"
["adr_login"]=>
string(4) "sanu"
["adr_ava"]=>
string(11) "i6ZCbsol1z4"
}
[1]=>
array(14) {
["id"]=>
string(2) "20"
["section"]=>
string(5) "match"
["el_id"]=>
string(3) "773"
["p_id"]=>
string(2) "19"
["avt_id"]=>
string(4) "8189"
["adr_id"]=>
string(4) "8189"
["date_create"]=>
string(19) "2015-03-09 12:47:48"
["like_p"]=>
string(1) "0"
["like_m"]=>
string(1) "0"
["text"]=>
string(8) "12123123"
["avt_login"]=>
string(4) "sanu"
["avt_ava"]=>
string(11) "i6ZCbsol1z4"
["adr_login"]=>
string(4) "sanu"
["adr_ava"]=>
string(11) "i6ZCbsol1z4"
}
}
}
}

Почему вылетает Undefined index: p_id к этой строке: if (!$node['p_id']) {

edogs software
На сайте с 15.12.2005
Offline
775
#5
Sanu0074:
edogs, p_id - везде нули, NULL не может там быть это 100%
Почему &$node - не к делу?

Судя по структуре таблицы - NULL там может быть, может случайно затесался.

&$node не к делу, потому что для него в данной ситуации нет никаких причин и Вы не совсем верно используете это, замените на $node.

Sanu0074:

Почему вылетает Undefined index: p_id к этой строке: if (!$node['p_id']) {

Непонятно на каком этапе оно это пишет. Сделайте var_dump перед этой строчкой и посмотрите состав массива $node - будет понятнее.

Sanu0074
На сайте с 31.08.2012
Offline
110
#6

edogs, ошибку нашел, она заключается в том что комментов то 3, а цикл почемуто 4 раза выполняется... почему такое может быть?

может посоветуете, вообще как-то иначе переписать функцию?

сделал так:

    private function mapTree($dataset) {

$tree = array();
foreach ($dataset as $id=>&$node) {
if(!isset($node['p_id'])){
$node['p_id']=0;
}
if (!$node['p_id']) {
$tree[$id] = &$node;
} else {
$dataset[$node['p_id']]['childs'][$id] = &$node;
}
}
return $tree;
}

теперь в конец массива добавляет лишний ["p_id"]=>0

array(2) {

[2]=>
array(14) {
["id"]=>
string(2) "19"
["section"]=>
string(5) "match"
["el_id"]=>
string(3) "773"
["p_id"]=>
string(1) "0"
["avt_id"]=>
string(4) "8189"
["adr_id"]=>
NULL
["date_create"]=>
string(19) "2015-03-09 12:47:43"
["like_p"]=>
string(1) "0"
["like_m"]=>
string(1) "0"
["text"]=>
string(16) "ыаывавыа"
["avt_login"]=>
string(4) "sanu"
["avt_ava"]=>
string(11) "i6ZCbsol1z4"
["adr_login"]=>
NULL
["adr_ava"]=>
NULL
}
[19]=>
array(2) {
["childs"]=>
array(2) {
[0]=>
array(14) {
["id"]=>
string(2) "21"
["section"]=>
string(5) "match"
["el_id"]=>
string(3) "773"
["p_id"]=>
string(2) "19"
["avt_id"]=>
string(4) "8189"
["adr_id"]=>
string(4) "8189"
["date_create"]=>
string(19) "2015-03-09 12:47:50"
["like_p"]=>
string(1) "0"
["like_m"]=>
string(1) "0"
["text"]=>
string(8) "12123123"
["avt_login"]=>
string(4) "sanu"
["avt_ava"]=>
string(11) "i6ZCbsol1z4"
["adr_login"]=>
string(4) "sanu"
["adr_ava"]=>
string(11) "i6ZCbsol1z4"
}
[1]=>
array(14) {
["id"]=>
string(2) "20"
["section"]=>
string(5) "match"
["el_id"]=>
string(3) "773"
["p_id"]=>
string(2) "19"
["avt_id"]=>
string(4) "8189"
["adr_id"]=>
string(4) "8189"
["date_create"]=>
string(19) "2015-03-09 12:47:48"
["like_p"]=>
string(1) "0"
["like_m"]=>
string(1) "0"
["text"]=>
string(8) "12123123"
["avt_login"]=>
string(4) "sanu"
["avt_ava"]=>
string(11) "i6ZCbsol1z4"
["adr_login"]=>
string(4) "sanu"
["adr_ava"]=>
string(11) "i6ZCbsol1z4"
}
}
["p_id"]=>
int(0)
}
}
LEOnidUKG
На сайте с 25.11.2006
Offline
1726
#7

Я лично использую вот такую функцию:

function build_hierarchy($arr, $id_key = 'id', $pid_key = 'parent_id') {

$structure = array();

while($elem = array_shift($arr)) {

if(isset($structure[ $elem[$id_key] ])) {

$elem['children'] = $structure[ $elem[$id_key] ];

unset($structure[ $elem[$id_key] ]);

} else

$elem['children'] = array();

if(isset($references[ $elem[$pid_key] ])) {

$references[ $elem[$pid_key] ]['children'][ $elem[$id_key] ] = $elem;

$references[ $elem[$id_key] ] =& $references[ $elem[$pid_key] ]['children'][ $elem[$id_key] ];

} else {

$structure[ $elem[$pid_key] ][ $elem[$id_key] ] = $elem;

$references[ $elem[$id_key] ] =& $structure[ $elem[$pid_key] ][ $elem[$id_key] ];

}

asort( $references );

}

return array($structure);

}

Выгружаю данные в переменную из SELECT например в $bigmass

Потом делаю:

$bigmass=build_hierarchy($bigmass,'id','rootid');

получаю дерево.

А потом уже делайте всё что хотите.

✅ Мой Телеграм канал по SEO, оптимизации сайтов и серверов: https://t.me/leonidukgLIVE ✅ Качественное и рабочее размещение SEO статей СНГ и Бурж: https://getmanylinks.ru/
Sanu0074
На сайте с 31.08.2012
Offline
110
#8

LEOnidUKG, ваша функция работает, спасибо

---------- Добавлено 09.03.2015 в 19:50 ----------

LEOnidUKG, я сделал так

    private function mapTree($arr, $id_key = 'id', $pid_key = 'p_id') {

$structure = array();
while ($elem = array_shift($arr)) {
if (isset($structure[$elem[$id_key]])) {
$elem['childs'] = $structure[$elem[$id_key]];
unset($structure[$elem[$id_key]]);
} else
$elem['childs'] = array();
if (isset($references[$elem[$pid_key]])) {
$references[$elem[$pid_key]]['childs'][$elem[$id_key]] = $elem;
$references[$elem[$id_key]] = & $references[$elem[$pid_key]]['childs'][$elem[$id_key]];
} else {
$structure[$elem[$pid_key]][$elem[$id_key]] = $elem;
$references[$elem[$id_key]] = & $structure[$elem[$pid_key]][$elem[$id_key]];
}
asort($references);
}
return $structure;
}

и получаю такой массив на выходе:

array(1) {

[0]=>
array(2) {
[21]=>
array(15) {
["id"]=>
string(2) "21"
["section"]=>
string(5) "match"
["el_id"]=>
string(3) "773"
["p_id"]=>
string(1) "0"
["avt_id"]=>
string(4) "8189"
["adr_id"]=>
string(4) "8189"
["date_create"]=>
string(19) "2015-03-09 12:47:50"
["like_p"]=>
string(1) "0"
["like_m"]=>
string(1) "0"
["text"]=>
string(8) "12123123"
["avt_login"]=>
string(4) "sanu"
["avt_ava"]=>
string(11) "i6ZCbsol1z4"
["adr_login"]=>
string(4) "sanu"
["adr_ava"]=>
string(11) "i6ZCbsol1z4"
["childs"]=>
array(0) {
}
}
[19]=>
array(15) {
["id"]=>
string(2) "19"
["section"]=>
string(5) "match"
["el_id"]=>
string(3) "773"
["p_id"]=>
string(1) "0"
["avt_id"]=>
string(4) "8189"
["adr_id"]=>
NULL
["date_create"]=>
string(19) "2015-03-09 12:47:43"
["like_p"]=>
string(1) "0"
["like_m"]=>
string(1) "0"
["text"]=>
string(16) "ыаывавыа"
["avt_login"]=>
string(4) "sanu"
["avt_ava"]=>
string(11) "i6ZCbsol1z4"
["adr_login"]=>
NULL
["adr_ava"]=>
NULL
["childs"]=>
array(1) {
[20]=>
array(15) {
["id"]=>
string(2) "20"
["section"]=>
string(5) "match"
["el_id"]=>
string(3) "773"
["p_id"]=>
string(2) "19"
["avt_id"]=>
string(4) "8189"
["adr_id"]=>
string(4) "8189"
["date_create"]=>
string(19) "2015-03-09 12:47:48"
["like_p"]=>
string(1) "0"
["like_m"]=>
string(1) "0"
["text"]=>
string(8) "12123123"
["avt_login"]=>
string(4) "sanu"
["avt_ava"]=>
string(11) "i6ZCbsol1z4"
["adr_login"]=>
string(4) "sanu"
["adr_ava"]=>
string(11) "i6ZCbsol1z4"
["childs"]=>
array(0) {
}
}
}
}
}
}

обходить его приходится двойным foreach несчитая childs, как сделать так чтобы на выходе получать примерно такой массив:

  array(2) {

array(15) {
["id"]=>
string(2) "21"
["section"]=>
string(5) "match"
["el_id"]=>
string(3) "773"
["p_id"]=>
string(1) "0"
["avt_id"]=>
string(4) "8189"
["adr_id"]=>
string(4) "8189"
["date_create"]=>
string(19) "2015-03-09 12:47:50"
["like_p"]=>
string(1) "0"
["like_m"]=>
string(1) "0"
["text"]=>
string(8) "12123123"
["avt_login"]=>
string(4) "sanu"
["avt_ava"]=>
string(11) "i6ZCbsol1z4"
["adr_login"]=>
string(4) "sanu"
["adr_ava"]=>
string(11) "i6ZCbsol1z4"
["childs"]=>
array(0) {
}
}
array(15) {
["id"]=>
string(2) "19"
["section"]=>
string(5) "match"
["el_id"]=>
string(3) "773"
["p_id"]=>
string(1) "0"
["avt_id"]=>
string(4) "8189"
["adr_id"]=>
NULL
["date_create"]=>
string(19) "2015-03-09 12:47:43"
["like_p"]=>
string(1) "0"
["like_m"]=>
string(1) "0"
["text"]=>
string(16) "ыаывавыа"
["avt_login"]=>
string(4) "sanu"
["avt_ava"]=>
string(11) "i6ZCbsol1z4"
["adr_login"]=>
NULL
["adr_ava"]=>
NULL
["childs"]=>
array(1) {
array(15) {
["id"]=>
string(2) "20"
["section"]=>
string(5) "match"
["el_id"]=>
string(3) "773"
["p_id"]=>
string(2) "19"
["avt_id"]=>
string(4) "8189"
["adr_id"]=>
string(4) "8189"
["date_create"]=>
string(19) "2015-03-09 12:47:48"
["like_p"]=>
string(1) "0"
["like_m"]=>
string(1) "0"
["text"]=>
string(8) "12123123"
["avt_login"]=>
string(4) "sanu"
["avt_ava"]=>
string(11) "i6ZCbsol1z4"
["adr_login"]=>
string(4) "sanu"
["adr_ava"]=>
string(11) "i6ZCbsol1z4"
["childs"]=>
array(0) {
}
}
}
}
}

ну т.е. убрать лишние индексы сразу чтоб потом не обходить их циклом...

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий