for example to output some image you need to write following in your twig template:
<img alt="" src="/bundles/sitebundle/images/image.jpg" />
But if you prefer Symfony way, you probably write something like:
<img alt="" src="{{asset('/bundles/sitebundle/images/image.jpg')}}" />
<img alt="" src="{{asset('/bundles/sitebundle/images/image.jpg')}}" />
But what if you can generate bundle assets path by bundle name, which is so familiar to you like 'YourGreatBundle' for example.
I decided to write some code for this.
Symfony's asset() twig function actually accepts 2nd argument, which is $packageName. $packageName is just named asset Package instance. By default it is PathPackage. Url for assets generated with getUrl() method of Package instance. All we need is create
custom asset Package class, let's call it BundlePathPackage:
<?php
namespace Vendor\SiteBundle\Asset\Package;
use Symfony\Component\Templating\Asset\PathPackage;
use Vendor\SiteBundle\Asset\Package\BundlePathPackageInterface;
/**
* Allows prepending bundle assets directory to base path
*/
class BundlePathPackage extends PathPackage implements BundlePathPackageInterface {
/**
* @var string
*/
private $bundleDir;
/**
* {@inheritdoc}
*/
public function __construct($basePath = null, $version = null, $format = null) {
parent::__construct($basePath, $version, $format);
}
/**
* If relative url detected, also prepend bundle dir to path
* {@inheritdoc}
*/
public function getUrl($path) {
if (isset($this->bundleDir))
$path = $this->bundleDir . '/' . ltrim($path, '/');
return parent::getUrl($path);
}
/**
* {@inheritdoc}
*/
public function setBundlePath($bundleName) {
$this->bundleDir = 'bundles/' . strtolower(str_replace('Bundle', '', $bundleName));
}
}
<?php
namespace Vendor\SiteBundle\Asset\Package;
interface BundlePathPackageInterface {
/**
* registers bundle dir by bundlename
* @param string $bundleName Identical to what
* Symfony\Component\HttpKernel\Bundle\BundleInterface->getName() gives
*/
public function setBundlePath($bundleName);
}
Almost done. Last step would be to tell Kernel that something new happens in our app. Something is Kernel event listener:
<?php
namespace Vendor\SiteBundle\Event\Listener\HttpKernel;
use Symfony\Component\HttpKernel\Event\KernelEvent;
use Vendor\SiteBundle\Asset\Package\BundlePathPackage;
class AssetPackageInjector {
/**
* Inject custom Asset package to Kernel assets helper
* @param \Symfony\Component\HttpKernel\Event\KernelEvent $event
*/
public function onKernelRequest(KernelEvent $event) {
$container = $event->getDispatcher()->getContainer();
/** @var Symfony\Component\Templating\Helper\CoreAssetsHelper */
$assetsHelper = $container->get('templating.helper.assets');
$bundles = $container->get('kernel')->getBundles();
foreach ($bundles as $bundle) {
$bundlePathPackage = new BundlePathPackage();
$bundlePathPackage->setBundlePath($bundle->getName());
$assetsHelper->addPackage($bundle->getName(), $bundlePathPackage);
}
}
}
Finally we register listener in services.yml configuration file:services:
vendor.site.event.listener.assetpackage:
class: Vendor\SiteBundle\Event\Listener\HttpKernel\AssetPackageInjector
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
That's it. Now in Twig we can write following:
<img alt="" src="{{asset('images/image.jpg', 'SiteBundle')}}" />
Or with leading slash (in this case base url will be appended if not standard):
<img alt="" src="{{asset('/images/image.jpg', 'SiteBundle')}}" />
No comments:
Post a Comment