Symfony2 dynamic assetic in twig template - symfony

I'm trying show image using assetic (symfony2, twig). URL address of image depends on the bundle.
{% image '#'{{ bundleName }}'/Resources/public/images/logo.png' %}
<img src="{{ asset_url }}" />
{% endimage %}
But it does not work.

You need to use the concatenation operator (~) to combine expressions inside twig tags:
{% image '#' ~ bundleName ~ '/Resources/public/images/logo.png' %}

I found a workaround for this. My situation is that I have images stored in a subdirectory under Resources/images. I wanted them there, rather than the web directory, as they will only be used temporarily and I want to just delete the subdirectory when they are no longer needed rather than having to delete images from various subdirectories. So, I couldn't use the asset() function (since the images were in the bundle) and assetic doesn't seem to support dynamic images.
I needed to display one of 2 banner images based on certain criteria. I wound up creating a twig template that would generate each image using assetic (2 images, so 2 templates).
<a href="{{ vm.bannerLinkUrl }}">
{% image '#MyBundle/Resources/public/images/path/to/image/banner.jpg' %}
<img src="{{ asset_url }}">
{% endimage %}
</a>
I created a 'banner' action in my Home controller to render the templates.
public function bannerAction()
{
/* code to load data into a view model object called $vm */
$template = $this->render(
"MyBundle:Home:path/to/banner-template-subdir/{$vm->bannerType}-banner.html.twig",
['vm' => $vm]
);
return $template;
}
Finally, I used the render function to generate the correct banner from the main page template.
<div class='banner'>
{{ render(controller("MyBundle:Home:banner")) }}
</div>

Related

Display images in twig using asset in Symfony 3

i have a list of objects which has an image as an attribute(name of the image as a string) , i am looping this list in twig and i try to display the image in an img html tag which takes it's source of image through a symfony 'asset' path .
this the twig part of code :
{% for offre in listeoffres %}
<li>
<img src="{{asset('images/')}} {{ offre.nomImage }}" alt="">
</li>
<li>
{{ offre.titre }}
</li>
{% endfor %}
Notes :
The database contains correct image names and the images already
exist in the correct folder (web/images)
The '{{ offre.nomImage }}' displays correctly the image name that
it's in the database (with the extension)
When i display {{asset('images/')}} {{ offre.nomImage }} it shows:
/myproject/web/images/ image.jpg
While your solution works, Tthe correct way to use the asset function would be to pass the full path of the image to the function call:
{{ asset('images/' ~ offre.nomImage) }}
I have solved it. The problem was the space between the asset and the image name.So the image source should have been like this :
{{asset('images/')}}{{ offre.nomImage}}

Loop over OneToMany - ManyToOne association

I have the tables as follows:
structure -> OneToMany -> media
media -> ManyToOne -> typeMedia
Browsing structure must enter the media for every type.
For example:
Photo:
img, img, img, img ..
Video:
video, video, video ...
...
I tried in every way, a for loop inside another for loop, but typeMedia (photo, video ..) are duplicated forever..
Here the code, but it is wrong
{% for media in structure.media %}
{% for type in media.typeMedia.media %}
<h3>{{ type.typeMedia.name }}</h3>
<hr/>
<img src="{{ type.webPath | imagine_filter('thumb', true) }}" />
{% endfor %}
{% endfor %}
How can I fix?
I need to change the database structure?
Firstly, I am guessing that in your twig code type.webPath that should be media.webPath? As it doesn't make sense for webPath to be an attribute of the media type?
The database structure is fine. However, you cannot directly follow the relationship typeMedia.media to get the results for a single structure. The typeMedia.media relationship will always give you all media of that type (for all structures), regardless of how you navigated to the typeMedia. Furthermore, as long as your outer loop is iterating over a set of media, it is only possible to output by mediaType from twig if that set of media is already ordered by mediaType. This is not the case by default when using structure.media.
There are various ways you could do this. One way would be to add a method to your Structure entity class to get the media by type. The advantage of this approach is that it enables you to get the media by type for a structure from anywhere in your code - repository, service, controller or twig. For example:
In your Structure entity class:
public function getMediaByTypeName()
{
$mediaByType = array();
foreach ($this->media as $aMedia)
{
$typeName = $aMedia->getTypeMedia()->getName();
if (!array_key_exists($typeName, $mediaByType)) $mediaByType[$typeName] = array();
$mediaByType[$typeName][] = $aMedia;
}
return $mediaByType;
}
In your twig:
{% for typeName, media in structure.mediaByTypeName %}
<h3>{{ typeName }}</h3>
<hr/>
{% for aMedia in media %}
<img src="{{ aMedia.webPath | imagine_filter('thumb', true) }}" />
{% endfor %}
{% endfor %}

