Sunday, January 24, 2010

Unlimited Categories Implementation by Recursively

  1. MySQL Table Definition:
    CREATE TABLE `categories` (
    `id` int(10) unsigned NOT NULL auto_increment,
    `name` varchar(50) NOT NULL,
    `parent_id` int(10) unsigned zerofill NOT NULL,
    `type` int(10) unsigned zerofill NOT NULL default '0',
    PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8;
  2. Implementation for DataObject
    public static function get_all($type = NULL, $parent_id = 0, $depth = 3, $count = 0){
    if($count == $depth) return;
    $condition = is_int($type) ? "AND type=$type" : '';

    $categories = Database::instance()->query("SELECT * FROM categories WHERE parent_id = '$parent_id' $condition")->result_array(FALSE);

    if(count($categories) == 0) return NULL;
    foreach ($categories as &$category) {
    $category['parent_id'] = intval($category['parent_id']);
    $category['type'] = intval($category['type']);
    $subcategories = self::get_all($type, $category['id'], $depth, $count+1);
    if($subcategories) $category['subcategories'] = $subcategories;
    }

    return $categories;
    }
  3. Implementation for Logical UI
    public static function output_options($categories,  $depth = 2, $level = 0, $nest = 0){
    if($nest == $depth || !is_array($categories)) return '';

    $html = '';
    foreach($categories as $category){
    $html .= "<option value=\"{$category['id']}\"";
    if($nest < $level) $html .= ' disabled="disabled"';
    $html .= '>';
    for($i=0,$j=$nest;$i<$j;$i++) $html .= ' ';
    $html .= "{$category['name']}</option>\n";

    if(isset($category['subcategories'])) {
    $html .= self::output_options($category['subcategories'], $depth, $level, $nest+1);
    }
    }
    return $html;
    }
  4. Usage
    $categories = category::get_all(0,0,2); // All Type, Parent Id = 0, MaxDepth = 2
    echo category::output_options($categories, 2);

0 Comments: