Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Solid Menu Bundle Laravel Package

solidcloud/solid-menu-bundle

A menu bundle for SolidCloud applications that helps define, organize, and render navigational menus through a simple, configurable API. Useful for adding structured site navigation to PHP projects while keeping menu logic reusable and easy to maintain.

View on GitHub
Deep Wiki
Context7

Getting Started

SolidMenuBundle is a thin Symfony bundle that ships Twig rendering themes for KnpMenuBundle. It does not replace KnpMenu — it layers presentation on top of it, so the day-to-day workflow is KnpMenu’s workflow plus a set of ready-made templates.

Minimum steps:

  1. Install both bundles (SolidMenu depends on KnpMenu):
    composer require solidcloud/solid-menu-bundle
    composer require knplabs/knp-menu-bundle
    
  2. Register the bundles in config/bundles.php:
    return [
        Knp\Bundle\MenuBundle\KnpMenuBundle::class => ['all' => true],
        Solid\MenuBundle\SolidMenuBundle::class => ['all' => true],
    ];
    
  3. Confirm the theme assets landed where expected:
    php bin/console debug:container --tag=twig.loader.namespaced_paths
    php bin/console debug:twig | grep -i -A2 solid
    
    You should see a Twig namespace (commonly @SolidMenu) registered by the bundle. That namespace is where every theme template lives.

Where to look first: vendor/solidcloud/solid-menu-bundle/src/Resources/views/ (or templates/). This is your ground truth for theme names, block structure, and CSS class assumptions — there is no published API surface beyond these templates.

First use case — a top nav:

// src/Menu/MainMenuBuilder.php
namespace App\Menu;

use Knp\Menu\FactoryInterface;
use Knp\Menu\ItemInterface;

final class MainMenuBuilder
{
    public function __construct(private FactoryInterface $factory) {}

    public function build(): ItemInterface
    {
        $menu = $this->factory->createItem('root');
        $menu->addChild('Home', ['route' => 'app_home']);
        $menu->addChild('Admin', ['uri' => '/admin']);
        return $menu;
    }
}
# config/services.yaml
App\Menu\MainMenuBuilder:
    tags: [{ name: knp_menu.menu_builder, method: build, alias: main }]
{# templates/base.html.twig #}
{{ knp_menu_render('main', {
    'template': '@SolidMenu/theme/bootstrap.html.twig'
}) }}

If that renders nothing, the bundle is working but the template name is wrong — list the actual templates with find vendor/solidcloud/solid-menu-bundle -name '*.twig'.

Implementation Patterns

Builder services, not config. Treat SolidMenu purely as the view layer. Keep menus in MenuBuilder services tagged knp_menu.menu_builder with an alias. This gives you DI (URL generators, security checks, request stack) and is far more testable than YAML menu definitions.

Theme selection three ways, pick one and stay consistent:

  • Per render: pass template in the options array (best for one-off pages).
  • Globally: knp_menu.renderer.twig.options.template in config/packages/knp_menu.yaml — set this to a SolidMenu theme and every menu inherits it.
  • Per menu: override in the builder by attaching a renderer option, useful when a sidebar and a topbar need different skins.

Runtime theme switching for multi-tenant or admin/frontend split:

// a listener or controller concern
$theme = $this->isAdmin ? '@SolidMenu/theme/admin.html.twig'
                        : '@SolidMenu/theme/site.html.twig';

Pass it through Twig globals rather than hardcoding in every template — one config/packages/twig.yaml entry and done.

Extend, don’t copy. The SolidMenu theme files are built on KnpMenu’s knp_menu.html.twig block structure (root, list, item, label, linkElement, children, attributes, compressed, spanElement). Override only the blocks you need:

{% extends '@SolidMenu/theme/bootstrap.html.twig' %}

{% block item %}
    {# add a badge or icon before delegating to the parent #}
    {{ parent() }}
{% endblock %}

This keeps you upgrade-safe. Copying the whole theme into templates/ is the single most common way teams get stuck when KnpMenu bumps block names.

Bootstrap/markup integration. SolidMenu themes typically emit Bootstrap-style <ul class="nav"> structures with active/current classes driven by KnpMenu’s currentClass, ancestorClass, and firstClass/lastClass options. Set these on the root item ($menu->setChildrenAttribute('class', 'nav flex-column')) rather than in the theme, so the menu remains reusable across skins.

Testing — render the menu builder in isolation:

$menu = $builder->build();
$this->assertSame('Home', $menu->getChild('Home')->getLabel());

Then a single functional test hitting a page that renders a theme catches template breakage from upgrades.

Gotchas and Tips

  • This bundle has no dependents and effectively no users. Treat it as unmaintained-adjacent. Pin the version in composer.json ("solidcloud/solid-menu-bundle": "1.*") and be prepared to fork — it’s MIT and small, so forking is often cheaper than waiting on a fix.
  • KnpMenu major-version drift is the top risk. KnpMenu 3.x renamed/reshuffled several Twig blocks. If you upgrade knplabs/knp-menu-bundle and menus render bare or throw Block "X" not defined, the SolidMenu theme is stale against the new block names. Fix by extending and overriding, or by pinning KnpMenu until you fork.
  • @SolidMenu namespace not found almost always means the bundle wasn’t registered (or was registered after Twig in a misconfigured bundles.php). bin/console debug:twig | grep -i solid is the 5-second diagnostic.
  • Clear the cache after touching themes. Twig caches compiled templates aggressively; php bin/console cache:clear (and cache:pool:clear cache.app in prod-like environments) before you start debugging a change that “didn’t apply”.
  • Menu items silently vanish when a route doesn’t exist. KnpMenu resolves route lazily at render time; a typo in route: app_home produces neither an exception nor an item. Cross-check with bin/console debug:router | grep app_home.
  • uri vs route matters for the current class. uri-based items often don’t get currentClass applied the way route-based items do, because KnpMenu matches on the matched route name. Prefer route wherever possible.
  • Security-gated items (hide a menu entry when the user lacks ROLE_ADMIN) should be done in the builder by injecting AuthorizationCheckerInterface and calling $menu->removeChild(...), not with Twig {% if %} around knp_menu_render — otherwise you get empty <ul> wrappers and broken first/last classes.
  • Translation: $menu->addChild('menu.home', ['route' => ...]) works out of the box because the theme passes labels through the trans filter by default in most KnpMenu themes — verify in vendor/.../theme/*.twig before relying on it.
  • Extension point you’ll actually use: register your own Twig namespace (config/packages/twig.yaml → paths:) with a project-local themes/ directory and extend SolidMenu’s theme from there. That isolates all your presentation tweaks to one folder and makes the eventual fork/replacement a one-line config change.
  • Don’t expect docs. The repo’s README is your only reference; if a theme’s expected options (e.g. depth, matchingDepth, leaf_class) aren’t documented, read the template — it’s 30 lines and tells you exactly which KnpMenu render options it consumes.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource