Icon Helper
A comprehensive CakePHP helper for rendering icons from popular icon libraries, with support for both font-based and SVG rendering modes.
The Icon helper provides a unified interface for rendering icons from multiple popular icon libraries. It supports three distinct rendering modes, each optimized for different use cases and performance requirements.
This page covers the overview, quick start, setup, and everyday usage. See also:
- Icon Configuration, the full configuration reference and per-set setups.
- Icon Advanced, backend browser, IDE auto-complete, custom sets, and configuration tips.
Key features
- Support for 8+ popular icon libraries
- Automatic mode detection based on configuration
- Advanced two-tier caching system
- Icon mapping and aliasing
- Backend browser interface
- IDE auto-completion support
- Performance optimizations for production
Rendering modes
Font-based icons (traditional)
- Uses icon fonts (CSS classes or data attributes).
- Requires loading CSS/font files.
- Lightweight setup, familiar approach.
- Limited customization options.
SVG icons
JSON map (recommended)
- All icons loaded from a single JSON file.
- Reads the map once before caching its contents.
- Full SVG customization plus caching benefits.
- The whole map occupies memory even when only one icon is rendered.
Individual SVG files
- Each icon loaded from a separate
.svgfile. - Full SVG customization capabilities.
- Ideal for selective icon usage or custom sets.
- Requires file system access per icon.
Quick start
Font-based rendering:
// In your AppView.php
$this->loadHelper('Templating.Icon', [
'sets' => [
'bs' => [
'class' => \Templating\View\Icon\BootstrapIcon::class,
'path' => ROOT . DS . 'node_modules/bootstrap-icons/font/bootstrap-icons.json',
],
],
]);
// In your template
echo $this->Icon->render('house'); // <span class="bi bi-house" title="House"></span>SVG rendering (JSON map):
// In your AppView.php
$this->loadHelper('Templating.Icon', [
'sets' => [
'feather' => [
'class' => \Templating\View\Icon\FeatherIcon::class,
'svgPath' => ROOT . DS . 'node_modules/feather-icons/dist/icons.json',
],
],
]);
// In your template
echo $this->Icon->render('home'); // <svg>...</svg> (inline SVG)SVG rendering (individual files):
// In your AppView.php
$this->loadHelper('Templating.Icon', [
'sets' => [
'lucide' => [
'class' => \Templating\View\Icon\LucideIcon::class,
'svgPath' => ROOT . DS . 'node_modules/lucide-static/icons/',
],
],
]);
// In your template
echo $this->Icon->render('home'); // <svg>...</svg> (loaded from home.svg)Installation and setup
1. Load the helper
Add the Icon helper to your src/View/AppView.php:
public function initialize(): void
{
parent::initialize();
$this->loadHelper('Templating.Icon', [
'sets' => [
'bs' => [
'class' => \Templating\View\Icon\BootstrapIcon::class,
'path' => ROOT . DS . 'node_modules/bootstrap-icons/font/bootstrap-icons.json',
],
'fa6' => [
'class' => \Templating\View\Icon\FontAwesome6Icon::class,
'path' => ROOT . DS . 'node_modules/@fortawesome/fontawesome-free/metadata/icons.json',
],
],
]);
}2. Install icon libraries
npm is not required
This plugin does not handle asset management or shipping of icon files. You can install icon libraries using any method (npm, Composer, CDN, manual download, etc.). The plugin only needs to know where the files are located via the configuration paths.
Install your preferred icon libraries via npm:
# Bootstrap Icons
npm install bootstrap-icons
# FontAwesome
npm install @fortawesome/fontawesome-free
# Lucide (modern Feather fork)
npm install lucide-static
# Heroicons (by Tailwind CSS)
npm install heroicons
# Feather Icons
npm install feather-icons
# Material Symbols
npm install material-symbols::: important Font CSS is your responsibility For font-based icons, you must include the necessary CSS/font files in your layout yourself. The plugin only generates the HTML markup, it does not handle loading stylesheets or font files. :::
Ship icon files to production
When deploying your application, ensure icon files are available in production. If using npm-installed icons, include them in your build/deployment process or copy them to a permanent location. The plugin expects icon files to exist at the configured paths, missing files will cause runtime errors.
3. Configuration
You can store default configurations in config/app.php:
'Icon' => [
'sets' => [
'bs' => [
'class' => \Templating\View\Icon\BootstrapIcon::class,
'svgPath' => ROOT . DS . 'node_modules/bootstrap-icons/icons/',
],
'fa6' => [
'class' => \Templating\View\Icon\FontAwesome6Icon::class,
'svgPath' => ROOT . DS . 'node_modules/@fortawesome/fontawesome-free/svgs/solid/',
],
],
'map' => [
'home' => 'bs:house',
'user' => 'fa6:user',
'settings' => 'bs:gear',
],
],See Icon Configuration for the full reference.
Run npm commands from the application root. SVG and metadata examples below read from that root's node_modules directory. Copy font CSS and referenced font files into webroot, or serve them through your application's asset build.
Supported icon sets
| Icon Set | Class | NPM Package |
|---|---|---|
| Bootstrap Icons | BootstrapIcon | bootstrap-icons |
| FontAwesome v7 | FontAwesome7Icon | @fortawesome/fontawesome-free |
| FontAwesome v6 | FontAwesome6Icon | @fortawesome/fontawesome-free |
| FontAwesome v5 | FontAwesome5Icon | @fortawesome/fontawesome-free@5 |
| FontAwesome v4 | FontAwesome4Icon | font-awesome |
| Lucide | LucideIcon | lucide-static |
| Heroicons | HeroiconsIcon | heroicons |
| Feather | FeatherIcon | feather-icons |
| Material Icons | MaterialIcon | material-symbols |
Besides these out-of-the-box ones, you can easily create your own Icon class. See Creating custom icon sets.
Usage
Basic rendering
// Render using alias
echo $this->Icon->render('home');
// Render with explicit namespace
echo $this->Icon->render('bs:house');
// Render with attributes
echo $this->Icon->render('user', [], ['class' => 'text-primary', 'title' => 'User Profile']);Icon prefixes and auto-prefixing
The Icon helper provides flexible prefixing to handle multiple icon sets.
#Automatic aliases need readable path metadata or an svgPath directory/map for every participating set. Without those files, an unprefixed name falls back to the first set.
Auto-prefixing (default behavior)
Automatic aliases require readable metadata or an SVG directory/map for every set. Clear the name cache after updating icon files.
By default, autoPrefix is enabled, which automatically creates unprefixed aliases for all icons:
'Icon' => [
'autoPrefix' => true, // Default - creates automatic mappings
'sets' => [
'bs' => [
'class' => \Templating\View\Icon\BootstrapIcon::class,
'path' => ROOT . DS . 'node_modules/bootstrap-icons/font/bootstrap-icons.json',
],
'fa6' => [
'class' => \Templating\View\Icon\FontAwesome6Icon::class,
'path' => ROOT . DS . 'node_modules/@fortawesome/fontawesome-free/metadata/icons.json',
],
],
],// All these work without prefixes (first match wins)
echo $this->Icon->render('home'); // Uses fa6:home (metadata alias)
echo $this->Icon->render('house'); // Uses bs:house
echo $this->Icon->render('user'); // Uses fa6:user
// Explicit prefixes always work
echo $this->Icon->render('bs:house');
echo $this->Icon->render('fa6:user');Manual prefixing only
Disable automatic alias generation. Unprefixed names still fall back to the first set:
'Icon' => [
'autoPrefix' => false, // Disable automatic mappings
'sets' => [
'bs' => [
'class' => \Templating\View\Icon\BootstrapIcon::class,
'path' => ROOT . DS . 'node_modules/bootstrap-icons/font/bootstrap-icons.json',
],
'fa6' => [
'class' => \Templating\View\Icon\FontAwesome6Icon::class,
'path' => ROOT . DS . 'node_modules/@fortawesome/fontawesome-free/metadata/icons.json',
],
],
'map' => [
'home' => 'bs:house', // Manual aliases only
'user' => 'fa6:user',
],
],// Explicit prefixes, manual mappings and the default set remain available
echo $this->Icon->render('bs:house'); // Works
echo $this->Icon->render('fa6:user'); // Works
echo $this->Icon->render('home'); // Works (manual mapping)
echo $this->Icon->render('house'); // Uses the first setHandling icon conflicts
When multiple sets have the same icon name:
'Icon' => [
'sets' => [
'bs' => [
'class' => \Templating\View\Icon\BootstrapIcon::class,
'path' => ROOT . DS . 'node_modules/bootstrap-icons/font/bootstrap-icons.json',
], // First set (default)
'fa6' => [
'class' => \Templating\View\Icon\FontAwesome6Icon::class,
'path' => ROOT . DS . 'node_modules/@fortawesome/fontawesome-free/metadata/icons.json',
],
],
],// Both sets have a "house" icon
echo $this->Icon->render('house'); // Uses Bootstrap (first set)
echo $this->Icon->render('bs:house'); // Explicitly Bootstrap
echo $this->Icon->render('fa6:house'); // Explicitly FontAwesomeUse manual mapping to resolve conflicts:
'Icon' => [
'map' => [
'home' => 'bs:house', // Use Bootstrap house for "home"
'home-alt' => 'fa6:home', // Alternative FontAwesome home
],
],Attributes and options
echo $this->Icon->render('settings',
['translate' => false], // Options
['class' => 'icon-lg', 'data-toggle' => 'tooltip'] // HTML attributes
);Available options:
translate(bool), whether to translate the title attribute.titleField(string), attribute name for auto-generated titles.- Put a custom
titleortitle => falsein the third, attributes argument. A stringtitlein the second argument is deprecated.
Auto-title translation
When a title attribute is auto-generated from the icon name (for example, arrow-left becomes Arrow Left), translation is off by default.
The translateAutoTitle config flag opts auto-generated titles back into translation for apps that have curated Arrow Left → Pfeil links mappings:
'Icon' => [
'translateAutoTitle' => true, // Default: false
],Caller-supplied titles (when you pass $attributes['title'] = 'Custom Title') continue to be translated by default. To override either contract per-call, pass translate => true|false in $options:
$this->Icon->render('arrow-left'); // title="Arrow Left" (no translation)
$this->Icon->render('arrow-left', ['translate' => true]); // title runs through translation
$this->Icon->render('save', [], ['title' => 'Save now']); // 'Save now' translated by default
$this->Icon->render('save', ['translate' => false], ['title' => 'Save now']); // not translatedWhy auto-title translation is off by default
The previous behavior translated auto-generated titles unconditionally, which had two problems: the runtime translation value is dynamic, so a static PO scanner could not extract the title strings (every icon name needed a hand-curated entry in template.po), and most apps never translate icon titles, so the runtime call was pure overhead and a misleading "this gets translated" signal.
Getting available icons
$icons = $this->Icon->names();
foreach ($icons as $iconSet => $iconList) {
echo "Icon set: {$iconSet}\n";
foreach ($iconList as $icon) {
echo " - {$icon}\n";
}
}Example output:
Icon set: bs
- house
- gear
- person
Icon set: fa6
- home
- user
- cogDemo: sandbox.dereuromark.de/sandbox/templating-examples/icons