Twigテンプレートにループがあり、複数の値を返します。最も重要なのは、私のエントリのIDです。フレームワークもテンプレートエンジンも使用しなかったときは、単にfile_exists()
ループ内で使用していました。今、私はTwigでそれを行う方法を見つけることができないようです。
ユーザーのアバターをヘッダーに表示するときfile_exists()
はコントローラーで使用しますが、ループがないので表示します。
Twigで試しdefined
ましたが、役に立ちません。何か案は?
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テンプレートapp / config/config.ymlのWebパスにアクセスできます。
# ...
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')) %}
このトピックで見つけた回答の拡張であるTwig関数を作成しました。私のasset_if
関数は2つのパラメーターを取ります。最初のパラメーターは、アセットを表示するためのパスです。最初のアセットが存在しない場合、2番目のパラメーターはフォールバックアセットです。
拡張ファイルを作成します。
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') }}" />
私はトメックと同じ問題を抱えていました。私はSybioのソリューションを使用し、次の変更を加えました。
app / config.yml=>web_pathの最後に「/」を追加します
parameters:
web_path: %kernel.root_dir%/../web/
「アセット」なしでfile_existsを呼び出します:
{% if file_exists(web_path ~ 'img/games/'~item.getGame.id~'.jpg') %}
お役に立てれば。
SF4、autowire、autoconfigureを使用した私の解決策は次のとおりです。
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を初めて使用するので、すべてのコメントを歓迎します。
また、最初の質問はSymfony 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が言ったとおりに機能します。
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;
}