Kotchasan Framework Documentation

Kotchasan Framework Documentation

Menu Class - Menu System

EN 03 Feb 2026 16:36

Menu Class - Menu System

The Menu class provides HTML menu rendering from arrays with support for nested submenus.

Namespace

Kotchasan\Menu

Overview

The Menu class provides:

  • HTML menu generation from arrays
  • Nested submenu support (multi-level)
  • Selected state display
  • Target attribute support
  • Clean HTML output

Public Methods (2 methods)

render()

Generate HTML menu from array

public static function render(array $items, string $select): string

Parameters:

  • $items - Menu items array
  • $select - Name of selected menu

Returns: HTML string

Array Structure:

[
    'menu-name' => [
        'text' => 'Menu Text',      // Display text
        'url' => '/path',           // URL (optional)
        'target' => '_blank',       // Target (optional)
        'submenus' => [...]         // Submenu (optional)
    ]
]

Example:

use Kotchasan\Menu;

$items = [
    'home' => [
        'text' => 'Home',
        'url' => '/'
    ],
    'about' => [
        'text' => 'About',
        'url' => '/about'
    ],
    'products' => [
        'text' => 'Products',
        'submenus' => [
            'electronics' => [
                'text' => 'Electronics',
                'url' => '/products/electronics'
            ],
            'books' => [
                'text' => 'Books',
                'url' => '/products/books'
            ]
        ]
    ]
];

$html = Menu::render($items, 'home');
echo $html;

getItem()

Generate HTML for single menu item (protected - internal use)

protected static function getItem(
    string|int $name,
    array $item,
    bool $arrow,
    string $select
): string

Note: This method is protected, used internally by render()

Complete Usage Examples

1. Simple Menu

use Kotchasan\Menu;

$menu = [
    'dashboard' => [
        'text' => 'Dashboard',
        'url' => '/dashboard'
    ],
    'users' => [
        'text' => 'Users',
        'url' => '/users'
    ],
    'settings' => [
        'text' => 'Settings',
        'url' => '/settings'
    ]
];

echo '<ul>';
echo Menu::render($menu, 'dashboard'); // 'dashboard' is selected
echo '</ul>';

HTML Output:

<ul>
<li class="dashboard select"><a href="/dashboard" title="Dashboard"><span>Dashboard</span></a></li>
<li class="users"><a href="/users" title="Users"><span>Users</span></a></li>
<li class="settings"><a href="/settings" title="Settings"><span>Settings</span></a></li>
</ul>

2. Multi-Level Menu

use Kotchasan\Menu;

$menu = [
    'home' => [
        'text' => 'Home',
        'url' => '/'
    ],
    'shop' => [
        'text' => 'Shop',
        'submenus' => [
            'electronics' => [
                'text' => 'Electronics',
                'submenus' => [
                    'phones' => [
                        'text' => 'Phones',
                        'url' => '/shop/electronics/phones'
                    ],
                    'laptops' => [
                        'text' => 'Laptops',
                        'url' => '/shop/electronics/laptops'
                    ]
                ]
            ],
            'clothing' => [
                'text' => 'Clothing',
                'url' => '/shop/clothing'
            ]
        ]
    ],
    'contact' => [
        'text' => 'Contact',
        'url' => '/contact'
    ]
];

echo '<ul class="menu">';
echo Menu::render($menu, 'phones');
echo '</ul>';

3. Menu with Target Attribute

use Kotchasan\Menu;

$menu = [
    'internal' => [
        'text' => 'Internal Link',
        'url' => '/page'
    ],
    'external' => [
        'text' => 'External Link',
        'url' => 'https://example.com',
        'target' => '_blank'
    ],
    'docs' => [
        'text' => 'Documentation',
        'url' => 'https://docs.example.com',
        'target' => '_blank'
    ]
];

echo '<ul>';
echo Menu::render($menu, '');
echo '</ul>';

4. Dynamic Menu from Database

use Kotchasan\Menu;
use Kotchasan\Model;

class MenuRenderer
{
    public static function buildMenu($currentPage)
    {
        // Fetch menu items from database
        $menuItems = Model::create()
            ->from('menus')
            ->where(['status', 1])
            ->order('sort_order')
            ->all();

        // Convert to array for Menu::render()
        $menu = [];
        $submenuMap = [];

        foreach ($menuItems as $item) {
            $menuData = [
                'text' => $item->title,
                'url' => $item->url
            ];

            if ($item->target) {
                $menuData['target'] = $item->target;
            }

            if ($item->parent_id == 0) {
                $menu[$item->alias] = $menuData;
                $submenuMap[$item->id] = &$menu[$item->alias];
            } else {
                if (!isset($submenuMap[$item->parent_id]['submenus'])) {
                    $submenuMap[$item->parent_id]['submenus'] = [];
                }
                $submenuMap[$item->parent_id]['submenus'][$item->alias] = $menuData;
            }
        }

        return Menu::render($menu, $currentPage);
    }
}

// Usage
echo '<nav>';
echo '<ul class="main-menu">';
echo MenuRenderer::buildMenu('products');
echo '</ul>';
echo '</nav>';

