Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

Simple way to create menu


Feb '16

Oct '16

6

1231

0

edited Feb '16
Feb '16

Component

<?php

use Phalcon\Tag;

class Menu extends \Phalcon\Mvc\User\Component
{
    protected $menu = [
        'sidebar-menu' => [
            'items' => [
                [
                    'class' => 'header',
                    'text' => 'HEADER',
                ],
                [
                    'link'  => [
                        'href' => '#',
                        'icon' => 'fa fa-link',
                        'text' => 'Link',
                    ],
                ],
                [
                    'link'  => [
                        'href' => '#',
                        'icon' => 'fa fa-link',
                        'text' => 'Another Link',
                    ],
                ],
                [
                    'class'   => 'treeview',
                    'submenu' => [
                        'link'  => [
                            'href'  => '#',
                            'icon'  => 'fa fa-link',
                            'text'  => 'Multilevel',
                            'wrap'  => 'span',
                            'caret' => 'fa fa-angle-left pull-right',
                        ],
                        'class' => 'treeview-menu',
                        'items' => [
                            [
                                'link'  => [
                                    'href' => '#',
                                    'text' => 'Link in level 2',
                                    'wrap' => 'span',
                                ],
                            ],
                            [
                                'link'  => [
                                    'href' => '#',
                                    'text' => 'Link in level 2',
                                    'wrap' => 'span',
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ],
    ];

    public function render()
    {
        /** @var \Phalcon\Cache\BackendInterface $cache */
        $cache = $this->getDI()->getShared('dataCache');

        if (!$menu = $cache->get('admin-menu')) {
            $menu = '';

            foreach ($this->menu as $classname => $menuData) {
                $menu .= sprintf('<ul class="%s">', $classname);
                $menu .= $this->renderItems($menuData['items']);
                $menu .= '</ul>';
            }

            if ($menu) {
                $cache->save('admin-menu', $menu, 60 * 60);
            }
        }

        echo $menu;
    }


    protected function renderItems($items)
    {
        if (empty($items) || !is_array($items)) {
            return '';
        }

        $html = '';

        foreach ($items as $item) {
            $html .= sprintf('<li class="%s">', (isset($item['class']) ? $item['class'] : ''));

            if (isset($item['text'])) {
                $html .= $item['text'];
            }

            if (isset($item['link'])) {
                $html .= $this->createLink($item['link']);
            }

            if (isset($item['submenu']) && is_array($item['submenu'])) {
                $submenu = $item['submenu'];
                if (isset($submenu['link'])) {
                    $html .= $this->createLink($submenu['link']);
                }

                $class = isset($submenu['class']) ? $submenu['class'] : '';
                $html .= sprintf('<ul class="%s">', $class);

                if (isset($submenu['items']) && is_array($submenu['items'])) {
                    $html .= $this->renderItems($submenu['items']);
                }

                $html .= '</ul>';
            }

            $html .= '</li>';
        }


        return $html;
    }

    protected function createLink($link)
    {
        /** @var \Phalcon\Tag $tag */
        $tag  = $this->getDI()->getShared('tag');

        if (empty($link) || !is_array($link)) {
            return '';
        }

        $local = isset($link['local']) ? boolval($link['local']) : true;
        $text  = isset($link['text']) ? $link['text'] : '';

        if (isset($link['wrap']) && is_string($link['wrap'])) {
            $text = strtr('<:open>:text</:close>', [
                ':open'  => $link['wrap'],
                ':close' => $link['wrap'],
                ':text'  => $text
            ]);
        }

        if (isset($link['icon']) && is_string($link['icon'])) {
            $text = strtr(':icon:text' ,[
                ':icon' => '<i class="'.$link['icon'].'"></i> ',
                ':text' => $text
            ]);
        }

        if (isset($link['caret']) && is_string($link['caret'])) {
            $text = strtr(':text:icon' ,[
                ':icon' => ' <i class="'.$link['caret'].'"></i>',
                ':text' => $text
            ]);
        }

        $href = isset($link['href']) ? $link['href'] : '';

        unset($link['text'], $link['local'], $link['wrap'], $link['icon'], $link['caret'], $link['href']);

        return $tag->linkTo([$href, $text] + (array) $link, ['local' => $local]);
    }
}

View

 {{ menu.render() }}

Result

result

Generated code

<ul class="sidebar-menu">
    <li class="header">HEADER</li>
    <li class="">
        <a href="#"><i class="fa fa-link"></i> <span>Link</span></a>
    </li>
    <li class="">
        <a href="#"><i class="fa fa-link"></i> <span>Another Link</span></a>
    </li>
    <li class="treeview">
        <a href="#"><i class="fa fa-link"></i> <span>Multilevel</span> <i class="fa fa-angle-left pull-right"></i></a>
        <ul class="treeview-menu">
            <li class="">
                <a href="#"><span>Link in level 2</span></a>
            </li>
            <li class="">
                <a href="#"><span>Link in level 2</span></a>
            </li>
        </ul>
    </li>
</ul>

Hi, I follow your example and an error: Service 'dataCache' wasn't found in the dependency injection container

And I added to index.php boostrap:

$di->setShared('dataCache', function(){ return new \Phalcon\Cache\BackendInterface; });

Please help me. I'am new bie


Serghei Iakovlev
8.1k
Accepted
answer
edited Mar '16
Mar '16

@thanhansoft Hello

dataCache it is my cache service. You can use your service or to define something like this:

$di->setShared('dataCache', function () {
    return new \Phalcon\Cache\Backend\Memcache(
        new \Phalcon\Cache\Frontend\Data(['lifetime' => 24 * 60 * 60]),
        [
            'prefix'     => 'my-data-cache-prefix-',
            'host'       => '127.0.0.1',
            'port'       => 11211,
            'persistent' => true,
            'statsKey'   => false,
        ]
    );
});

Hi, I added and present an error: Fatal error: Class 'memcache' not found in F:..... Line: 72

This is my line 72: if (!$menu = $cache->get('menu-frontend')) {

edited Mar '16
Mar '16

This means that you have not installed the php5-memcache extension. Or at least it is not enabled.

Follow this manual to caching arbitrary data

edited Mar '16
Mar '16

Hi Serghei Iakovlev, I want to pass variables to view helper for change class default. ex: {{ menu.render('classUl': 'class-abc', 'classLi': 'class-sub') }}

<ul class="class-abc">
    <li class="class-sub">HEADER</li>
</ul>

Please help me

public function render($classUl = 'class-abc', $classLi = 'class-sub')
{
    ...
    foreach ($this->menu as $classname => $menuData) {
        $classname = $classUl ?: $classname;
        $menu .= sprintf('<ul class="%s">', $classname);
        $menu .= $this->renderItems($menuData['items'], $classLi);
        $menu .= '</ul>';
    }
    ...
}

This is so cool @sergeyklay, will definitely incorporate this with my slayer-admin


Amal
97
edited Jun '16
Jun '16

This is really a good tip @sergeyklay. I would like to use it but my menu would come from a table. I would like to request you to modify your code to take the menu from a table. If you wish you can use the tables below. I also have a table Users and another table which will specify which user has permission to access which menu. If you can spare the time to modify the code it would be helpful to many users. You can make any changes to the tables which would make the implementation more generic.

CREATE TABLE co_menu_m (
  co_menu_id int(10) unsigned NOT NULL,
  co_menu_category_id int(10) unsigned NULL,
  co_menu_title varchar(60) DEFAULT NULL,
  co_menu_desc varchar(100) DEFAULT NULL,
  co_menu_level smallint(5) unsigned NOT NULL,  // Level (depth) of the menu 1,2,3...
  co_menu_parent_iid int(10) unsigned NOT NULL, // Parent Id of the menu to create hierarchy
  co_menu_link varchar(100) DEFAULT NULL,       // Link/Page where it points to
  co_menu_enabled char(1) DEFAULT NULL,
  co_menu_active char(1) DEFAULT NULL,

  PRIMARY KEY (co_user_id, co_menu_id)
) ;

create table co_user_m
(
    co_user_id              int unsigned not null,           // User Id
    co_password             char(20) null, 
    co_user_name            char(30) null, 
    co_perm                 char(1) null, 

    primary key (co_user_iid)
) ;

CREATE TABLE co_usermenu_perm (
  co_user_id int(10) unsigned NOT NULL,
  co_menu_id int(10) unsigned NOT NULL,
  co_menu_visible char(1) DEFAULT NULL,

  PRIMARY KEY (co_user_id, co_menu_id)
) ;

In case I can help you with anything, kindly let me know. Thanks in advance.


Amal
97
edited Oct '16
Oct '16

@sergeyklay I have written the exact code you have mentioned but I don't get the caret for Multileveltreeview menu. Secondly I get to see bullets on the left for each menu. The code generated is given below:

    <div class="col-sm-2 col-md-2 col-lg-2 affix-content">
        <div id="wrap">
            <div class="container">

<ul class="sidebar-menu">
    <li class="header">HEADER</li>
    <li class=""><a href="/payroll/#"><i class="fa fa-link"></i> Link</a></li>
    <li class=""><a href="/payroll/#"><i class="fa fa-link"></i> Another Link</a></li>
    <li class="treeview"><a href="/payroll/#"><i class="fa fa-link"></i> <span>Multilevel</span> <i class="fa fa-angle-left pull-right"></i></a>
        <ul class="treeview-menu">
            <li class=""><a href="/payroll/#"><span>Link in level 2</span></a></li>
            <li class=""><a href="/payroll/#"><span>Link in level 2</span></a></li>
        </ul>
    </li>
</ul>

            </div>
        </div>
    </div>

Menu

edited Oct '16
Oct '16

@amsharma9 You have to use custom CSS for it. I used AdminLTE