Symfony2 - проверка наличия файла

У меня есть цикл в шаблоне Twig, который возвращает несколько значений. Самое главное - идентификатор моей записи. Когда я не использовал фреймворк или механизм шаблонов, я использовал просто file_exists() в цикле. Теперь я не могу найти способ сделать это в Twig.

Когда я отображаю аватар пользователя в заголовке, я использую file_exists() в контроллере, но я делаю это, потому что у меня нет цикла.

Я попытался defined в Twig, но это мне не помогает. Есть идеи?

Ответ 1

Если вы хотите проверить наличие файла, который не является шаблоном ветки (так что он не может работать), создайте службу TwigExtension и добавьте функцию file_exists() в twig:

src/AppBundle/Twig/Extension/TwigExtension.php

<?php

namespace AppBundle\Twig\Extension;

class FileExtension extends \Twig_Extension
{

    /**
     * Return the functions registered as twig extensions
     * 
     * @return array
     */
    public function getFunctions()
    {
        return array(
            new Twig_SimpleFunction('file_exists', 'file_exists'),
        );
    }

    public function getName()
    {
        return 'app_file';
    }
}
?>

Зарегистрируйте свой сервис:

src/AppBundle/Resources/config/services.yml

# ...

parameters:

    app.file.twig.extension.class: AppBundle\Twig\Extension\FileExtension

services:

    app.file.twig.extension:
        class: %app.file.twig.extension.class%
        tags:
            - { name: twig.extension }

Что он, теперь вы можете использовать file_exists() внутри шаблона ветки;)

Некоторые template.twig:

{% if file_exists('/home/sybio/www/website/picture.jpg') %}
    The picture exists !
{% else %}
    Nope, Chuck testa !
{% endif %}

EDIT, чтобы ответить на ваш комментарий:

Чтобы использовать file_exists(), вам нужно указать абсолютный путь к файлу, поэтому вам нужен абсолютный путь к веб-каталогу, чтобы сделать это, чтобы получить доступ к веб-пути в ваших шаблонах twig app/config/config.yml:

# ...

twig:
    globals:
        web_path: %web_path%

parameters:
    web_path: %kernel.root_dir%/../web

Теперь вы можете получить полный физический путь к файлу внутри шаблона ветки:

{# Display: /home/sybio/www/website/web/img/games/3.jpg #}
{{ web_path~asset('img/games/'~item.getGame.id~'.jpg') }}

Таким образом, вы сможете проверить, существует ли файл:

{% if file_exists(web_path~asset('img/games/'~item.getGame.id~'.jpg')) %}

Ответ 2

Я создал функцию Twig, которая является расширением ответов, которые я нашел на эту тему. Моя функция asset_if принимает два параметра: первый - это путь для отображаемого актива. Второй параметр - резервный актив, если первый актив не существует.

Создайте файл расширения:

SRC/Showdates/FrontendBundle/Twig/Extension/ConditionalAssetExtension.php:

<?php

namespace Showdates\FrontendBundle\Twig\Extension;

use Symfony\Component\DependencyInjection\ContainerInterface;

class ConditionalAssetExtension extends \Twig_Extension
{
    private $container;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    /**
     * Returns a list of functions to add to the existing list.
     *
     * @return array An array of functions
     */
    public function getFunctions()
    {
        return array(
            'asset_if' => new \Twig_Function_Method($this, 'asset_if'),
        );
    }

    /**
     * Get the path to an asset. If it does not exist, return the path to the
     * fallback path.
     * 
     * @param string $path the path to the asset to display
     * @param string $fallbackPath the path to the asset to return in case asset $path does not exist
     * @return string path
     */
    public function asset_if($path, $fallbackPath)
    {
        // Define the path to look for
        $pathToCheck = realpath($this->container->get('kernel')->getRootDir() . '/../web/') . '/' . $path;

        // If the path does not exist, return the fallback image
        if (!file_exists($pathToCheck))
        {
            return $this->container->get('templating.helper.assets')->getUrl($fallbackPath);
        }

        // Return the real image
        return $this->container->get('templating.helper.assets')->getUrl($path);
    }

    /**
     * Returns the name of the extension.
     *
     * @return string The extension name
     */
    public function getName()
    {
       return 'asset_if';
    }
}

Зарегистрируйте свой сервис (app/config/config.yml или src/App/YourBundle/Resources/services.yml):

services:
    showdates.twig.asset_if_extension:
        class: Showdates\FrontendBundle\Twig\Extension\ConditionalAssetExtension
        arguments: ['@service_container']
        tags:
          - { name: twig.extension }

Теперь используйте его в своих шаблонах следующим образом:

<img src="{{ asset_if('some/path/avatar_' ~ app.user.id, 'assets/default_avatar.png') }}" />

Ответ 3

У меня была такая же проблема, как у Томека. Я использовал решение Sybio и внес следующие изменения:

  1. app/config.yml => добавить "/" в конец web_path

    parameters:
        web_path: %kernel.root_dir%/../web/
    
  2. Вызовите file_exists без "актива":

    {% if file_exists(web_path ~ 'img/games/'~item.getGame.id~'.jpg') %}
    

Надеюсь это поможет.

Ответ 4

Просто добавьте небольшой комментарий к вкладу Sybio:

Класс Twig_Function_Function устарел с версии 1.12 и будет удален в версии 2.0. Вместо этого используйте Twig_SimpleFunction.

Мы должны изменить класс Twig_Function_Function на Twig_SimpleFunction:

<?php

namespace Gooandgoo\CoreBundle\Services\Extension;

class TwigExtension extends \Twig_Extension
{

    /**
     * Return the functions registered as twig extensions
     *
     * @return array
     */
    public function getFunctions()
    {
        return array(
            #'file_exists' => new \Twig_Function_Function('file_exists'), // Old class
            'file_exists' => new \Twig_SimpleFunction('file_exists', 'file_exists'), // New class
        );
    }

    public function getName()
    {
        return 'twig_extension';
    }
}

Остальная часть кода по-прежнему работает точно так же, как сказал Сибио.

Ответ 5

Улучшая ответ Sybio, Twig_simple_function не существует для моей версии, и здесь ничего не работает для внешних изображений. Таким образом, файл расширения файла выглядит следующим образом:

namespace AppBundle\Twig\Extension;

class FileExtension extends \Twig_Extension
{
/**
 * {@inheritdoc}
 */

public function getName()
{
    return 'file';
}

public function getFunctions()
{
    return array(
        new \Twig_Function('checkUrl', array($this, 'checkUrl')),
    );
}

public function checkUrl($url)
{
    $headers=get_headers($url);
    return stripos($headers[0], "200 OK")?true:false;
}