【问题标题】:Symfony2 - checking if file existsSymfony2 - 检查文件是否存在
【发布时间】:2012-12-23 07:24:00
【问题描述】:

我在 Twig 模板中有一个循环,它返回多个值。最重要的 - 我的条目的 ID。当我没有使用任何框架或模板引擎时,我在循环中只使用了file_exists()。现在,我似乎无法在 Twig 中找到方法。

当我在标题中显示用户头像时,我在控制器中使用file_exists(),但我这样做是因为我没有循环。

我在 Twig 中尝试了defined,但它对我没有帮助。有什么想法吗?

【问题讨论】:

    标签: symfony twig


    【解决方案1】:

    这是我的解决方案,使用 SF4、自动装配和自动配置:

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

    在 services.yaml 中:

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

    在模板中:

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

    我是 Symfony 的新手,所以欢迎每个 cmets!

    另外,由于最初的问题是关于 Symfony 2,也许我的答案不相关,我最好自己提出一个新问题和答案?

    【讨论】:

      【解决方案2】:

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

      其余的代码仍然和 Sybio 说的一样工作。

      【讨论】:

        【解决方案3】:

        改进 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;
        }
        

        【讨论】:

          【解决方案4】:

          如果你想检查一个不是 twig 模板的文件是否存在(这样定义的不能工作),创建一个 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 %}
          

          编辑回答您的评论:

          要使用 file_exists(),你需要指定文件的绝对路径,所以你需要 web 目录的绝对路径,这样做可以访问你的 twig 模板中的 webpath app/config/config.yml:

          # ...
          
          twig:
              globals:
                  web_path: %web_path%
          
          parameters:
              web_path: %kernel.root_dir%/../web
          

          现在您可以在 twig 模板中获取文件的完整物理路径:

          {# 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')) %}
          

          【讨论】:

          • 效果很好,但你能告诉我,我如何检查资产是否存在?
          • 我是这样想的: {% if file_exists(asset('images/logo.png')) %}Checked !{% endif %} 因为asset() 返回媒体的绝对路径所以它可以工作并检查正确的路径^^
          • 我是这么想的,但是{% if file_exists(asset('img/games/'~item.getGame.id~'.jpg')) %} 不起作用(我的意思是,即使文件在那里,它也会返回false)。
          • 我刚刚编辑了我的答案,我想我最后有解决方案检查!
          • 嗯,web_path 很好用,但还是看不到文件。
          【解决方案5】:

          我创建了一个 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.ymlsrc/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') }}" />
          

          【讨论】:

            【解决方案6】:

            我遇到了和 Tomek 一样的问题。我使用了 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') %}
              

            希望这会有所帮助。

            【讨论】:

            • 我想添加一个参数以在树枝模板中使用您需要将其添加到树枝配置中,如 here 所述
            猜你喜欢
            • 1970-01-01
            • 2013-05-22
            • 1970-01-01
            • 1970-01-01
            • 2021-12-25
            • 1970-01-01
            相关资源
            最近更新 更多