I had trouble with styling svg icons on the fly in my project and therefore created a “quick and dirty helper” for displaying SVG Icons as svg and not in the image tag.
I have the helper in
src/View/Helper/IconHelper.php
<?php
declare(strict_types=1);
namespace App\View\Helper;
use Cake\View\Helper;
use Cake\View\View;
use Cake\Utility\Xml;
/**
* SVG helper
*/
class IconHelper extends Helper
{
/**
* Default configuration.
*
* @var array<string, mixed>
*/
protected array $_defaultConfig = [];
protected array $helpers = ['Html'];
public function svg(array|string $path, array $options = []): string
{
$path = WWW_ROOT.'img'.DS.$path;
$xml = Xml::build($path, ['readFile' => true]);
$options = array_diff_key($options, ['fullBase' => null, 'pathPrefix' => null]);
if (isset($options['class'])) { //change attribute "class" if necessary
$xml['class'] =$options['class'] ;
}
if (isset($options['title'])) { //add title if necessary
$xml->addChild('title', $options['title']);
}
$svg = $xml->asXML();
return $svg;
}
}
In
src/View/AppView.php
i added in “function initialize()”
$this->addHelper('Icon');
The Usage in a view file is:
a) for displaying only the svg:
<?= $this->Icon->svg('icons'.DS.'book-open.svg',['title'=>__('Quoth the Raven ...Nevermore...'),'class'=>'icon-base']) ?>
Output is:
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="icon-base">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25"></path>
<title>Quoth the Raven ...Nevermore...</title></svg>
b) for displaying as “image” link:
<?= $this->Html->link(
$this->Icon->svg('icons'.DS.'book-open.svg',['title'=>__('Quoth the Raven ...Nevermore...'),'class'=>'icon-base']),
['_name'=>'user-edit'],
['escape' => false]
)
?>
Output is:
<a href="/recipes/user/edit"><!--?xml version="1.0"?-->
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="icon-base">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25"></path>
<title>Quoth the Raven ...Nevermore...</title></svg>
</a>
I tested with Heroicon Icon from https://heroicons.com/
I get no error messages and the icons are displayed correctly and can be styled with css-classes.
But I´m still al learner and ask you kindly to check if and how the code can be improved.
Edit:
The Icons are stored as *.svg files in
webroot/img/icons/