PHP Classes

SB PHP Menu Builder: Create menus and store definitions in files

Recommend this page to a friend!
  Info   View files Example   View files View files (4)   DownloadInstall with Composer Download .zip   Reputation   Support forum   Blog (1)    
Last Updated Ratings Unique User Downloads Download Rankings
2023-09-11 (1 month ago) RSS 2.0 feedNot yet rated by the usersTotal: 100 This week: 4All time: 9,737 This week: 23Up
Version License PHP version Categories
sb_menu 1.0.0BSD License8HTML, Files and Folders, GUI, PHP 8
Description 

Author

This class allows for creating, modifying, saving, loading, and displaying a menu tree without needing a database.

The menus display menu entries with labels. Menu entries may have child menu entries that form a tree hierarchy.

Each menu entry is associated with a callback function called by this package when the user clicks on that menu entry.

The definition of the menu entries can be modified dynamically.

The definition of menus can be saved to text files that work like a flat-file database.

The menu definitions can be loaded later from same text files.

Innovation Award
PHP Programming Innovation award nominee
September 2023
Nominee
Vote
Many Web sites need to present their navigation to the users so that they understand the site's structure.

Often, those sites use navigation menus that define a tree structure of its entries.

Some sites store the menu definition in a database.

Although that way of storing menu definition works well, the database queries that need to be performed during the request that serves the pages with the menus may be slow due to the need to perform database queries.

This package implements a menu-building solution that uses files to store menu definitions.

This way, it can load menu definition files faster than loading the same menu definitions using database queries.

Manuel Lemos
Picture of JImmy Bo
  Performance   Level  
Name: JImmy Bo <contact>
Classes: 14 packages by
Country: United States United States
Innovation award
Innovation award
Nominee: 8x

Winner: 1x

Instructions

Class Methods:

save($filename) - saves the menu tree to a file
load($filename) - loads the menu tree from a file

getNodeByField($field, $value) - returns a reference to the node with a field that matches a value
applyCallbackToNode($id, $callback) - applies a callback to a node with a specific id
applyCallbackToNodeByField($field, $value, $callback) - applies a callback to a node with a specific field that matches a value

Examples:

class.sb_menu.test.directory.php 	// an example showing a directory and subdirectories
class.sb_menu.test.simple.php		// a simple multilevel collapsible flexible and responsive accordion menu

See examples or the top of the class file for more details on how to use the various methods.

Example

<?php
/*
Name: SB Menu - A PHP Class for Building Menus - Simple Test Usage
File: class.sb_menu.test.simple.php
License: BSD 3-Clause License <https://opensource.org/licenses/BSD-3-Clause>
Description: An example usage of class to create/modify/save/load/display a menu tree.

Info:
    I left js and css in this file to keep it more contained

Version: 1.0

PHP Version: 8+

REQUIRED PHP CLASSES: class.sb_menu.php

Author: https://www.phpclasses.org/browse/author/144301.html
*/

   
include_once("class.sb_menu_1.0.php");

   
   
// extend the main Tree class to add a custom render() method

   
class SimpleTree_Extended extends Tree {

        public function
render($addClass='') {
           
$pre = "\r\n\r\n<div class='sbmenu ".$addClass."'><div class='container'>\r\n\r\n";
           
$post = "\r\n</div></div><!-- sbmenu //-->\r\n";

           
$output = $this->renderNode($this->root, 0);

            return
$pre.$output.$post;
        }
   
        private function
renderNode(TreeNode $node, $depth)
        {
           
$output = '';
   
            if(
$depth > 0) # skip first node as it is the main node. Just show sublevels
           
{
               
$id = $node->data['id'];
               
$label = $node->data['label'];

               
$has_children = true;
                if(empty(
$node->children))
                   
$has_children = false;

               
$root = '';
                if(
$depth == 1)
                   
$root = "root";

               
# cheap padding
               
$pad = "\t";
               
$pad_left = str_repeat($pad, $depth);

               
$html_pad = "&nbsp;&nbsp;&nbsp;";
               
$html_pad_left = str_repeat($html_pad, $depth);
   

               
$output .= "$pad_left<div class='node $root' depth=".$depth.">\r\n";

                       
$extra_html = '';
                       
// if we have child nodes
                       
if($has_children)
                           
$extra_html .= "<div class='arrow'></div>\r\n";

                       
$add_class = '';
                        if(
$has_children)
                           
$add_class = 'has-submenu';


                       
$output .= "$pad_left$pad_left<div class='label $add_class' d=$depth>$html_pad_left".$label."</div>$extra_html\r\n";
                        if(
$has_children)
                            foreach (
$node->children as $child)
                               
$output .= $this->renderNode($child, $depth+1);
   
               
$output .= "$pad_left</div><!-- depth=$depth //-->\r\n\r\n";

                return
$output;
            }
            else {
                foreach (
$node->children as $child)
                   
$output .= $this->renderNode($child, $depth+1);
            }
   
            return
$output;
        }
               
    }
