unable to access variables in extended view page in symfony - symfony

I'm passing values to a view page called abc.html.php using render in Symfony. Now this view page extends a header. The variable i'm passing from controller is not accessible in the extended view. Is there any way to do so ?
In symfony, the variables i pass from controller and not accessible in the view pages which are extended. In that case, i want to declare a global variable in config/packages/twig.php.
How can i define a global variable with session data ?
or is there any way to use variables of controller in extended view page ?
I tried accessing it. But it doesn't work out.
In my controller
return $this->render('abc.html.php',[
'variable' => 'some array or string',
]);
Now i'm unable to use the 'variable' in a base file which is extended in abc.html.php like this:
<?php echo $this->render('includes/base.html.php');?>

You can use render controller instead of extends or include template. you should create a function inside your controller witch render the header view then you call this function with render controller.
Now you can pass any variable to your header view from the controller.
https://symfony.com/doc/current/templating/embedding_controllers.html

Related

ZF3 - adding a view fragment to ViewModel

I am curious to know if it is possible to add a fragment to a view model:
return new ViewModel([]);
Returns my view to https://example.com/view
However is it possible to set this dynamically to add a fragment?
return new ViewModel("#fragment")
To return to https://example.com/view#fragment
The use case, have a js login/register view that is either https://example.com/view#login or https://example.com/view#register and want to return to the correct view...
EDIT
Obviously, this can be done using a re-direct, however, in the case of returning form errors, ViewModel needs to be used...
Not sure if this is possible to apply param to router, but you can alwas return redirectToRegister = true, and then write and execute JavaScript in view which will change view if True.
A fragment is a same document reference i.e. if the URL specification is used correctly #register and #login will refer to different elements in the same document.
The view model therefore should be returning the same html in both cases, and the fragment will be handled by the browser. To distinguish register and login pages instead use different paths in the URL.

Can't use render(controller) in SonataAdminBundle template

I create custom controller(extending Sonata\AdminBundle\Controller\CRUDController) and action.
When render this action {{render(controller('MainBundle:SonataAdmin/Order:searchCertificate'))}}
I get Symfony error:
An exception has been thrown during the rendering of a template ("There is no _sonata_admin defined for the controller MainBundle\Controller\SonataAdmin\OrderController and the current route").
I found answer in official documentation:
If you want to render a custom controller action in a template by
using the render function in twig you need to add _sonata_admin as an
attribute. For example; {{
render(controller('AppBundle:XxxxCRUD:comment', {'_sonata_admin':
'sonata.admin.xxxx' })) }}. This has to be done because the moment the
rendering should happen the routing, which usually sets the value of
this parameter, is not involved at all, and then you will get an error
"There is no _sonata_admin defined for the controller
AppBundleControllerXxxxCRUDController and the current route ' '."
i have solved this Problem by setting the _sonata_admin in the comming request:
with normal Controller:
$request->request->set('_sonata_admin','admin.template');

Creating menu on symfony2.3 using render

on my Admin template I've used render function to add the menu.
The controller sidebar add all links from db.
The problem is made when i want to add "current" class because i can't access of current url/controller from a render request.
{{ render(controller('AdminDashboardBundle:Template:sidebar')) }}
How I can access to all informations from the render controller (without pass a var )?
Thanks
The RequestStack service has been built with Symfony 2.4. If you declare your Template controller as a service and inject RequestStack, you'll be able to use your current render call without passing arguments.
But you are speaking about Symfony 2.3, and unfortunately I don't think it is possible to do what you want without arguments. Here are some example on how to pass the current route / the URL as an argument of your controller.
1) Passing the URL :
{{
render(controller('AdminDashboardBundle:Template:sidebar', {
'url': app.request.requesturi
}))
}}
2) Passing the route :
{{
render(controller('AdminDashboardBundle:Template:sidebar', {
'route': app.request.attributes.get('_route'),
'route_params': app.request.attributes.get('_route_params')
}))
}}
I know you want to use Symfony2.3 and this call without passing vars, I think that's simply not possible because of how work scopes.

How to send data to base template without controller?

I need to get the data from entity in the base template (twig), but not rendering this data from controller.
Specifically, I want to realize the menu. Menu labels stored in the database (Page entity). I have many controllers and I don't want to repeat the code of the entity handling in each controller.
I could extend the controller's classes, but I want to avoid stuff like this:
return $this->render('... .html.twig',
array(
...
'menu' => $labels,
...
)
);
in each of the controllers.
This is the perfect use-case for an embedded controller. You can call a new controller from your template for rendering a part of your response, in this case the menu. It can have any logic a controller can, meaning you can query your database, build your menu structure and render a twig file for outputting it as html.

FOSUserBundle: Change Password within actual project

I have successfully installed FOSUserBundle in my project and everything works as expected. However, I am struggling with how to implement it in my actual project.
I want to create the following setup:
A page displaying some user settings in one form (like newsletter subscription), the possibility to change the password in a second form and maybe also a third form to change the username.
The settings form as well as some more information is coming from an existing action in my controller and is working well.
I did try a few things but things are not really working out yet:
I copied some functionality from FOSUserBundle\Controller\ChangePasswordController\changePasswordAction() to my own action. This way I could get the change password form, create the view and pass it to my template.
I added the form to my template with {{ form_widget(form) }}. The form is being displayed and it's even working. I can change the password. However, the labels are being lost, simply reading Current, First, and Second. Also there is no error messaging showing up when the two new passwords don't match or are being left empty.
Over all I have the feeling I am probably doing this in a wrong way. Could you please help me how I should handle this task and point out where I am likely doing something stupid?
Here is the code of my action, reduced to what's important here:
# src/Acme/MyBundle/Controller/BackendController.php
public function accountAction(){
//pretty much a copy of FOSUserBundle\Controller\ChangePasswordController\changePasswordAction()
$user = $this->get('security.context')->getToken()->getUser();
$form = $this->container->get('fos_user.change_password.form');
$formHandler = $this->container->get('fos_user.change_password.form.handler');
$process = $formHandler->process($user);
if ($process) {
//password has been changed, response will be generated
}
//more stuff going on here
$moreStuff = ...
//render view
return $this->render('AcmeMyBundle:Backend:account.html.twig', array(
'form' => $form->createView(),
'moreStuff' => $moreStuff
));
}
IMO rendering more than one form in one action is not a good idea.
Always try to separate things and let an action handle only one feature.
In your twig template I suggest to use the render method :
{% render 'AcmeBundle:SomeAction' with{'param:param} %}
It will generate a GET request on the action provided with some params if needed.
Create one action that will render the twig template with subrequests :
// AcmeUserBundle:editAction
{% render 'AcmeUserBundle:changePasswordAction' %}
{% render 'AcmeUserBundle:settingsAction' %}
{% render 'AcmeUserBundle:profileAction' %}
And then you'll need to create one action per form.
For password and username modification you can also override FOSUserBundle views if your needs are only visual. If you need to add/remove a field on the form you will need to create a new service.
I sugget reading FOSUserBundle documentation about overriding :
https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/index.md#next-steps

Resources