2

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
  • 19,631
  • 51
  • 159
  • 265
  • 1
    Take a look at this question: http://stackoverflow.com/questions/14231967/symfony2-checking-if-file-exists – Juan Sosa Jun 03 '13 at 14:15

3 Answers3

18

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.

Alain Tiemblo
  • 36,099
  • 17
  • 121
  • 153
  • I have add / in assets_exists `TEST IMAGE => {% if asset_exists('/bundles/fuztest/images/test.png') %} YES ! asset_exists {% else %}NO asset_exists :({% endif %}` – Barno Dec 16 '13 at 10:45
  • @Alain Tiemblo I've tried your solution and I'm looking for .jpg files if it exists to list out a
    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
    – esteemed.squire Jun 25 '14 at 01:42
  • This Twig function checks if a real path exists. This mean, `asset_exists('/images/some_image.jpg')` will return true if `some_image.jpg` exists. You currently can't put a joker in the file name, but that's quite simple to implement. Replace `if (!is_file($toCheck))` by `if (count(glob($toCheck)) == 0)`. Then, use `asset_exists('/image/*.jpeg')`. – Alain Tiemblo Jun 25 '14 at 05:32
  • 1
    You don't need to inject the whole kernel here - just the `%kernel.root_dir%` parameter. – Sam Jan 07 '16 at 10:29
  • Ohh yeah, you're right. This answer is a bit old, I'll update it when I'll have time. Thanks! – Alain Tiemblo Jan 07 '16 at 10:31
  • I took out the "well contained" check - `realpath` resolves symlinks, so in development (where I use `assets:install --symlink`), `$toCheck` was always outside the web-root by this stage (i.e. pointing to the original file under `src`). – Sam Jan 11 '16 at 12:03
1

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
Doc
  • 11
  • 1
0

Hi Milos I already answered this question here : https://stackoverflow.com/a/14232207/875519

Just register file_exists by extending Twig engine and then you'll be able to test inside Twig templates ^^

Community
  • 1
  • 1
Sybio
  • 8,565
  • 3
  • 44
  • 53
  • Thank 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. – Milos Cuculovic Jun 03 '13 at 14:19
  • -1,Your answer gives a way to check if a file exists, not specifically an asset. – Alain Tiemblo Jun 03 '13 at 19:22
  • My 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. – Alain Tiemblo Jun 03 '13 at 21:21