Let's say I use Webpack, and builded a Css file properly at "build/theme/mail.css".
I wants to include the CONTENT of this File into my twig.
{% include "https://mysite.io/build/theme/mail.css" %} doesn't work saying it can't find the file ( but it exist).
I don't want that because im using an inliner, and absolutly need the #CONTENT in my twig.
Tried the File get Content, didn't works. Found a solution:
twig:
paths:
'%kernel.project_dir%/public': public
Add a twig path to public directory
and then use :
{% apply inline_css(source(theme_asset('#public/build/theme/email.css'))) %}
and add a webpackconfig to build the scss file into public/build
Thanks you all.
You could create custom twig extension and use file_get_contents.
Extension:
<?php
namespace App\Twig;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
class GetPublicFileContentExtension extends AbstractExtension
{
/** #var string */
private $publicPath;
public function __construct(ParameterBagInterface $parameterBag)
{
$this->publicPath = $parameterBag->get('kernel.project_dir') . '/public/';
}
public function getFunctions(): array
{
return [
new TwigFunction('get_public_file_content', [$this, 'getPublicFileContent']),
];
}
public function getPublicFileContent(string $filepath)
{
return file_get_contents($this->publicPath . $filepath);
}
}
Twig:
{{ get_public_file_content('build/theme/mail.css') }}
Related
I am looking to use substr_count in Twig, does anything exist already? I want to perform something like this;
<?php
$text = 'This is a test';
echo strlen($text); // 14
echo substr_count($text, 'is'); // 2
I can do an extension but it seems this might be something built in already that I have missed.
How about this?
{%set count = text|split('is')|length-1 %}
This doesn't exist in the list of Twig functions or filters.
You'll have to write your own custom function/filter or try a package (note; I've never used this package so can't comment on it, but was on the first page of Google results).
I went for an extension
namespace AppBundle\Twig;
class SubStrCountExtension extends \Twig_Extension
{
public function getFunctions()
{
return array(
new \Twig_SimpleFunction('substr_count', array($this, 'substr_count')),
);
}
public function getName()
{
return 'substr_count_extension';
}
public function substr_count($str, $char)
{
return substr_count($str, $char);
}
}
And in services.yml
app.twig_extension.substr_count_extension:
class: AppBundle\Twig\SubStrCountExtension
tags:
- { name: twig.extension }
I use solution in Symfony 3.2.8 but in the description does not say this block of code should is inside : services
If you does not make show this error:
There is no extension able to load the configuration for .....
This code should is inside services this is correct:
services:
app.twig_extension.substr_count_extension:
class: AppBundle\Twig\SubStrCountExtension
tags:
- { name: twig.extension }
Finally, the correct use in twig is:
tu placa es: {{substr_count(datos.picoyplaca,4)}}
Regards
I have a function in my controller like this:
<?php
namespace GradeBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
use GradeBundle\Entity\User;
use GradeBundle\Entity\SchoolClass;
class MainController extends Controller
{
/**
* #Route("/", name="index_page")
*/
public function index()
{
return $this->render('GradeBundle:Default:index.html.twig');
}
It renders the twig template correctly. However when I use other function:
/**
* #Route("/adminNew", name="add_admin")
*/
public function addAdmin()
{
$session = new Session();
if($session->get('loggedIn') == null)
return $this->redirect($this->generateUrl('index_page'));
else
return $this->render('GradeBundle:Add:newAdmin.html.twig');
}
I have the following error:
Unable to find template "GradeBundle:Default:index.twig.html".
Does anybody have any idea what might be wrong?
It's a typo somewhere you call template:
GradeBundle:Default:index.twig.html
But you have only GradeBundle:Default:index.html.twig template.
Note the difference: html.twig twig.html
I suspect that you extend it in GradeBundle:Add:newAdmin.html.twig by:
{% extends 'GradeBundle:Default:index.twig.html' %}
but should be:
{% extends 'GradeBundle:Default:index.html.twig' %}
Have you made sure to use the correct namespace for the Controller you're using? And are you including the correct files? Also I'm not sure I understand the question correctly - are you saying if you add another function with a different twig file render, the first one no longer renders? Could I see your class names and the namespaces / use statements?
Usually in these instances, it's that the templates are in the wrong place or the correct file is not included in order to find it.
Michael
what i Need :
Split the string.
i Need first Character from the String.
if the string certain character limit i like to show only first name not by(...).
ex: ankit mishra pandit aggarwaal.
- so i just want only ankit.
- if its is ankit mishra its ok.
* otherwise show Full Name.
Here is the twig code:
{%if item.metadata.name |length < 20 %}
{% set foo = item.metadata.name|split(',') %}
{{ foo[0] }}
{%else%}{{WordLimit(item.metadata.name,20,10)}} ..
{%endif%}
output im getting :
Deepak Singh.
i have refer Source: Twig Split filter http://twig.sensiolabs.org/doc/filters/split.html.
where i have done wrong.
I think the best solution is to write a twig extension.
See http://symfony.com/doc/current/cookbook/templating/twig_extension.html
class AcmeExtension extends \Twig_Extension
{
public function getFilters()
{
return array(
new \Twig_SimpleFilter('first_word', array($this, 'first_word')),
);
}
public function first_word($word)
{
$words = explode(' ', $word);
$first_word = $words[0];
...
return $first_word;
}
public function getName()
{
return 'acme_extension';
}
}
And if your twig file :
{{item.metadata.name | first_word }}
As i can see Assetic made some progress on CacheBusting:
https://github.com/kriswallsmith/assetic#cache-busting
But i dont really understand how i should use this.
Can this be used from within twig:
{% stylesheets 'bundles/mybundle/css/fonts.css'
'bundles/mybundle/css/style.css'
'bundles/mybundle/css/screen.css'
filter='cssrewrite'
%}
<link rel="stylesheet" type="text/css" href="{{ asset_url }}" />
{% endstylesheets %}
And with the usual assetic:dump command?
Where would i have to hook the CacheBustingWorker in?
Cache buster is now part of symfony/AsseticBundle (Version >= 2.5.0).
Change AsseticBundle version in composer.json like that:
"symfony/assetic-bundle": "2.5.0",
And activate cache busting for assets in your config.yml file like that
assetic:
workers:
cache_busting: ~
My JS files are now looking like that:
web/bundles/js/projectname-876f9ee.js
See https://github.com/symfony/AsseticBundle/pull/119#issuecomment-28877145
I have been recently looking how to do the same.
The solution I came up with was to override Symfony's AssetFactory with my own class and add the CacheBustingWorker in its constructor. Basically you create a file like the following:
<?php
namespace YourSite\YourBundle\Factory;
use Symfony\Bundle\AsseticBundle\Factory\AssetFactory as BaseAssetFactory;
use Assetic\Factory\Worker\CacheBustingWorker;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpKernel\KernelInterface;
class AssetFactory extends BaseAssetFactory
{
public function __construct(KernelInterface $kernel, ContainerInterface $container, ParameterBagInterface $parameterBag, $baseDir, $debug = false)
{
parent::__construct($kernel, $container, $parameterBag, $baseDir, $debug);
// Add CacheBustingWorker
$this->addWorker(new CacheBustingWorker(CacheBustingWorker::STRATEGY_CONTENT));
}
}
and then change the assetic.asset_factory.class parameter to point to this new class in your config. In my case I added the following to config.yml:
parameters:
assetic.asset_factory.class: YourSite\YourBundle\Factory\AssetFactory
With the current implementation of assetic, I needed to update your code to the following to get this to work. Also note if you are using xdebug, you must up the max nesting level - xdebug.max_nesting_level = 200 to more than 100.
<?php
namespace YourSite\YourBundle\Factory;
use Symfony\Bundle\AsseticBundle\Factory\AssetFactory as BaseAssetFactory;
use Assetic\Factory\LazyAssetManager;
use Assetic\Factory\Worker\CacheBustingWorker;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpKernel\KernelInterface;
class AssetFactory extends BaseAssetFactory
{
public function __construct(KernelInterface $kernel, ContainerInterface $container, ParameterBagInterface $parameterBag, $baseDir, $debug = false)
{
parent::__construct($kernel, $container, $parameterBag, $baseDir, $debug);
// Add CacheBustingWorker
$this->addWorker(new CacheBustingWorker(new LazyAssetManager(new BaseAssetFactory($kernel, $container, $parameterBag, $baseDir, $debug))));
}
}
Hope this helps someone
As the assetic code changed again, there is no need of Stategy on LazyAssetManager on the master branch.
Do not forget to change your composer.json file:
{
"kriswallsmith/assetic": "dev-master#dev",
"symfony/assetic-bundle": "dev-master#dev"
}
You now just need this:
namespace YourSite\YourBundle\Factory;
use Symfony\Bundle\AsseticBundle\Factory\AssetFactory as BaseAssetFactory;
use Assetic\Factory\Worker\CacheBustingWorker;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpKernel\KernelInterface;
class AssetFactory extends BaseAssetFactory
{
public function __construct(
KernelInterface $kernel,
ContainerInterface $container,
ParameterBagInterface $parameterBag,
$baseDir,
$debug = false
) {
parent::__construct($kernel, $container, $parameterBag, $baseDir, $debug);
// Add CacheBustingWorker
$this->addWorker(new CacheBustingWorker());
}
}
Do not forget to php app/console cache:clear -e prod before dumping assets one time to avoid standard filenames to be generated.
assetic:
workers:
cache_busting: ~
Is the answer.
I have created two functions in controller of Symfony as follow:
first is newAction
public function newAction()
{
return $this->render('AcmeTaskBundle:Default:index.html.twig');
}
then subAction
public function subAction()
{
echo "hello";
}
I want to use some data from index.html.twig into subAction function.
How I can do that?
All you need is to use
$content = $this->renderView('AcmeTaskBundle:Default:index.html.twig')
This will render contents of template in variable
http://symfony.com/doc/current/book/controller.html#rendering-templates
EDIT according to comment
If you need to render only part of template - then you should refactor your templates.
Exclude that part of code from your index.html.twig into separate template file and include it in index.html.twig:
...
{% include 'AcmeTaskBundle:Default:subpage.html.twig' %}
...
And then in your subAction() call:
$content = $this->renderView('AcmeTaskBundle:Default:subpage.html.twig')