Symfony2 - 检查文件是否存在

时间:2013-01-09 09:27:38

标签: symfony twig

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

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

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

6 个答案:

答案 0 :(得分:31)

如果您想要检查是否存在不是twig模板的文件(如此定义无效),请创建一个TwigExtension服务并将file_exists()函数添加到twig:

的src /的appbundle /枝条/扩展/ 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 /资源/配置/ 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 应用程序/配置/ 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')) %}

答案 1 :(得分:11)

我创建了一个Twig函数,它是我在这个主题上找到的答案的扩展。我的asset_if函数有两个参数:第一个是资产显示的路径。如果第一个资产不存在,则第二个参数是后备资产。

创建扩展程序文件:

的src / Showdates / FrontendBundle /枝条/扩展/ 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') }}" />

答案 2 :(得分:3)

我和Tomek有同样的问题。我使用了Sybio的解决方案并进行了以下更改:

  1. app / config.yml =&gt;在web_path

    的末尾添加“/”
    parameters:
        web_path: %kernel.root_dir%/../web/
    
  2. 调用没有“资产”的file_exists:

    {% if file_exists(web_path ~ 'img/games/'~item.getGame.id~'.jpg') %}
    
  3. 希望这有帮助。

答案 3 :(得分:0)

只需对Sybio的贡献添加一些评论:

  

从版本1.12开始,不推荐使用Twig_Function_Function类   将在2.0中删除。请改用Twig_SimpleFunction。

我们必须通过Twig_SimpleFunction更改类Twig_Function_Function:

<?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完全一样。

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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

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

在services.yaml中:

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

在模板中:

// @flow

import React, {Component, Fragment} from 'react';
import {ErrorMessage, Field} from 'formik';
import IntlTelInput from 'react-intl-tel-input';

export default class MobileField extends Component {
  formatPhoneNumberOutput(
    isValid: boolean,
    newNumber: string,
    countryData: Object,
    fullNumber: string,
    isExtension: boolean
  ) {
    if (isValid && fullNumber) {
      return fullNumber.replace(/(\s|-)/g, '');
    }
    return 'invalid_phone_number'; // caught by validator
  }

  render() {
    return (
      <Field
        name={name}
        render={({field, form: {errors, isSubmitting, touched, setFieldTouched, setFieldValue}}) => {
          return (
            <Fragment>
              <IntlTelInput
                defaultCountry="fr"
                defaultValue={field.value}
                disabled={isSubmitting}
                fieldId={name}
                fieldName={name}
                onPhoneNumberBlur={() => {
                  setFieldTouched(name, true);
                }}
                onPhoneNumberChange={(...args) => {
                  setFieldValue(name, this.formatPhoneNumberOutput(...args));
                }}
                preferredCountries={['fr', 'gb', 'es', 'be', 'de']}
              />
              <ErrorMessage name={name} render={msg => <p>{msg}</p>} />
            </Fragment>
          );
        }}
      />
    );
  }
}

我是Symfony的新手,欢迎大家发表评论!

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