web-dev-qa-db-de.com

Symfony2 - Überprüfen, ob eine Datei vorhanden ist

Ich habe eine Schleife in der Twig-Vorlage, die mehrere Werte zurückgibt. Am wichtigsten - eine ID meines Eintrags. Wenn ich weder ein Framework noch eine Template-Engine verwendet habe, habe ich einfach file_exists() innerhalb der Schleife verwendet. Jetzt kann ich in Twig keinen Weg finden, dies zu tun.

Wenn ich den Avatar des Benutzers in der Kopfzeile anzeige, verwende ich file_exists() im Controller, aber ich mache das, weil ich keine Schleife habe.

Ich habe defined in Twig ausprobiert, aber es hilft mir nicht. Irgendwelche Ideen?

12
Tomek Buszewski

Wenn Sie überprüfen möchten, ob eine Datei vorhanden ist, die keine Zweigvorlage ist (die so definiert ist, dass sie nicht funktioniert), erstellen Sie einen TwigExtension-Dienst und fügen Sie dem Zweig die Funktion file_exists () hinzu:

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';
    }
}
?>

Registrieren Sie Ihren Dienst:

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 }

Jetzt können Sie file_exists () in einer Zweigvorlage verwenden.

Einige template.twig:

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

BEARBEITEN, um Ihren Kommentar zu beantworten:

Um file_exists () zu verwenden, müssen Sie den absoluten Pfad der Datei angeben, sodass Sie den absoluten Pfad des Webverzeichnisses benötigen. Geben Sie dazu den Zugriff auf den Webpfad in Ihrer Zweigvorlagen-App/config/config.yml:

# ...

twig:
    globals:
        web_path: %web_path%

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

Jetzt können Sie den vollständigen physischen Pfad zu der Datei in einer Zweigvorlage abrufen:

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

So können Sie überprüfen, ob die Datei vorhanden ist:

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

Ich habe eine Twig-Funktion erstellt, die eine Erweiterung der Antworten ist, die ich zu diesem Thema gefunden habe. Meine asset_if -Funktion verwendet zwei Parameter: Der erste ist der Pfad für das anzuzeigende Asset. Der zweite Parameter ist das Fallback-Asset, wenn das erste Asset nicht vorhanden ist.

Erstellen Sie Ihre Erweiterungsdatei:

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';
    }
}

Registrieren Sie Ihren Dienst (app/config/config.yml oder 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 }

Verwenden Sie es jetzt in Ihren Vorlagen wie folgt:

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

Ich hatte das gleiche Problem wie Tomek. Ich habe die Lösung von Sybio verwendet und folgende Änderungen vorgenommen:

  1. app/config.yml => füge "/" am Ende von web_path hinzu

    parameters:
        web_path: %kernel.root_dir%/../web/
    
  2. Rufe file_exists ohne "asset" auf:

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

Hoffe das hilft.

3
Tobias

Als Verbesserung der Antwort von Sybio gab es für meine Version keine Twig_simple_function, und für externe Bilder funktioniert hier beispielsweise nichts. Meine Dateierweiterungsdatei sieht also so aus:

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;
}
0
Mr Sorbose

Hier ist meine Lösung mit SF4, Autowire und Autokonfiguration:

namespace App\Twig;

use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
use Symfony\Component\Filesystem\Filesystem;

class FileExistsExtension extends AbstractExtension
{
    private $fileSystem;
    private $projectDir;

    public function __construct(Filesystem $fileSystem, string $projectDir)
    {
        $this->fileSystem = $fileSystem;
        $this->projectDir = $projectDir;
    }

    public function getFunctions(): array
    {
        return [
            new TwigFunction('file_exists', [$this, 'fileExists']),
        ];
    }

    /**
     * @param string An absolute or relative to public folder path
     * 
     * @return bool True if file exists, false otherwise
     */
    public function fileExists(string $path): bool
    {
        if (!$this->fileSystem->isAbsolutePath($path)) {
            $path = "{$this->projectDir}/public/{$path}";
        }

        return $this->fileSystem->exists($path);
    }
}

In services.yaml:

services:
    App\Twig\FileExistsExtension:
        $projectDir: '%kernel.project_dir%'

In Vorlagen:

# Absolute path
{% if file_exists('/tmp') %}
# Relative to public folder path
{% if file_exists('tmp') %}

Ich bin neu bei Symfony, daher sind alle Kommentare willkommen!

Da es sich bei der ersten Frage um eine Frage zu Symfony 2 handelt, ist meine Antwort möglicherweise nicht relevant. Besser, ich stelle eine neue Frage und beantworte sie selbst.

0
jo66

Fügen Sie einfach einen kleinen Kommentar zum Beitrag von Sybio hinzu:

Die Twig_Function_Function-Klasse ist seit Version 1.12 veraltet und wird in 2.0 entfernt. Verwenden Sie stattdessen Twig_SimpleFunction.

Wir müssen die Klasse Twig_Function_Function durch Twig_SimpleFunction ändern:

<?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';
    }
}

Der Rest des Codes funktioniert immer noch genauso wie Sybio.

0
Daniel Guerrero