PHP: Категории бесконечного уровня вложенности.

Author Роман Чернышов    Category PHP     Tags , Комментариев 0 Дата 9 Авг

category PHP: Категории бесконечного уровня вложенности.Приветствую вас мои дорогие читатели, сегодня я хочу поделиться с вами моими небольшими наработками по созданию скрипта(класса) для работы с категориями и подкатегориями бесконечного уровня вложенности. Необходимость применения сие функционала может потребоваться где угодно, например в организации категорий новостей, статей, товаров в интернет магазине или же вообще пользовательских комментариев с ответами, также вложенными друг в друга.

И так для начала опишу с чем мы будем работать и что нам понадобится.
Система: PHP 5 и выше, mySQL 4 и выше
Вспомогательные классы: dbsql.class.php (класс для работы с базой данных)
Класс вложенных категорий: classTreeCategory.php (непосредственно основной класс, ниже приведен его листинг и пояснения.

Создаем таблицу в БД, следующей структуры:

DROP TABLE IF EXISTS `category`;
CREATE TABLE `category` (
   `id` int(11) NOT NULL auto_increment,
   `podcat` int(11) NOT NULL,
   `name` varchar(255) NOT NULL,
    PRIMARY KEY  (`id`),
    KEY `id` (`id`)
   ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

В данной таблице присутствует поле ID — порядковый номер категории, podcat — имеет значение ноль у категорий первого порядка или ID родительской категории, name — название категории.

Пример работы класса, вывод категорий списком с подкатегориями:

include('dbsql.class.php');
include('classTreeCategory.php');
$DB=new DB_Engine('mysql', $settings['dbHost'], $settings['dbUser'], $settings['dbPass'], $settings['dbName']); // подключаемся к БД, с указанием данных доступа
 
$category = new TreeCategory ($DB); // передаем в класс категорий, объект работы с БД
$category->table='category'; // название таблицы в БД с категорийми
$array=$category->getCategory(); // получаем все категории из БД в виде многоуровневого массива, отсортированные и вложенные уже в нужном нам порядке
$category->outCategory($array, 'option'); // подготовка вывода категорий (формируем HTML), передаем массив с категориями
echo $category->html; // вывод категорий в виде HTML <option value="id">name</option>

Как видно из примера выше, все предельно просто, создаем новый объект $category, устанавливаем с какой таблицей БД работаем: ‘category’, далее получаем из таблицы список всех категорий уже оформленный в виде массива и разложенных в иерархичном порядке, с учетом всех подкатегорий. затем передаем массив в метод outCategory() который формирует для нас готовый HTML код, который остается только вывести в браузер.

Метод outCategory(), как мы видим принимает два параметра @array и @string в первом параметре массив со всеми категориями, а во втором строка содержащая значение option или table, это значени указывает какой тип HTML кода требуется сформировать.
Значение option — формирует следующий HTML код:

<option value="1">-категория1</option>
<option value="2">--подкатегория 1</option>
<option value="3">---подподкатегория 1</option>
<option value="4">-категория 2</option>

Для вставки данного HTML кода в поле select какой либо формы.

Значение table— формирует следующий HTML код:

<tr><td>-категория1</td><td>кнопки ред и удл</td></tr>
<tr><td>--подкатегория1</td><td>кнопки ред и удл</td></tr>
<tr><td>---подподкатегория1</td><td>кнопки ред и удл</td></tr>
<tr><td>-категория2</td><td>кнопки ред и удл</td></tr>

Этот HTML код удобен для вставки в таблицу которая отображает все наши категории подкатегории.

Класс имеет также следующие методы:
deleteItem($id); — удаляет одну категорию, не смотря на вложенные
delCategory($array, $id); — удаляет категорию со всеми вложенными подкатегориями, $array — массив со всеми категориями подготовленный методом $category->getCategory(), $id- номер удаляемой категории
addItem(); — данный метод следует вызывать если вы хотите добавить категорию, при этом этот метод считывает значения из данных переданных методом POST, т.е. из массива $_POST.
$name=$this->PHP_slashes(strip_tags($_POST[‘name’])); // имя категории
$podcat=intval($_POST[‘podcat’]); // ID родительской категории, если указан 0 категория будет в корне.
updateItem(); — аналогично предыдущему методу, кроме того что данный метод обновляет категорию, её название и уровень вложенности.

Листинг всего класса по работе с категориями и подкатегориями бесконечного уровня вложенности.

table='category'; // запрос на выборку списка категорий, название таблицы
 *  $category->outCategory($category->getCategory()); // подготовка вывода категорий(запрос массива категорий)
 *  echo $category->html; // вывод категорий в HTML 
 *
 */

/**
 *  Дамп таблицы с которой ведется работа
 *
 *  DROP TABLE IF EXISTS `category`;
 *  CREATE TABLE `category` (
 *    `id` int(11) NOT NULL auto_increment,
 *    `podcat` int(11) NOT NULL,
 *    `name` varchar(255) NOT NULL,
 *    PRIMARY KEY  (`id`),
 *    KEY `id` (`id`)
 *  ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
 *  
 */

class TreeCategory {
/**
*   Строка запроса в БД
*/var $table;

/**
*   Интерфейс работы с БД
*/var $DB;

/**
*   Массив категорий с вложенными подкатегориями
*/var $arrayCat;

/**
*   Авто-подстчет кол-ва прочерков перед названием категории при выводе
*/var $countPodcat;

/**
*   HTML код для вывода категорий с подкатегориями
*/var $html;


/**
*   Получаем интерфейс для работы с БД и кладем его в локальные переменную
*/function __construct($DB) {
$this->DB=$DB;
$this->component=$_GET['component'];
}


/**
*   Получает список категорий, сортирует и помещает в массив с вложенными массивами и т.д.
*   @return array category
*/function getCategory () {
   $all = $this->DB->getAll("SELECT * FROM `{$this->table}` ORDER BY `id` ASC");
          $path = array();
  if(count($all)>0) {
   foreach($all as $item):
if($item['podcat']==0)$sort[$item['id']]=$item;
if($item['podcat']>0)
{
if(isset($path[$item['podcat']]))
{
$str='$sort';
foreach($path[$item['podcat']] as $pitem):
$rep=$item['podcat'];
$str.="[$pitem][sub]";
endforeach;
$str.="[{$item['podcat']}][sub]";

$str.="[{$item['id']}]";
                                $str.='=$item;';

eval($str);

foreach($path[$item['podcat']] as $pitem):
$path[$item['id']][]=$pitem;
endforeach;

$path[$item['id']][]=$item['podcat'];
}
else
{
$sort[$item['podcat']]['sub'][$item['id']]=$item;
$path[$item['id']][]=$item['podcat'];
}
}
           endforeach;
           }
           $this->arrayCat=$sort;
   return $this->arrayCat;
        }


        /**
        *   Печатает категории, помещает готовый HTML в $this->html
*   @param array Массив с категориями и вложенными подкатегориями
*   @param string Тип генерируемого HTML кода для вывода, option или table
        */        function outCategory(&$arrayCat, $type='option', $idSel=0) {
foreach($arrayCat as $sub) {
  $this->countPodcat++;
  $this->outItem($sub, $type);
  if(!empty($sub['sub']))$this->outCategory($sub['sub'], $type, $idSel);
  $this->countPodcat--;
}
}

/**
*   Вспомогательный метод подготовки HTML кода
*   @param array Массив с категорией
*   @param string Тип генерируемого HTML кода для вывода, option или table
*/        function outItem($sub, $type='option', $idSel=0) {
                for($i=0;$i<=$this->countPodcat;$i++) {
                        $out.='-';
}
if($idSel==$sub['id'])$se='selected'; else $se='';
if($type=='option')$this->html.="";
if($type=='table')$this->html.= <<{$out} index PHP: Категории бесконечного уровня вложенности.
{$sub['name']}

user edit PHP: Категории бесконечного уровня вложенности.

trash PHP: Категории бесконечного уровня вложенности.
HTML;

}

function delCategory(&$a_tree,&$id=0) {
foreach($a_tree as $sub) {
if($sub['id']<>$id and isset($sub['sub']))$this->delCategory($sub['sub'],$id);
if($sub['id']==$id) {
$sql="DELETE FROM {$this->table} WHERE id = '$id' LIMIT 1";
$this->DB->execute($sql);
if (isset($sub['sub'])) $this->delCategory_process($sub['sub']);
}
}
}

function delCategory_process(&$a_tree) {
foreach($a_tree as $sub) {
$sql="DELETE FROM {$this->table} WHERE id = '{$sub['id']}' LIMIT 1";
$this->DB->execute($sql);
if(isset($sub['sub']))$this->delCategory_process($sub['sub']);
}
}


function updateItem() {
$name=$this->PHP_slashes(strip_tags($_POST['name']));
$podcat=intval($_POST['podcat']);
$id=intval($_POST['id']);
$sql="UPDATE `{$this->table}` SET `name` = '{$name}',`podcat` = '{$podcat}'
WHERE `id`='{$id}' LIMIT 1; ";
$this->DB->execute($sql);

}

function addItem() {
$name=$this->PHP_slashes(strip_tags($_POST['name']));
$podcat=intval($_POST['podcat']);
$id=intval($_POST['id']);
$sql="INSERT INTO `{$this->table}` (`id`,`podcat`,`name`) VALUES ('', '$podcat', '$name');";
$this->DB->execute($sql);

}

function deleteItem($id) {
$id=intval($id);
$sql="DELETE FROM `{$this->table}` WHERE `id` = '{$id}' LIMIT 1";
$DB->execute($sql);
header("Location: ?component={$this->component}");
}

function PHP_slashes($string,$type='add') {
    if ($type == 'add') {
        if (get_magic_quotes_gpc()) {
            return $string;
            }
        else {
            if (function_exists('addslashes')) {
                return addslashes($string);
    }
            else {
                return mysql_real_escape_string($string);
            }
        }
    }
    else if ($type == 'strip') {
        return stripslashes($string);
    }
    else {
        die('error in PHP_slashes (mixed,add | strip)');
    }
}

}

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

Буду признателен если в комментариях вы предложите собственные варианты решения данной задачи — организации категорий бесконечного уровня вложенности.

Оставить комментарий

Консультации

Последние вопросы
Меню

Archive

Портфолио Все работы


с 2009 года по сегодняшний день, создано более 300 сайтов...