Get current route/path deliver _internal route - symfony

I'm rendering data from a CMS via Twigcode to a Controller and the Controller renders a twig template. I'd like to have the current route. I already tried to use:
// Controller
$request = $this->container->get('request');
$routeName = $request->get('_route');
// or Twigtemplate
{{ app.request.attributes.get('_route') }}
But the result is "_internal". How can I solve that problem?

You forgot the call to the Twig path function in your Twig template!
{{ path(app.request.attributes.get('_route')) }}
instead of
{{ app.request.attributes.get('_route') }}
Hope it helps!

Related

Passing twig code into a twig template and rendering it

So I have a twig template that's basically empty, and the application generates some twig code and passes this as a variable into a twig template, like this:
return $this->render('blank.html.twig', [
'twig' => $this->generateTwig()
]);
blank.html.twig looks like this:
{{ twig }}
But when the template is rendered it just has un-rendered twig code inside, like this:
{% extends 'base.html.twig' %} {% block content %} <h1>{{ 'app-name'|trans }}...
How do you render the injected twig code in this example?
Doing a file_put_contents('blank', $this->generateTwig()) works, but this defeats the purpose of using templates.
You can solve this two ways. Either you pre-render $this->generateTwig()'s output and inject (the HTML) into the blank.html.twig template (untested pseudo):
$template = $this->get('twig')->createTemplate($this->generateTwig());
$twig = $template->render();
return $this->render('blank.html.twig', [
'twig' => $twig,
]);
The downside of this approach is that you have to call {{ twig|raw }} in blank.html.twig, otherwise Twig will escape the HTML. Also: it feels a bit weird to pre-render a twig template before feeding it to Twig (again).
The other approach is that you load the template inside of your blank.html.twig template:
{{ include(template_from_string(twig)) }}
The template_from_string function is part of the StringLoaderExtension.
Docs here: https://twig.symfony.com/doc/3.x/recipes.html#loading-a-template-from-a-string
Edit: Thinking of it, a third approach could be even simpler if blank.html.twig is really just a file that outputs {{ twig }}:
$template = $this->get('twig')->createTemplate($this->generateTwig());
return $template->render();

Should I repack the fetched entity object before passing it to the twig template?

I'm using Symfony 4. I have a fetched object $user that has relationships with other entities. I have setup all the getter so I can get other information from that $user object.
$user = $em->getDoctrine()->getRepository(User::class)->find($id);
$usergroup = $user->getGroup()->getName();
What I'll do is to create a new object for repacking the information I needs from the $user object before passing it to the template.
# controller
$repack_user = new \stdClass();
$repack_user->id = $user->getId();
$user_friends = $user->getFrends();
$friends_gf = [];
foreach($user_friends as $friend) {
$friends_gf[] = $friend->getGirlfriend()->getName();
}
$repack_user->friends_gf = $friends_gf;
return $this->render("home.html.twig", ['user' => $repack_user]);
And then in the template, I unpacked it with similar procedures.
# twig template
{{ user.id }}
{% for gf in user.friends_gf %}
{{ gf }}
{% endfor %}
But since I can also call entity function inside twig, I can skip all the whole repacking in the controller and pass the $user object right into the template.
# skipped repack in controller
# twig template
{{ user.getID() }}
{% for friend in user.getfriends %}
{{ friend.getGirlfriend().getName() }}
{% endfor %}
The first way is kind of redundant because I have to do it twice. The second way is kind of hard to read. So which one is the more reasonable approach? What is the common practice for this?
Common practice is definitely to hand over your entity graph directly to the view.
Why do you think your second example is harder to read?
If you don't want those chained calls in the template you might want to consider adding another getter in your User entity. Something like:
public function getNamesOfFriendsGirlfriends()
{
$gfNames = [];
foreach($this->getFriends() as $friend) {
$gfNames[] = $friend->getGirlfriend()->getName();
}
return $gfNames;
}
And then call that in your template:
{% for gfName in user.namesOfFriendsGirlfriends %}
{{ gfName }}
{% endfor %}
And if you need many of these helpers and don't want to spoil your nice and clean entities you might want to consider wrapping them in a Decorator object before using it in the view layer.

Symfony2: How to get request parameter

I have a route:
professor_identity_edit:
path: /professor/{id}/identity
defaults: { _controller: FrontBundle:ProfessorIdentity:edit }
How can I get the parameter {id} in twig.html file ?
I already tried app.request.query.get('id') but with no success.
Not a good thing but you can still do. Normally you would pass the info to Twig from the controller like #Maerlyn pointed out.
Get route parameters in Twig.
{{ app.request.attributes.get('_route_params') }}
AND
Gets whole bundle name in Twig.
{{ app.request.attributes.get("_controller") }}
Get route name in Twig.
{{ app.request.attributes.get('_route') }}
I found the solution:
{{ app.request.attributes.get('_route_params')['id'] }}

Symfony2 - add flashbag message on entity operations

I'm working on a Symfony2.3.6 project, and it works good. I've made a backend side with a few CRUD for some Entities, and it also work good.
Now what I want to do is notify an user when an operation is made on an entity. So I want to notify when an entity is saved, updated or deleted, as Symfony1.4 made.
I was in doubt where to put the flashbag message, if in the entity or in the controller or even with events?!
Which is the right place where I can put this kind of feature, and how I can do it?
Thanks...
The documentation describes perfectly how to store and display these messages in your controller.
In your controller
public function updateAction(Request $request)
{
$form = $this->createForm(...);
$form->handleRequest($request);
if ($form->isValid()) {
// do some sort of processing
$this->get('session')->getFlashBag()->add(
'notice',
'Your changes were saved!'
);
return $this->redirect($this->generateUrl(...));
}
return $this->render(...);
}
In your Twig template
% for flashMessage in app.session.flashbag.get('notice') %}
<div class="flash-notice">
{{ flashMessage }}
</div>
{% endfor %}
You can use different flashbags for other messages, for example an error :
In your controller
[...]
$this->get('session')->getFlashBag()->add(
'delete',
'The entity has been deleted!'
);
[...]
In your Twig template
% for flashMessage in app.session.flashbag.get('delete') %}
<div class="flash-notice delete">
{{ flashMessage }}
</div>
{% endfor %}
Use CSS to style the delete class.

Symfony Twig path() not working when using render

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)

Resources