Symfony2 and Twig - Check if an asset exists
12,612
Solution 1
If you want to check if an asset exists, you can create a Twig extension to implement the function.
PHP In your Twig\Extension
directory, create AssetExistsExtension.php
with the following content:
<?php
namespace Fuz\TestBundle\Twig\Extension;
use Symfony\Component\HttpKernel\KernelInterface;
class AssetExistsExtension extends \Twig_Extension
{
private $kernel;
public function __construct(KernelInterface $kernel)
{
$this->kernel = $kernel;
}
public function getFunctions()
{
return array(
'asset_exists' => new \Twig_Function_Method($this, 'asset_exists'),
);
}
public function asset_exists($path)
{
$webRoot = realpath($this->kernel->getRootDir() . '/../web/');
$toCheck = realpath($webRoot . $path);
// check if the file exists
if (!is_file($toCheck))
{
return false;
}
// check if file is well contained in web/ directory (prevents ../ in paths)
if (strncmp($webRoot, $toCheck, strlen($webRoot)) !== 0)
{
return false;
}
return true;
}
public function getName()
{
return 'asset_exists';
}
}
YML And here is the configuration, to put in your services.yml
file.
parameters:
(...)
fuz_tools.twig.asset_exists_extension.class: Fuz\TestBundle\Twig\Extension\Asset@ExistsExtension
services:
(...)
fuz_tools.twig.asset_exists_extension:
class: '%fuz_tools.twig.asset_exists_extension.class%'
arguments: ['@kernel']
tags:
- { name: twig.extension }
Twig To use this extension, on a twig file, use:
{% if asset_exists('bundles/fuztest/images/test.png') %}
Note: do not forget to replace namespaces to match with your project.
Solution 2
There's a typo in your code:
fuz_tools.twig.asset_exists_extension.class: Fuz\TestBundle\Twig\Extension\AssetsExistsExtension
should be
fuz_tools.twig.asset_exists_extension.class: Fuz\TestBundle\Twig\Extension\AssetExistsExtension
Author by
Milos Cuculovic
Masters degree in Embedded and comunicant systems.
Updated on September 05, 2022Comments
-
Milos Cuculovic over 1 year
I have a symfony2 project using twig templates.
I am displaying some images and would like to display the image only if the specific asset exists.
I have this:
{% if asset('bundles/sciforumversion2/images/logos/'~conf.img) %} <img style="width: 60px; float:right; margin-right: 15px;" src="{{ asset('bundles/sciforumversion2/images/logos/')}}{{ conf.img }}"/> {% endif %}
But the if condition is always true.
Any idea please? Thank you.
-
Milos Cuculovic almost 11 yearsThank you Sybio. This could work but I found another way, which works in my case. For each conference object, I have the image object, if the image is set, the image object will be null for a specific conference, so I can test it this way. But you answer is more complete and I will accept it. Thanks again.
-
Alain Tiemblo almost 11 years-1,Your answer gives a way to check if a file exists, not specifically an asset.
-
Alain Tiemblo almost 11 yearsMy point is, you could inject kernel in your extension and use a proper method to check if an asset exists, I'll write my answer this will be better to explain.
-
Barno over 10 yearsI have add / in assets_exists
TEST IMAGE => {% if asset_exists('/bundles/fuztest/images/test.png') %} YES ! asset_exists {% else %}NO asset_exists :({% endif %}
-
esteemed.squire almost 10 years@Alain Tiemblo I've tried your solution and I'm looking for .jpg files if it exists to list out a <div> to display the image if not, don't display the image. I am using the following:
{% if asset_exists('/images/.jpeg') %}
and nothing is found even though the posts being listed have .jpeg files to them. Is using .jpeg the proper way to look for this? The images are in web/images -
Alain Tiemblo almost 10 yearsThis Twig function checks if a real path exists. This mean,
asset_exists('/images/some_image.jpg')
will return true ifsome_image.jpg
exists. You currently can't put a joker in the file name, but that's quite simple to implement. Replaceif (!is_file($toCheck))
byif (count(glob($toCheck)) == 0)
. Then, useasset_exists('/image/*.jpeg')
. -
Sam over 8 yearsYou don't need to inject the whole kernel here - just the
%kernel.root_dir%
parameter. -
Alain Tiemblo over 8 yearsOhh yeah, you're right. This answer is a bit old, I'll update it when I'll have time. Thanks!
-
Sam over 8 yearsI took out the "well contained" check -
realpath
resolves symlinks, so in development (where I useassets:install --symlink
),$toCheck
was always outside the web-root by this stage (i.e. pointing to the original file undersrc
).