// end class MyTree extends Tree



## BEGIN PHP SIDE EXAMPLE ##


// $menu = new Tree(new TreeNode('Main Menu')); // if you just want to use base class
   
$menu = new SimpleTree_Extended(new TreeNode('Main Menu')); // .. or the extended class to seperate the render() method


           
$last_menu = $menu->root->addChild(new TreeNode('Submenu 1'));
           
$last_menu = $menu->root->addChild(new TreeNode('Submenu 2'));
               
// another level
               
$next_level = $last_menu->addChild(new TreeNode('Item 2.1'));
                   
// another level
                   
$next_level = $next_level->addChild(new TreeNode('Item 2.1.1'));
                   
           
$last_menu = $menu->root->addChild(new TreeNode('Submenu 3'));

               
// add to root menu choices
               
$submenu = $menu->root->addChild(new TreeNode('Submenu 4'));
                       
// another level
                       
$next_level = $submenu->addChild(new TreeNode('Item 4.1'));
                           
// another level
                           
$next_level = $next_level->addChild(new TreeNode('Item 4.1.1'));
                               
// another level
                               
$next_level = $next_level->addChild(new TreeNode('Item 4.1.1.1'));
                                   
// ... etc

                       
$next_level = $submenu->addChild(new TreeNode('Item 4.2'));
                           
$next_level->data['url'] = "https://www.google.com"; // handled in extended class
                           
$next_level->data['target'] = "_blank"; // handled in extended class

                       
$next_level = $submenu->addChild(new TreeNode('Item 4.3'));
                           
// another level
                           
$next_level = $next_level->addChild(new TreeNode('Item 4.3.1'));
                               
// another level
                               
$next_level = $next_level->addChild(new TreeNode('Item 4.3.1.1'));



           
# save
           
$menu->save('menu-simple.txt');

           
# load
           
$menu2 = $menu->load('menu-simple.txt');

## END PHP SIDE EXAMPLE ##


?>
<!DOCTYPE html>
<html>
    <head>
        <title>SB Menu - A PHP Class for Building Menus - Simple Test Usage</title>

        <!-- jquery -->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>


<!-- BEGIN JS //-->
        <script>
            // page uses jQuery
            // docready
            $(document).ready(function () {
                // Toggle nodes when a label with 'has-submenu' class is clicked
                $('.label.has-submenu')
                    .off('click')
                    .on('click', function () {

                        // // make slide effect
                        $(this).siblings('.node').slideToggle(60);

                        // $(this).parent().find('.arrow').first().toggleClass('active');
                        $(this).toggleClass('active');
                });
            });
        </script>
<!-- END JS //-->

<!-- BEGIN CSS //-->

       

    <style>
            .sbmenu {
                position:relative;
                display:block;
                /* make click through */
                pointer-events:none;

                /* make it look like a menu */
                font-family:Arial, Helvetica, sans-serif;
                text-align:center;

                /* disable text selection */
                -webkit-user-select:none;
                -moz-user-select:none;
                -ms-user-select:none;
                -o-user-select:none;
                user-select:none;

                font-size:0.9em;
                width:100%;
               
                vertical-align:top;
               
            }
            .sbmenu .container {
                display:block;
                position:relative;

                text-align:center;
                vertical-align:top;


            }
            .sbmenu div {
                position:relative;
                vertical-align:top;
                margin:0px;padding:0px;
                min-width:10em;
            }
            .node {
                display:none;
                pointer-events:auto;
            }
            .root {
                display:inline-block;
                position:relative;
                top:0px;
            }

            .unhide {
                display:block;
            }

            .label {
                position:relative;

                display:block;
                padding:0.6em;

                padding-left:3em;
                padding-right:3em;

                cursor:pointer;
                text-align:left;
            }

            .label[d="1"]{
                font-size:1.2em;
                text-align:center;
                font-weight:bold;
                border-bottom:1px solid #ccc;
                padding-bottom:0.3em;
                margin-bottom:0.1em;
                padding-top:0.5em;
            }

            .label:hover {
                background-color:orange;
                color:white;
                cursor: pointer;
            }

            /* add an arrow text decoration to has-submenu */
            .label.has-submenu::after {
                color:#ccc;
                text-align:right;
                /* right arrow */
                content: " ?";
                font-size:1em;
                position:absolute;
                right:0px;
            } /* when clicked rotate */
            .label.has-submenu.active::after {
                color:orange;
                content: " ?";
                font-size:1em;
            }


            /* if mobile... */
            @media (max-width: 780px) {
                .sbmenu .container {
                    text-align:left;
                    width:100%;
                }
                .sbmenu .node {
                    text-align:left;
                    width:100%;
                }
                .sbmenu .label {
                    text-align:left;
                    width:100%;
                    font-size:1.2em;
                }

            }


    </style>
       
       
       
