Bug tracker. Преобразуем таблицу в html список (часть 4).

Владимир | | CodeIgniter, HTML, PHP, Web разработка.

Начало на предыдущей странице

Теперь рассмотрим метод _nestedComments.

function _nestedComments($comments, $parentId, $depth) {
	$commentsRes = array();
	$i = 0;
	foreach ($comments as $val) {
		if ($val['parent_id'] == $parentId) {
			$commentsRes[$i] = $val;
			$commentsRes[$i]['depth'] = $depth;
			$commentsRes[$i]['comments'] = $this->_nestedComments($comments, $val['id'], $depth + 1);
			$i++;
		}
	}
	return $commentsRes;
}

Он значительно меньше предыдущего, но принцип его работы сложнее. Прежде всего, обратите внимание на входные параметры:
comments – массив с комментариями отдельного бага;
parentIdid родительского комментария;
depth – глубина рекурсии.

Думаю, вы уже догадались, что метод рекурсивный, т.е. вызывает сам себя. Причем первый параметр остаётся неизменным, а второй и третий изменяются.

При первом вызове parentId = NULL (соответствует комментарию верхнего уровня). Мы в цикле перебираем все комментарии и ищем те, у которых элемент parent_id равен текущему значению parentId.

Если такой комментарий найден, мы сохраняем его в массив с результатами и пробуем найти его потомков.

Для этого вызываем этот же метод (_nestedComments), но уже во втором параметре указываем id текущего комментария.

В результате мы получим дерево комментариев. Глубина рекурсии будет совпадать с уровнем вложенности комментариев.

Переходим к формированию HTML списка.

Рассмотрим метод getHTMLList.

function getHTMLList($tree, $config = null) {
	if (!empty($config)) {
		foreach ($config as $key => $value) {
			$this->config[$key] = $value;
		}
	}
	$this->CI->load->library('parser');
	$html = $this->config['listOpen']."\n";
	foreach ($tree as $node) {
		$html .= $this->config['bugOpen'].$this->CI->parser->parse('bug_tpl', $node, TRUE)."\n";
		if (!empty($node['comments'])) {
			$html .= $this->_convert2HTMLList($node['comments'], 0)."\n";
		}
		$html .= $this->config['bugClose'];
	}
	return $html.$this->config['listClose'];
}

Его первый параметр – массив с багами и комментариями, который мы получили до этого.

Второй – массив с настройками отображения списка. Он позволяет легко изменять HTML разметку, которую формирует этот метод.
По-умолчанию, поля этого массива имеют следующие значения

private $config = array(
	'listOpen' => '<ul>'
	,'listClose' => '</ul>'
	,'bugOpen' => '<li>'
	,'bugClose' => '</li>'
	,'commentOpen' => '<li>'
	,'commentClose' => '</li>'
);

Т.е. будет сформирован ненумерованный список. Изменив значения listOpen и listClose на <ol> и </ol> мы получим нумерованный список.

Кроме того, в результирующий список данные о багах должны быть вставлены с соответствующей разметкой. Поэтому, чтобы не превращать код метода в мешанину php и html, мы используем встроенный в CodeIgniter шаблонизатор.

Сами шаблоны мы рассмотрим чуть ниже, а сейчас достаточно знать, что с помощью
$this->CI->parser->parse(...)
можно получить соответствующую html разметку.

Теперь взгляните на цикл (строки 9-15). В нём мы перебираем все элементы массива и для каждого вызываем метод _convert2HTMLList.

function _convert2HTMLList($bugComments, $depth) {
	$list = '';
	$list .= $this->config['listOpen']."\n";
	foreach ($bugComments as $comment) {
		$openTag = str_replace('{depth}', $depth, $this->config['commentOpen']);
		$list .= $openTag.$this->CI->parser->parse('comment_tpl', $comment, TRUE)."\n";
		if (!empty($comment['comments'])) {
			$list .= $this->_convert2HTMLList($comment['comments'], $depth + 1);
		}
		$list .= $this->config['commentClose']."\n";
	}
	$list .= $this->config['listClose'];
	return $list;
}

Думаю, вы заметили, что этот метод тоже рекурсивный. Мы перебираем все элементы массива комментариев и с помощью шаблонизатора формируем HTML разметку.

Если текущий элемент массива имеет вложенный массив с именем comments (т.е. есть дочерние комментарии), то мы вызываем этот же метод, но в качестве первого параметра передаем ему вложенный массив.

Второй параметр метода содержит значение глубины рекурсии.

Посмотрите на HTML разметку в начале этой статьи. Каждый вызов метода _convert2HTMLList формирует свой тег <ul> для комментариев. Так для первого бага этот метод будет вызван 2 раза. Первый раз из метода getHTMLList при создании списка с комментариями нулевого уровня (комментарий 1, комментрарий 2), а второй раз – рекурсивно при создании списка с ответами на комментарий 2.

В результате мы получим необходимую разметку со вложенными HTML списками.

Теперь посмотрите на шаблоны для багов и комментариев. Они должны быть размещены в папке application\views.

bug_tpl.php

<div class="bug" id="bug-{id}">
	<p class="bugTitle">Название: <?php echo anchor('bugtracker/bug/'.'{id}', '{title}'); ?></p>
	<p class="bugInfo">
		<span class="bugAuthor">Автор: {uname}.</span>
		<span class="bugCategory">Категория: <?php echo anchor('bugtracker/category/'.'{link}', '{category}'); ?>.</span>
		<span class="bugDate">Добавлен: {bug_date}.</span>
	</p>
	<p class="bugDescription">Описание: {description}</p>
</div>

comment_tpl.php

<div class="comment depth-{depth}" id="comment-{id}">
	<p class="commentInfo">
		<span class="commentAuthor">Автор: {uname}.</span>
		<span class="commentDate">Дата: {comment_date}.</span>
		<span class="commentDescription">Ответ: {description}</span>
	</p>
</div>

Обратите внимание на параметры в фигурных скобках. Их имена совпадают с ключами полей в массиве с деревом багов и комментариев. При формировании страницы шаблонизатор CodeIgniter заменит их соответствующими значениями.

На этом я закончу эту часть. В следующий раз мы рассмотрим создание записи о новом баге.

До встречи!

P.S. Как всегда я буду рад услышать любые замечания и комментарии (кроме спамерских 😉 ).

Страница: 1 2