Using locateResource inside Twig Extension - php

I wish to use the following inside of a Twig Extension
$kernel = $container->getService('kernel');
$path = $kernel->locateResource('#AdmeDemoBundle/path/to/file/Foo.png');
but this involved passing in the Kernel, which is bad. Plus I could not get it to work anyway when trying this method.
How can I access a resources path within a Twig Extension?
The Extension is already a Service. I can use Assetic to give me the URL, but I really want the path.

I had a similar need: i needed to pass to the filter the url of an image to display it in a for loop and build a string.
I passed the URL directly to the filter in this way:
{% image '#AppBundle/Resources/public/images/my_asset.png' %}
{% set resolved_asset_url = asset_url %}
{% endimage %}
{{ my_var|filter_name(resolved_asset_url)|raw(html) }}
In this way the Twig template resolve the correct resource's URL, sets it as a variable, and then I pass it to the filter from inside the template itself, without having to deal with kernel or something else.

If you want just to serve a download, you should create a Route that accomplishes that task.
In this way, you'll call the locator inside the route, and a simple
{{ path('route_that_does_the_locator_thing') }}
will be fine.
If you need instead to include a file in your template (ex. CSS, JS..), you need to declare your file as an asset, maybe using Assetic.

Related

Get assets urls from assetic group in controller (not template) Symfony2

I wonder if how could I load an assetic group of assets from inside my controller.
my config.yml:
assetic:
assets:
systemassets:
inputs:
- 'bundles/belkapanel/js/*.js'
- 'bundles/belkapanel/router.js'
Using twig, the solution is very simple:
{% javascripts '#systemassets'%}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
it will resolve the path wildcard and generate an single .js file with the content of all files found inside "systemassets".
However, I want to get the generated .js file inside an controller. I know it is possible, but reading the symfony's assetic-bundle I only found AsseticHelper with "javascripts" method, but I don't know how to use it, I think it is used after the packagename and wildcards are resolved.
/** #var DynamicAsseticHelper $asseticDynamic */
$asseticDynamic = $this->get('assetic.helper.dynamic');
$assets = $asseticDynamic->javascripts('systemassets'); // Doesn't work!
I'm looking at AsseticTokenParser, I think it is the solution, am I right? can someone help me find the solution?
This should work:
$assets = $asseticDynamic->javascripts(array('#systemassets'));
See this documentation chapter for more details (check PHP version).

Is It Possible to Register or Publish Asset Files css,js from Bundle in Symfony 2

How to register js,css file to head tag from inside bundle automatically? so we don't need to add it manually to layout.
In zend framework there is HeadScript and InlineScript Helper, prepend or append method to do this. How about symfony2 ? is it possible too?
In zend framework we can register it like this from module bootstrap :
public function onBootstrap($e) {
$sm = $e->getApplication()->getServiceManager();
$headLink = $sm->get('viewhelpermanager')->get('headLink');
$headLink->appendStylesheet('/assets/MyModule/css/mystylesheet.css');
}
I mean, I want register it from e.g AcmeBlogBundle.php so we don't need to add manually to <head></head> in layout.
I'm not sure if this is what you are looking for, but check this out, this shows you how to include every js-file inside a directory, without listing them all manually.
You can't do it like in Zend. But you can define the appropriate block with js in base layout only once. And then from any template you can put anything you want into this block. Symfony implements a bit different logic than Zend does.
In your layout:
<head>
{% block custom_head_js %}
<some basic js files for all the pages>
{% endblock%}
</head>
In your templeate:
{% block custom_head_js
'#YourBundleNamespace/YourBundleName/Resources/public/js/your_js_filename.js'
%}
<script src="{{ asset_url }}"></script>
{% endblock %}
So, as I said it's not necessary to change base layout every time you want to add js into 'head' js files - you have to do it only once.

Symfony2 Twig Inject additional blocks