<!-- END CSS //-->

    </head>

    <body>
        <?php
           
# render the menu
           
echo $menu2->render();
       
?>



    </body>
</html>


Details

The SB Menu class is a PHP class that allows for the creation, modification, saving, loading, and display of a menu tree without the need for a database. This class is designed to be simple, efficient, and easily customizable. It uses a flatfile approach, meaning that the menu structure is stored in a text file rather than a database. 'label' (user provided) and 'id' (generated) are default fields in the base class. Class Methods: save($filename) - saves the menu tree to a file load($filename) - loads the menu tree from a file getNodeByField($field, $value) - returns a reference to the node with a field that matches a value applyCallbackToNode($id, $callback) - applies a callback to a node with a specific id applyCallbackToNodeByField($field, $value, $callback) - applies a callback to a node with a specific field that matches a value Examples: class.sb_menu.test.directory.php // an example showing a directory and subdirectories class.sb_menu.test.simple.php // a simple multilevel collapsible flexible and responsive accordion menu EXAMPLE USAGE: EXAMPLE USAGE: EXAMPLE USAGE: <?php // include the class include_once("class.sb_menu_1.0.php"); // example creation... (look at class.sb_menu.test.simple.php for extended class needed to render) class SimpleTree_Extended extends Tree { ... extended code ( render(), renderNode(), etc ) ... } // create extended class of Tree and throw in a render and renderNode to customize display based on dynamic data fields // we pass the name we want for the main root node. In the example, we skip rendering this root node. $menu = new SimpleTree_Extended(new TreeNode('Main Menu')); // .. or the extended class to seperate the render() method // now add some menus... // when menu is created, a root node is created and assigned to $menu->root. This is our main level. $last_menu = $menu->root->addChild(new TreeNode('Submenu 1')); $last_menu = $menu->root->addChild(new TreeNode('Submenu 2')); // another level $next_level = $last_menu->addChild(new TreeNode('Item 2.1')); // example adding more data for our extended class to use with a custom render() method $next_level->data['url'] = "https://www.google.com"; // handled in extended class render $next_level->data['target'] = "_blank"; // handled in extended class render // # use a callback to run some code on a specific node via its id (id and label are default fields in base class) $menu->applyCallbackToNode($s2_id, function($node) { $node->data['label'] = 'New Label'; $new_submenu = new TreeNode('New Submenu'); $node->addChild($new_submenu); }); // example usage of applyCallbackToNodeByField($field, $value, $callback) // (this example changes the label of the node with label 'Submenu 1' to 'New Label') $menu->applyCallbackToNodeByField('label', 'Submenu 1', function($node) { $node->data['label'] = 'New Label'; }); // get the reference to the node by a field for modification. (only returns first match) // example usage of getNodeByField($key, $value) $s2 = $menu->getNodeByField('label', 'Submenu 2'); $s2_id = $s2->data['id']; # save (ez) (make sure directory or file is writeable) $menu->save('menu-simple.txt'); # load (pz) $menu2 = $menu->load('menu-simple.txt'); // render (display the menu :: see example Tree extended class in class.sb_menu.test.simple.php ) echo $menu->render('sbmenu'); // render defined in extended class ?>

  Files folder image Files  
File Role Description
Accessible without login Plain text file class.sb_menu.README.txt Doc. README and USAGE
Accessible without login Plain text file class.sb_menu.test.directory.php Example Example showing dir/subdirs/and files
Accessible without login Plain text file class.sb_menu.test.simple.php Example Example Extended Class and Usage
Plain text file class.sb_menu_1.0.php Class SB Menu - A PHP Class for Building Menus

 Version Control Unique User Downloads Download Rankings  
 0%
Total:100
This week:4
All time:9,737
This week:23Up