assume you are in Twig template and want to indicate if you are on a controller with any action.
The simple process you can check a single route is
{% if app.request.attributes.get('_route') == 'app_user_list' %}
// code...
{% endif %}
But I need something with a wildcard to determine if the action is under current controller like 'app_user_*' to match also 'app_user_add' or 'app_user_delete'. It is nonsence to if-else all possible routes.
Any thoughts?
Thanks!
You can use the slice Twig filter, from the doc:
The slice filter works as the array_slice PHP function for arrays and
mb_substr for strings with a fallback to substr.
So you can archive as example of matching a group of routing with the prefix of app_user_ (app_user_add, app_user_delete, etc):
{% if app.request.attributes.get('_route')|slice(0,9) == 'app_user_' %}
// code...
{% endif %}
Hope this help
Related
Inside Twig file I have this code:
{% set player = app.security.getToken().getUser().getPlayer() %}
{% if player.getSelectedCharacter() is not null %}
{% set character = player.getSelectedCharacter() %}
{% .... %}
{% endif %}
But at now, app.security is deprecated. So I want to change this. I can obtain user token inside my controller and send it to the Twig. But I prefer to get it directly via Twig.
How I can do this?
As you said and mentioned in the documentation.
The app.security global is deprecated as of 2.6. The user is already
available as app.user and is_granted() is registered as function.
I think you can just try something like this in your view.
app.user.getPlayer()
I have a layout that includes some chuck of code form a controller called "Layout"
In the header section I have:
{% block accessinfo %} {% render "/layout/accessinfo" %} {% endblock %}
It works pretty fine, the view file content is:
{% extends '::layout.html.twig' %}
{% block body %}
{% if( is_logged == 0 ) %}
Welcome, access your <a id="accessAccount" title="Access your account">here</a>.
{% else %}
Hi, <b><em> {{ is_logged_user_name }}</em></b>, <a id="doLogout" href="javascript:void;">(Logout)</a>.
<i class="icon-user"></i> Your Account
{% endif %}
{% endblock %}
As one can figure out, path('account/manage') points to the Route named 'account/manage', but it's not returning the fully qualified URL to my project.
It returns:
http://localhost.project/account/manage
where it should be:
http://localhost.project/web/app_dev.php/account/manage
NOTE: I have path() all around my template files and they work like a charm.
IMPORTANT: I found out that when I call REQUEST URI inside the action method:
$this->get('request')->server->get('REQUEST_URI')
PHP will return the URL called by the render, in this case is:
/layout/accessinfo
Perhaps I'm not fully understanding your issue but it seems like you missunderstood the use of the path() and render() functions.
First of all if you like to render a controller and you follow the documentation here you would do it like this...
{{ render(controller('AcmeArticleBundle:Article:recentArticles') }}
{# with some parameters #}
{{ render(controller('AcmeArticleBundle:Article:recentArticles', {
'max': 3
})) }}
This assumes you're using Symfony >= 2.2. This follows the bundle:controller:action pattern, which is called Controller Naming Pattern
For a normal use of the path() function you would always use the name of the route and not a hardcoded URL (as it seems like you're passing in URLs and not route names?)
Let's say your route is called accountmanager, your routing.yml should look like this example
# app/config/routing.yml
accountmanager:
path: /account/manage
defaults: { _controller:YourBundleName:YourControllerName:ControllerAction }
And with that in your routing.yml in twig the use of path() is simply achieved by writing {{ path('accountmanager') }}
See the documentation on this topic. Using the name of the route and not a URL pattern ensures that you're getting to the right page which also includes your environment settings (like app_dev.php for your dev environment)
In Symfony / Twig, I could use tags by using percentages in my translated block. For example:
Hello {{nickname}}
would become
{% trans %}Hello %nickname%{% endtrans %}
This works as expected. The array with placeholders that I pass to Twig, are automatically mapped to %placeHolder%. No extra work involved. So this works with my PHP array from the controller being:
Array('nickname' => 'rolandow')
When I want to use the nickname inside the translation block, all I have to do is surround it with percentages %. Unfortunately, this doesn't seem to work when I pass it to trans.
Now I would like to translate a whole block of text, using tags. I can't figure out how I can use the tags in my translation. So, my twig would look something like this:
{{ say.hello|trans }}
And my translation snippet
<trans-unit id="1">
<source>say.hello</source>
<target>Hello %nickName%, how are you doing today? lots-of-text-here</target>
</trans-unit>
I got it working by using this in my template, but it feels like doing things twice. I now need to put the array of placeholder into the trans function again. For example:
{{ say.hello|trans('%nickName%' : nickName) }}
If I want to use other tags that are given to twig in my controller, I need to pass them to the translator as well. Can't I just pass the complete array somehow?
{{ say.hello|trans('%nickname%': 'rolandow') }}
There are several questions here so let's cover them.
1) Twig's behaviour is not like a Doctrine query, where each parameter must be bounded. You can pass an array that contains unused parameters to trans, so if you don't want to specify {'key': 'value', 'key2': 'value2'...} to the filter, just pass the entire array (example: | trans(array)). That's #Luke point.
2) You can translate block of texts using several ways, the most simple is {% set %}. The {% set %} tag can be used two ways :
{% set var = expression %} or {% set var1, var2 = expression1, expression2 %} is the most known and used way: you just put some value inside one or several variables.
{% set var %} block of text {% endset %} allow you to set an entire block of text inside that variable. This is useful if you want to put that block into a filter (such as, escape, or in your case, trans).
So to translate a block of text, you'll do something like:
{% set variable %}
block to translate %placeholder%
{% endset %}
{{ variable | trans(array) }}
Anyway, I don't see any interest of translating a whole block in one time : we use | trans generally after a property (such as say.hello), and I can't imagine your xlf/yml translation file with such a design. If you want to use the translator just to fulfill placeholders, just use Twig as it is written for that job :-)
3) About replacing placeholder by %placeholder% in your parameters array's keys : the point of Twig is: put what you want as placeholder. In such a way, if your translated sentence contains several %, you can use $something$, #something# or even something as placeholder.
If your array keys does not contain those %, you need to add them, you don't have any choice. If you really want to do it on a Twig file, you can create a macro that will do the job for you, and put it in a file you import in your base layout.
Something like :
{% macro trans_pct(property, params) %}
{% set newParams = [] }
{% if params %}
{% for key, value in params %}
{% set newParams['%' ~ key ~ '%'] = value %}
{% endfor %}
{% endif %}
{{ property | trans(newParams) }}
{% endmacro %}
And then use it with {{ _self.trans_pct('hello.say', array) | trim }}.
Notes :
_self is the template where is stored the macro (see the documentation for more details).
trim is used because I wrote the macro with indentation and line breaks (that's cleaner to read). Those spaces are, by default, printed.
imaging that i have a object and which can be called in a twig template like this:
{{ object1.object2.object3.property3A }}
well, it will show me the content if we use php to write is :
$object1->getObject2()->getObject3()->getProperty3A();
My question is if i have a string ,
$refString="object1.object2.object3.property3A";
and then it is passed to twig, how could i get the property3A? For my experience, we can do this in php like this:
$refString="object1->getObject2()->getObject3()->getProperty3A()";
echo $$refString;
But i do not know how to make it work in twig.
I didn't tested this, but i think it schould do the trick.
{#
recursively reading attributes from an object
! object1 must be available !
theValue is the value of property3A
#}
{% for key in "object1.object2.object3.property3A"|split('.') %}
{% if not loop.first %}{# skip the 'object1' part #}
{% set theValue = attribute(theValue|default(object1), key) %}
{% endif %}
{% endfor %}
I don't think there is a "shortcut" to do this in twig. If you can't find a simple way to do this, you can write you own extension, that would convert a STRING_TYPE to a VAR_TYPE.
Twig internals might put you on the right track. This is an example of what is feasable with twig extension and might inspire you.
I ran into a similar situation. This answer will only work if the object you need is available to the template and you know the name of it with a string.
In this case, you can access the object using Twig's Global Variable _context:
{% set object1 = _context['object1'] %}
And then access the methods and variables of the object as normal:
{{ object1.object2.object3.property3A }}
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)