What is the difference between 'url' and 'path' in symfony2.3

The document said
{# src/Acme/ArticleBundle/Resources/views/Article/recentList.html.twig #}
{% for article in articles %}
<a href="{{ path('article_show', {'slug': article.slug}) }}">
{{ article.title }}
</a>
{% endfor %}
also, can use 'url' like this:
Home
it confused me what is the difference between using 'url' and 'path'?
They are very similar.
path()
Generates a relative/absolute path :
path('contact') will generate /contact
url()
Generates a scheme-relative/absolute url, ie domain + path
url('contact') will generate http://example.org/contact
The url() style is useful when using cross-domain ajax or generating emails, because the hostname won't be the same.
Take a look at the code https://github.com/symfony/symfony/blob/master/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php for more information
url Twig function generates absolute path
path Twig function generates / related url
Example we have http://sf2sandbox.local with AcmeDemoBundle
{{ path('_welcome') }} produce /
{{ url('_welcome') }} produce http://sf2sandbox.local/

Extending twig for generate html code

I have to generate something like star rating and I have to generate some html for styling ect.
<div class="star on"><i>*</i></div>
<div class="star on"><i>*</i></div>
<div class="star on"><i>*</i></div>
<div class="star"><i></i></div>
<div class="star"><i></i></div>
I want to render using a twig function passing active stars parameters.
{{ stars(4) }}
Is correct use twig functions for generate html code?
Or maybe should I use {% include ... %}
No need in overengineering for such simple task.
If you generate your array in Controller, then it could look like this:
$stars = array(
true,
true,
true,
false,
false,
);
Then you could render your HTML in Twig:
{% for star in stars %}
<div class="star{{ star ? ' on' }}"<i>{{ star ? '*' }}</i></div>
{% endfor %}
In case if you would like to operate with Twig only, I recommend you to use macro:
{% macro stars(stars, total) %}
{% for item in 1..total %}
{{ item }}<br>
{% if item <= stars %}
<div class="star on"><i>*</i></div>
{% else %}
<div class="star"><i></i></div>
{% endif %}
{% endfor %}
{% endmacro %}
If you've defined your macro in the same template, you should call it via _self, if in another file - just like a function, but not forget to import your file into needed twig. See chapter about macros (linked above).
Following call will produce HTML structure that you described in your question:
{{ _self.stars(3,5) }}
See the Extending Twig section of its docs. According to the table in the first section on that page, using functions for content generation is natural. I create a lot of Twig functions and I suggest you create one to solve your problem.
BTW, your function can render a separate template with HTML code — do not generate the HTML code right in your Twig function's PHP code. To render a separate template from your Twig function, inject the service_container service into it, get the templating service and call the render() method on it:
return $this->container->get('templating')->render($pathToYourCustomTemplate);
Usually, it's best to inject the needed services individually, but if you inject the templating service instead of service_container, you'll get a cyclic dependencies problem. That's why injecting the whole container into Twig extensions is a reasonable exception.

symfony2 - twig - how to render a twig template from inside a twig template

I have a xxx.html.twig file which shows a page, but when I want to refresh the page with different data and just update it with new data, I have a select and a submit button for it.
The thing is that I don't know how do I call an action in the controller which I pass parameters to from my twig and call for new data and then I render the same twig template again with new parameters.
How do I do so?
Here are a few different ways:
{{ render(app.request.baseUrl ~ '/helper/test', {"hostid2": hostid } ) }}
or
{% include 'MyCoreBundle:Helper:test.html.twig' with {"hostid2": hostid } only %}
or
{% render controller("MyCoreBundle:Helper:test", {'hostid2': hostid}) %}
Symfony 2.1:
{% render 'YourBundle:YourController:yourAction' with {'var': value} %}
Symfony 2.6+:
{{ render(controller('YourBundle:YourController:yourAction', {'var': value})) }}
And, of course, read the documentation.
I think some parts are depricated here.
To make the include work in latest Symfony 3.1.10, I solved it like this:
{% extends 'base.html.twig' %}
{% block body %}
{{ include('AppBundle:Default:inner_content.html.twig') }}
{% endblock %}
Note: include() with parentheses.
Then all the variables are included from the parent template. If you like to restrict some variables in the child template, you use with ... only (look over)

Resources