symfony3.4 service container in template - php

I do have defined a service in my MainBundle/MainFunctions/ and in Controller I can call the service. How can I get the service container in SYMFONY 3.4 in a template now? Read the docs that it is not public anymore.
#view/template.html.php
<?php $shop_id = $this->container->get('main_functions')->getSessionShopId(); ?>
My config.yml
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
- { resource: "#FrontendMainBundle/Resources/config/services.yml
my FrontendMainBundle/Resources/config/services.yml
services:
_defaults:
public: true
frontend_locale.locale_listener:
class: Frontend\MainBundle\EventListener\LocaleListener
arguments: ["%kernel.default_locale%"]
tags:
- { name: kernel.event_subscriber }
main_functions:
public: true
class: "%main_functions_class.class%"
arguments: ['#translator', '#doctrine.orm.entity_manager'....
I read the docs that it is not public anymore. But I can't get to main_functions in template. How?
THANKS!!!

if you need some inteligence in your template, I advice you to use twig extension: https://symfony.com/doc/current/templating/twig_extension.html
this you will be able to call {{ yourFunction }}
this is quite simple.

The answer by MatMouth is the best way to interface with your service from the twig template. You can create functions for each method you need access in the template. Attempting to add your object as a twig variable is not a good practice unless it is just basic getters like you would use with Doctrine entities for example.
Here is some great documentation on setting up a new function and registering it in the container service:
https://symfony.com/doc/3.2/templating/twig_extension.html
You can also register a filter instead of a function. The difference between the two are the function syntax someFunction(someVar) and the filter someVar|someFilter. If you need to add additional arguments to your function or filter, just add the arguments to your callable.
Here's some documentation from Twig:
https://twig.symfony.com/doc/2.x/advanced.html
You can do cool things like make it HTML safe, inject the twig environment, etc...
Good luck and happy coding!

Related

Symfony 4 - controllers in two directories

In my application, I use Symfony 4. I want Symfony to search for controllers in two directories: A and B. I found something like this:
controllers:
resource: '../src/DirectoryA/Controller/'
type: annotation
, but it only works for one directory. How can I have Symfony to search for controllers in two directories?
Regards
In your config/services.yaml
App\DirectoryA\Controller\: # assuming you have namespace like that
resource: '../src/DirectoryA/Controller'
tags: ['controller.service_arguments']
App\DirectoryB\Controller\: # assuming you have namespace like that
resource: '../src/DirectoryB/Controller'
tags: ['controller.service_arguments']
This will add next directory for service arguments. Thats answers your questions based In directory, what you have posted is routing file, in there would be similiar
controllers_a:
resource: '../src/DirectoryA/Controller/'
type: annotation
controllers_b:
resource: '../src/DirectoryB/Controller/'
type: annotation
The accepted answer is of course completely correct.
However, once you move from having one controller directory to multiple directories, updating your services.yaml file can be a bit of a pain. Even having to have directories specifically for controllers can be limiting.
Here is an alternate approach which allows creating controllers wherever you want and automatically tagging them.
Start with an empty controller interface for tagging.
interface ControllerInterface {}
Now have all your controllers implement the interface
class Controller1 implements ControllerInterface { ...
class Controller2 implements ControllerInterface { ...
And then adjust the kernel to automatically tag all your controller interface classes with the controller tag.
# src/Kernel.php
protected function build(ContainerBuilder $container)
{
$container->registerForAutoconfiguration(ControllerInterface::class)
->addTag('controller.service_arguments')
;
}
And presto. You can create your controllers wherever you want with nothing in services.yaml.
Update:
If you would like to avoid editing Kernel.php then you can use the _instanceof functionality in your services.yaml file.
#config/services.yaml
services:
_instanceof:
App\Contract\ControllerInterface:
tags: ['controller.service_arguments']
Another Update: As long as your controller extends Symfony's AbstractController then no additional tagging is needed. You can even delete the default controller lines in the default services.yaml file if you want.

Symfony 3.4 - Auto wire of service not working in method

I'm relatively new to Symfony, and I'm having trouble some trouble.
I'm trying to type hint a custom RequestValidator class in the method being called when the endpoint is called.
Using Symfony 3.4
However, I am getting the following error:
Controller "ApiBundle\Endpoints\Healthcheck\v1\Index::check()" requires that you provide a value for the "$request" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.
Here is my setup:
services.yml file
...
_defaults:
autowire: true
autoconfigure: true
...
routing.yml
api.Healthcheck:
path: /healthcheck
controller: ApiBundle\Endpoints\Healthcheck\v1\Index::check
defaults: { _format: json }
methods:
- GET
And then - inside the Index class, I have the following:
<?php
namespace ApiBundle\Endpoints\Healthcheck\v1;
use ApiBundle\Responses\ApiResponse;
class Index extends ApiResponse
{
public function check(HealthcheckRequest $request) {
var_dump($request);die;
}
}
When I do debug:autowiring I see my HealthcheckRequest in the list.
Further, when I do the same and try type-hint in the constructor of the Index class, it all works.
And finally, if I try and type hint the Symfony/HttpFoundation/Request, inside the check() method, it instantiates it correctly.
In summary:
Not working :
check(HealthcheckRequest $request)
Working:
__construct(HealtcheckRequest $request)
check(SymfonyRequest $request)
Am I doing something wrong? Any help is appreciated.
It's part of services.yaml already in Symfony 4, but introduced in version 3.3, so this might help:
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
ApiBundle\Endpoints\:
resource: '../../Endpoints/*'
tags: ['controller.service_arguments']

Override translator class not working in symfony3

I need to know how to override the trans method in symfony3.
In symfony2 project we used to override the parameter for the translator class
parameters:
translator.class: Acme\HelloBundle\Translation\Translator
We started using symfony3 and try to apply the same approach but unfortunately the parameter was removed and the class path is written directly into the service.
You can override an existing definition (e.g. when applying the Decorator pattern). This kind of decoration is supported by the Dependency Injection Container of Symfony as described in the doc. As example:
services:
app.mailer:
class: AppBundle\Mailer
# this replaces the old app.mailer definition with the new one, the
# old definition is lost
app.mailer:
class: AppBundle\DecoratingMailer
and:
services:
# ...
app.decorating_mailer:
class: AppBundle\DecoratingMailer
decorates: app.mailer
arguments: ['#app.decorating_mailer.inner']
public: false
Hope this help

Overriding Default FOSUserBundle Forms: InvalidArgumentException

I'm using official documentation for symfony 2.1 for overriding default FOSUserBundle forms. But when I tried to override form handlers I've got this error:
InvalidArgumentException: The service definition
"test_user.form.handler.registration" does not exist.
Files listing:
<?php
// src/Test/UserBundle/Form/Handler/RegistrationFormHandler.php
namespace Test\UserBundle\Form\Handler;
use FOS\UserBundle\Form\Handler\RegistrationFormHandler as BaseHandler;
use FOS\UserBundle\Model\UserInterface;
class RegistrationFormHandler extends BaseHandler
{
protected function onSuccess(UserInterface $user, $confirmation)
{
// logic here...
parent::onSuccess($user, $confirmation);
}
}
=-=-=-=-=
# src/Test/UserBundle/Resources/config/services.yml
services:
test_user.form.handler.registration:
class: Test\UserBundle\Form\Handler\RegistrationFormHandler
arguments: ["#fos_user.registration.form", "#request", "#fos_user.user_manager", "#fos_user.mailer", "#fos_user.util.token_generator"]
scope: request
public: false
=-=-=-=-=
# app/config/config.yml
fos_user:
db_driver: orm
firewall_name: dev
user_class: Test\UserBundle\Entity\User
registration:
form:
handler: test_user.form.handler.registration
P.S. Yes, I have read similar questions, but there is not the same problem that I have.
Take a close look at the last line in services.yml. It says public: false, that is, this service is not accessible from the code (see Advanced Container Configuration). You can do one of two things: change the value of public to true or remove the line since the default value is true.
The problem was simple. I created my UnserBundle manually, so folder named DependencyInjection has not been created. This folder contains php files, which load services configuration.

Symfony2: How to render partial in Twig extension

I have a already working Twig extension in my Symfony2 app:
namespace Company\MyBundle\Service;
class MyExtension extends \Twig_Extension
{
// ...
}
I now want to create a Twig function, which itselfs takes some data and renders a partial template. But my question is: how do I get a new templating instance in my twig extension service?
Here is my current config:
services:
twig.extension.my_extensions:
class: Company\MyBundle\Service\TwigExtension
tags:
- { name: twig.extension }
If I now add arguments: [#templating] to the config, I get an (understandable) circular reference exception.
It seems one of the recommended simple ways is to inject the container directly and retrieve the templating engine from there. As you've seen, injecting in the templating engine directly causes a circular reference exception.
So, inject in #service_container and you should be good. This seems to be the approach taken by bundles such as the FOSFacebookBundle as well.

Categories