5. Admin Sidebar Menu

use Kotchasan\Menu;
use Kotchasan\Login;

class AdminMenu
{
    public static function render($current)
    {
        $login = Login::isMember();

        $menu = [
            'dashboard' => [
                'text' => 'Dashboard',
                'url' => '/admin/dashboard'
            ]
        ];

        // Admin only
        if (Login::isAdmin($login)) {
            $menu['users'] = [
                'text' => 'Users',
                'submenus' => [
                    'list' => [
                        'text' => 'All Users',
                        'url' => '/admin/users'
                    ],
                    'add' => [
                        'text' => 'Add New',
                        'url' => '/admin/users/add'
                    ]
                ]
            ];

            $menu['settings'] = [
                'text' => 'Settings',
                'submenus' => [
                    'general' => [
                        'text' => 'General',
                        'url' => '/admin/settings'
                    ],
                    'security' => [
                        'text' => 'Security',
                        'url' => '/admin/settings/security'
                    ]
                ]
            ];
        }

        $menu['profile'] = [
            'text' => 'My Profile',
            'url' => '/admin/profile'
        ];

        return Menu::render($menu, $current);
    }
}

// Usage
echo '<aside class="sidebar">';
echo '<ul class="admin-menu">';
echo AdminMenu::render('dashboard');
echo '</ul>';
echo '</aside>';

6. Breadcrumb Menu

use Kotchasan\Menu;

class Breadcrumb
{
    public static function render($path)
    {
        $parts = explode('/', trim($path, '/'));
        $menu = [];
        $url = '';

        $menu['home'] = [
            'text' => 'Home',
            'url' => '/'
        ];

        foreach ($parts as $part) {
            if (!empty($part)) {
                $url .= '/' . $part;
                $menu[$part] = [
                    'text' => ucfirst($part),
                    'url' => $url
                ];
            }
        }

        // Last item is current (no link)
        $last = array_key_last($menu);
        if ($last && $last !== 'home') {
            unset($menu[$last]['url']);
        }

        return Menu::render($menu, $last);
    }
}

// Usage
echo '<nav class="breadcrumb">';
echo '<ul>';
echo Breadcrumb::render('/products/electronics/phones');
echo '</ul>';
echo '</nav>';

7. Conditional Menu Items

use Kotchasan\Menu;
use Kotchasan\Login;

$login = Login::isMember();

$menu = [];

// For everyone
$menu['home'] = [
    'text' => 'Home',
    'url' => '/'
];

// Logged in only
if ($login) {
    $menu['dashboard'] = [
        'text' => 'Dashboard',
        'url' => '/dashboard'
    ];

    // Admin only
    if (Login::isAdmin($login)) {
        $menu['admin'] = [
            'text' => 'Admin',
            'submenus' => [
                'users' => [
                    'text' => 'Manage Users',
                    'url' => '/admin/users'
                ],
                'content' => [
                    'text' => 'Content',
                    'url' => '/admin/content'
                ]
            ]
        ];
    }

    $menu['logout'] = [
        'text' => 'Logout',
        'url' => '/logout'
    ];
} else {
    $menu['login'] = [
        'text' => 'Login',
        'url' => '/login'
    ];
}

echo '<ul class="nav">';
echo Menu::render($menu, 'home');
echo '</ul>';

HTML Output Format

<li class="menu-name"><a href="/url" title="Text"><span>Text</span></a></li>
<li class="menu-name select"><a href="/url" title="Text"><span>Text</span></a></li>
<li class="menu-name"><span class=menu-arrow title="Text"><span>Text</span></span><ul>
  <!-- submenu items -->
</ul>
<li class="menu-name"><span title="Text"><span>Text</span></span>

Best Practices

1. Clean Array Structure

// ✅ Good - clear structure
$menu = [
    'products' => [
        'text' => 'Products',
        'submenus' => [
            'new' => ['text' => 'New', 'url' => '/products/new'],
            'sale' => ['text' => 'Sale', 'url' => '/products/sale']
        ]
    ]
];

// ❌ Bad - missing text
$menu = [
    'products' => [
        'url' => '/products'  // Missing 'text'
    ]
];

2. Selected State

// ✅ Good - pass current page
$current = 'dashboard';
echo Menu::render($menu, $current);

// ✅ Good - use empty string if no selection
echo Menu::render($menu, '');
// ✅ Good - specify target for external links
$menu = [
    'docs' => [
        'text' => 'Documentation',
        'url' => 'https://docs.example.com',
        'target' => '_blank'
    ]
];

Summary

The Menu class is a simple tool for:

  • ✅ Generate HTML menus from arrays
  • ✅ Nested submenu support
  • ✅ Selected state display
  • 📝 Clean, semantic HTML
  • 🎨 Use CSS for styling

Suitable for:

  • Navigation menus
  • Admin sidebars
  • Breadcrumbs
  • Dropdown menus
  • Multi-level menus

File Size: 79 lines
Public Methods: 2 methods (1 public, 1 protected)
Pattern: Static utility class