Is there a way with Symfony2 and Twig to always make files available which just contain blocks.
For example, if I wanted to make a block named 'cookie' always available in any template in my system, without having to always include or extend it in the template I'm using.
Any ideas?
Clarification
Say I have a generic block which can do something, like:
{% block myBlock %}
ABC Examples
{% endblock %}
I have a class which knows it wants to be rendered with this block. My template itself doesn't necessarily know this though.
{{ block(myObj.blockName) }}
I would then like to have it so my controller/services/etc. could register the file which contains that block, without my template actually needing to know about it directly (so I could have multiple files like that, each working with some common interface).
Similar to registering custom Twig functions with a TwigExtension. My template doesn't need to explicitly know it's there, it just has to be available at run-time.
Does that make sense?
To clarify a bit further, I'm essentially looking to do something just like how there are default Twig blocks for rendering Forms in Symfony2. I don't have to include the default form file every time, just when I want to change something.
I went digging around in the Symfony source code to try and find my answer. It looks like there isn't some fancy, neat way to embed it from a configuration file or controller directly, which is a bit disappointing, but not a huge deal.
So, to solve my situation, I'll be using the "use" keyword to include my block file in my base template, so it will then be available to everything else.
{# widget_blocks.html.twig #}
{# Widgets #}
{% block my_widget %}
ABC Cookies
{% endblock %}
{# base.html.twig #}
{% use widget_blocks.html.twig %}
{{ block(my_widget.block) }}
Not exactly what I wanted, but sufficiently close.
{% render 'MyMainBundle:Default:credits' with {'arg1': $myObj } %}
Thats what I say. What's the difference between the line above or
{{ block(myObj.blockName) }}
You can register a custom filter but as far as I know it returns only string value. http://twig.sensiolabs.org/doc/advanced.html#id2

How to pass an array from Symfony 2 controller to a TWIG template ?

I can`t pass an array from a symfony 2 controller to a TWIG template. I use this code in the controller:
$searchTerms['color'] = "Red";
return $this->render('TestBundle::search.html.twig',
array(
"searchTerms" => $searchTerms));
In the twig template, I am trying to access the variable like this:
{{ searchTerms['color'] }}
{{ searchTerms.color }}
Both output nothing, empty string, so it seems like array comes to template but its elements are empty.
What`s wrong?
Yes, this code works. The first thing to check is that your twig code is in the correct page (TestBundle::search.html.twig). This might sound silly but that happens sometimes...
If this is all good, I suggest that you try to debug within your template. Debugging is the most important thing. You will always have this kind of problem while programming, especially when you try something new. The better you are at debugging your code, the better you are as a programmer because there is no way you can get everything right the first time.
So, how can you debug?
To debug within your twig template, you can use the debug extension of twig. To activate the debug option, you will have to do a quick change in your config file. You can also read this thread if your lost.
You can debug any variable within your template like this:
<pre>
{% debug searchTerms %}
</pre>
This way, you can easily debug your variable and test what your problem is:
{% debug searchTerms['color'] %}
If you want to debug things quickly, I highly recommend that you use the LadyBugBundle. It is an awesome tool that will allow you to do something like that:
In your controller:
ladybug_dump($searchTerms);
In your TWIG template:
{{ searchTerms|ladybug_dump }}
Not that different from a classic var_dump option, but if you have long arrays or objects, ladybug will impress you. More importantly, in a controller, you will often have the need to stop the code at a certain point to avoid the page to load after your debug statement, this is fairly easy with ladybug:
ladybug_dump_die($searchTerms);
You can even ask ladybug to load the "debugged" variable into Symfony profiler with this simple statement.
$this->get('ladybug')->log($searchTerms);
You have now direct access of the variable from a tab of the Symfony2 profiler.
Ladybug can do a lot more, but for this, the doc is really good.
I think you must change template like this:
{% for item in searchTerms %}
{{ item.color }}<br/>
{% endfor %}
See official documentation: Creating and using Templates->embedding-controllers

Generate URL to external route with UrlGenerator

With Silex (the PHP micro framework), it's possible to give names to existing controllers, so that we can easily generate urls to them later. Example:
$app->get('/gallery', function () {...})
->bind('gallery');
// Later on, in a template
{{ path('gallery') }}
I think this is really useful and I can't live without it.
But is it possible to register a route to an external website ? Say I'd like to generate urls to a google search, kind of
{{ path('google', {'search':'symfony'}) }}
// Would render to http://google.com/search?q=symfony
I take any idea :) Thx for your help !
path() is a Twig Extension for routing. Routing is to route an incoming URL to a controller action.
You can, however, create your own twig extension if you want a helper to easily create those standard outgoing URLs.
Take a look at: http://symfony.com/doc/current/cookbook/templating/twig_extension.html
You could then create an extension that turns {{ google('search string') }} into a URL. Only the imagination is your boundary.

Categories