{"id":2457,"date":"2018-09-10T15:39:11","date_gmt":"2018-09-10T10:09:11","guid":{"rendered":"https:\/\/pheonixsolutions.com\/blog\/?p=2457"},"modified":"2026-09-28T20:30:59","modified_gmt":"2026-09-28T15:00:59","slug":"create-dynamic-menu-from-database-using-codeigniter","status":"publish","type":"post","link":"https:\/\/pheonixsolutions.com\/blog\/create-dynamic-menu-from-database-using-codeigniter\/","title":{"rendered":"Create Dynamic Multi-Level Menu from Database Using CodeIgniter"},"content":{"rendered":"\n<h4 class=\"wp-block-heading\"><strong>Post Date: <\/strong>September 10, 2018<br><strong>Last Updated: September 22, 2026<\/strong><\/h4>\n\n\n\n<h2 class=\"wp-block-heading\">&nbsp;Introduction<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Dynamic menus are a common requirement in modern web applications. Instead of hardcoding menu items, storing menu data in a database allows administrators to add, update, or remove menu entries without modifying application code.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this tutorial, we will create a <strong>dynamic multi-level menu (parent and child categories)<\/strong> using CodeIgniter and MySQL. The menu structure will be generated recursively from a database table, making it suitable for category trees, navigation menus, product catalogs, and content management systems.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">By the end of this guide, you will learn how to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Create a category table in MySQL<\/li>\n\n\n\n<li>Fetch parent and child categories dynamically<\/li>\n\n\n\n<li>Build recursive menu structures<\/li>\n\n\n\n<li>Organize code using CodeIgniter&#8217;s MVC architecture<\/li>\n\n\n\n<li>Generate unlimited menu levels<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before starting, ensure you have:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>CodeIgniter installed and configured<\/li>\n\n\n\n<li>MySQL database configured<\/li>\n\n\n\n<li>Basic knowledge of:\n<ul class=\"wp-block-list\">\n<li>PHP<\/li>\n\n\n\n<li>MySQL<\/li>\n\n\n\n<li>CodeIgniter MVC structure<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Database connectivity configured in <code>application\/config\/database.php<\/code><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">How It Works<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The application follows this process:<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/pheonixsolutions.com\/blog\/wp-content\/uploads\/2018\/09\/category_menu_flow-scaled.png\"><img fetchpriority=\"high\" decoding=\"async\" width=\"911\" height=\"1024\" data-id=\"11891\" src=\"https:\/\/pheonixsolutions.com\/blog\/wp-content\/uploads\/2018\/09\/category_menu_flow-911x1024.png\" alt=\"\" class=\"wp-image-11891\" srcset=\"https:\/\/pheonixsolutions.com\/blog\/wp-content\/uploads\/2018\/09\/category_menu_flow-911x1024.png 911w, https:\/\/pheonixsolutions.com\/blog\/wp-content\/uploads\/2018\/09\/category_menu_flow-267x300.png 267w, https:\/\/pheonixsolutions.com\/blog\/wp-content\/uploads\/2018\/09\/category_menu_flow-768x863.png 768w, https:\/\/pheonixsolutions.com\/blog\/wp-content\/uploads\/2018\/09\/category_menu_flow-1367x1536.png 1367w, https:\/\/pheonixsolutions.com\/blog\/wp-content\/uploads\/2018\/09\/category_menu_flow-1823x2048.png 1823w\" sizes=\"(max-width: 911px) 100vw, 911px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Database Structure<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Create Categories Table<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Execute the following SQL query:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">CREATE TABLE `categories` (\n  `cat_id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `cat_name` varchar(50) COLLATE latin1_general_ci NOT NULL,\n  `parent_id` int(10) unsigned NOT NULL DEFAULT '0',\n  PRIMARY KEY (`cat_id`)\n) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Table Explanation<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><th>Column<\/th><th>Description<\/th><\/tr><tr><td>cat_id<\/td><td>Unique category ID<\/td><\/tr><tr><td>cat_name<\/td><td>Category name<\/td><\/tr><tr><td>parent_id<\/td><td>Parent category reference<\/td><\/tr><tr><td>0<\/td><td>Indicates a root category<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Example Data<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><th>cat_id<\/th><th>cat_name<\/th><th>parent_id<\/th><\/tr><tr><td>1<\/td><td>Electronics<\/td><td>0<\/td><\/tr><tr><td>2<\/td><td>Mobile Phones<\/td><td>1<\/td><\/tr><tr><td>3<\/td><td>Android Phones<\/td><td>2<\/td><\/tr><tr><td>4<\/td><td>iPhones<\/td><td>2<\/td><\/tr><tr><td>5<\/td><td>Laptops<\/td><td>1<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Resulting Structure:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Electronics\n\u251c\u2500\u2500 Mobile Phones\n\u2502   \u251c\u2500\u2500 Android Phones\n\u2502   \u2514\u2500\u2500 iPhones\n\u2514\u2500\u2500 Laptops<\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Create Controller<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create a new controller file:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>application\/controllers\/Dashboard.php<\/code><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\nclass Dashboard extends MY_Controller {\n\n    public function __construct()\n    {\n        parent::__construct();\n        $this->load->model('Dashboard_model');\n    }\n\n    public function index()\n    {\n        $data['title'] = \"Dashboard\";\n        $data['page_name'] = \"Dashboard\";\n\n        $this->include_view('dashboard', $data);\n    }\n\n    public function categories()\n    {\n        $data = $this->Dashboard_model->get_categories();\n\n        echo \"&lt;pre>\";\n        print_r($data);\n        echo \"&lt;\/pre>\";\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Controller Responsibilities<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Loads the model<\/li>\n\n\n\n<li>Requests category data<\/li>\n\n\n\n<li>Sends data to views<\/li>\n\n\n\n<li>Displays hierarchical category structure<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Create Model<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create a model file:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>application\/models\/Dashboard_model.php<\/code><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\nclass Dashboard_model extends CI_Model {\n\n    public function get_categories()\n    {\n        $this->db->select('*');\n        $this->db->from('categories');\n        $this->db->where('parent_id', 0);\n\n        $parent = $this->db->get();\n\n        $categories = $parent->result();\n\n        $i = 0;\n\n        foreach ($categories as $p_cat)\n        {\n            $categories[$i]->sub = $this->sub_categories($p_cat->cat_id);\n            $i++;\n        }\n\n        return $categories;\n    }\n\n    public function sub_categories($id)\n    {\n        $this->db->select('*');\n        $this->db->from('categories');\n        $this->db->where('parent_id', $id);\n\n        $child = $this->db->get();\n\n        $categories = $child->result();\n\n        $i = 0;\n\n        foreach ($categories as $p_cat)\n        {\n            $categories[$i]->sub = $this->sub_categories($p_cat->cat_id);\n            $i++;\n        }\n\n        return $categories;\n    }\n}<\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Understanding the Recursive Function<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The key feature of this implementation is recursion.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What Happens?<\/h3>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>Fetch all parent categories.<\/li>\n\n\n\n<li>For each parent category:\n<ul class=\"wp-block-list\">\n<li>Search for child categories.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>If child categories exist:\n<ul class=\"wp-block-list\">\n<li>Search for their children.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Continue until no more child categories are found.<\/li>\n\n\n\n<li>Return the complete nested structure.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Recursive Flow<\/h3>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Parent Category\n      \u2502\n      \u25bc\nFind Child Categories\n      \u2502\n      \u25bc\nChild Found?\n \u251c\u2500 No \u2192 Return\n \u2514\u2500 Yes\n       \u2502\n       \u25bc\nCall Function Again\n       \u2502\n       \u25bc\nFind Next Level Children<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This approach supports unlimited menu depth.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Sample Output<\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Array\n(\n    [0] => stdClass Object\n        (\n            [cat_id] => 1\n            [cat_name] => Electronics\n            [parent_id] => 0\n            [sub] => Array\n                (\n                    [0] => stdClass Object\n                        (\n                            [cat_id] => 2\n                            [cat_name] => Mobile Phones\n                            [parent_id] => 1\n                        )\n                )\n        )\n)<\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Benefits of Dynamic Menus<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>No hardcoded navigation<\/li>\n\n\n\n<li>Easy administration<\/li>\n\n\n\n<li>Unlimited category levels<\/li>\n\n\n\n<li>Database-driven architecture<\/li>\n\n\n\n<li>Suitable for eCommerce sites<\/li>\n\n\n\n<li>Suitable for CMS platforms<\/li>\n\n\n\n<li>Better scalability<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Performance Considerations<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For large category trees:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Recommended Improvements<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Add an index on <code>parent_id<\/code><\/li>\n<\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ALTER TABLE categories\nADD INDEX idx_parent_id(parent_id);<\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Implement caching<\/li>\n\n\n\n<li>Use eager loading where possible<\/li>\n\n\n\n<li>Limit recursion depth if required<\/li>\n\n\n\n<li>Consider Nested Sets or Closure Tables for very large datasets<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Creating a dynamic menu from a database in CodeIgniter is an effective way to build scalable and maintainable navigation systems. By using a recursive model function, you can generate multi-level category trees of any depth without hardcoding menu items.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This approach is ideal for:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>eCommerce category navigation<\/li>\n\n\n\n<li>CMS menus<\/li>\n\n\n\n<li>Product hierarchies<\/li>\n\n\n\n<li>Knowledge base structures<\/li>\n\n\n\n<li>Blog category systems<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">With proper indexing and caching, this solution can efficiently handle both small and large category structures while keeping your application flexible and easy to manage.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Frequently Asked Questions (FAQ)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. Can this support unlimited menu levels?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. The recursive function allows unlimited parent-child relationships.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. What does <code>parent_id = 0<\/code> mean?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">It identifies root-level categories.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Can I display the data as a Bootstrap dropdown menu?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. The returned array can be looped through recursively in a view to generate Bootstrap dropdown navigation.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Related Articles<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/pheonixsolutions.com\/blog\/restore-database-on-xampp-from-command-line\/\">Restore Database on Xampp from command line<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/pheonixsolutions.com\/blog\/wp-admin\/post.php?post=1634&amp;action=edit\">Export data from Database to Excel Sheet(.xls) using Codeigniter<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/pheonixsolutions.com\/blog\/create-a-database-and-the-user-for-that-database-in-cpanel\/\">Create a database and the user for that database in cPanel<\/a><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Talk to our experts<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Have a technology challenge or looking for the right solution for your business? Our team can help you with <strong>cloud, DevOps, development, infrastructure, design, and more<\/strong>. Feel free to reach out to our experts <a href=\"https:\/\/pheonixsolutions.com\/contact\">here<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Post Date: September 10, 2018Last Updated: September 22, 2026 &nbsp;Introduction Dynamic menus are a common requirement in modern web applications. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[1022],"tags":[],"class_list":["post-2457","post","type-post","status-publish","format-standard","hentry","category-web-architecture","psol-cat-web-architecture"],"jetpack_publicize_connections":[],"jetpack_shortlink":"https:\/\/wp.me\/phn2x7-DD","jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/2457","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/comments?post=2457"}],"version-history":[{"count":3,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/2457\/revisions"}],"predecessor-version":[{"id":11988,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/2457\/revisions\/11988"}],"wp:attachment":[{"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/media?parent=2457"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/categories?post=2457"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/tags?post=2457"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}