Symfony2: Best way for logging from anywhere - symfony

I am working on my first Symfony project. I wonder what is the best / recommendet method to write log messages from anywhere in my code.
So far I used Monolog which works great when being used in a controller:
public function indexAction() {
$logger = $this->get('logger');
$logger->info('I just got the logger');
$logger->error('An error occurred');
// ...
}
But how can I use this code from any classe/code from my project? Doctrine entity classes for example cannot use $this->get('logger') to create the logger. How can I access the service in these classes? Or what other methode to log message is recommended in these cases?
EDIT: Of course I could create the logger in any controller and pass it down to all other classes. But this would be quite very cumbersome. There has to be a better way.

IMO, a first approach could be the creation of Event Listeners for specific actions in order to log only what you have decided to.
Have a look to this chapter : http://symfony.com/doc/current/cookbook/event_dispatcher/event_listener.html
Hope it will help you.

Related

In Spring Kafka, do I need to add the #EnableKafka annotation to my application if I'm just using producer?

As per my understanding of the below documentation, it seems, #EnableKafka annotation might be required for consumers/listeners.
https://docs.spring.io/spring-kafka/api/org/springframework/kafka/annotation/EnableKafka.html
Does this mean, this annotation is applicable in the context of consumers but not producers? Please clarify.
If you have doubts, it is better just to try that from your project and see how it is going.
Another way is to follow by its source code to analyze the logic behind that annotation. This way is easier for me because I'm too lazy to wait for build to fail when I'm not sure in the outcome. So, let's follow together!
#Import(KafkaListenerConfigurationSelector.class)
public #interface EnableKafka {
}
See that KafkaListenerConfigurationSelector. It says that for itself - listener. Since there is nothing about producer on this annotation, then no need in it when you have only a producer logic in your application.

Fix circular reference in symfony when using SerializerInterface

I'm getting a circular reference error when serializing a component. Usually this can be fixed using
$normalizer->setCircularReferenceHandler()
However, I'm using the SerializerInterface like this:
/**
* #Route("/get/{id}", name="get_order_by_id", methods="GET")
*/
public function getOrderById(SerializerInterface $serializer, OrderRepository $orderRepository, $id): Response
{
return new Response($serializer->serialize(
$orderRepository->find($id),
'json',
array('groups' => array('default')))
);
}
Is it possible to fix a circular reference error when serializing using this interface?
You totally can. Just add this in your framework config.
framework:
serializer:
circular_reference_handler: App\Serializer\MyCustomCircularReferenceHandler
This handler will work globally. Make sure you register it as a service. I does not need to implement any interface. So just a class with an __invoke() will suffice. That invoke will receive the object that is being "circle referenced" as the only argument.
You can either return the id or do some really cool stuff, like creating a uri for the resource. But the implementation details are totally up to you, as long as you don't return the same object, everything will be fine.
:)
According to the Symfony API Reference on the interface there doesn't look to be a way to execute that function or retrieve the normalizer.
Even in the Serializer, there doesn't look to be a way to retrieve the normalizer after creating the serializer.
You're best off creating the normalizer before the serializer to achieve this, rather than injecting the interface via config files. (Relevant docs link)

How to test internal controllers without route in Symfony 2

I am trying to reduce redundant code by refactoring template and controller code into reusable components, which I then use via the render(controller('AppBundle:Foo/Bar:baz')) construct inside my other templates.
Of course I would like to test these components. In the examples regarding functional testing, however, an actual route is required to make fake test requests. But my BarController here is purely internal and has no routes attached to it. How can I test this controller?
Creating dummy routes is not always possible, because some of the arguments are model objects that cannot be passed via URL. Am I approaching this the wrong way?
The service approach sounds nice, but I am simply doing this now:
self::$kernel->getContainer()->get('router')->getContext()->setParameter('_locale', 'en');
$controller = new MyController();
$controller->setContainer(self::$kernel->getContainer());
$response = $controller->myAction($arg1, $arg2, $argWhatever);
// assertions here
Seems to work just fine.
If the controllers are setup as services, then they can be easily tested much as any other class would be unit-tested. Even before Symfony 3.3 started to make them services by default, I had altered some of my own to allow them to be more easily tested like this.

Symfony2 use Doctrine in ExceptionController

Hi I'm trying to use Doctrine inside the default ExeptionController but I get the following error:
Fatal error: Call to undefined method Symfony\Bundle\TwigBundle\Controller\ExceptionController::getDoctrine()
when I try to call:
$manager = $this->getDoctrine()->getManager();
What I'm trying to do is to have a custom 404 page where I can present some items from the database.
Could you please help me? Thank you!
You may also inject the Doctrine service as a dependency in your Controller (in that case you don't need to entend class Controller)
You will have to create your own ExceptionController extending the default one. You'll have to declare it as described here: http://symfony.com/doc/current/cookbook/controller/error_pages.html#custom-exception-controller. Your custom controller must have a constructor with at least an argument of type Registry (Doctrine). You have to declare that controller as a service in your service.yml (or xml depending on your config) Have a look at the symfony doc for further explanation on how to do that. For the moment I can't help you much more as I'm outside with my Android and it's rather difficult to make long answers

Symfony2: Access Request object in Entity

I'd like to know how to access the Request object in an entity (Symfony2) to modify the user locale.
If someone has found a solution for my problem, please let me know.
It's not possible. This is by design: the entity is just a simple object that should know nothing about the request - it's the responsibility of the controller to interpret the request, and manipulate the entity based on that.
Something like:
//inside your controller:
public function fooBarAction(Request $request)
{
$entity = // get entity
$entity->setLocale($request->getSession()->getLocale());
}
The above is just example code, it won't work if you just copy and paste it. It's just to demonstrate the general idea. The entity should just be a very simple object, who's only responsibility is to hold some data. It shouldn't know where the data is coming from - that keeps it flexible (if you want to set the locale based on something else, you only have to change your controller, not all your entities).
It is possible, but...
What you can but never should do is inject the Request object into the entity (Practically turning your entity into service, see here). Also, even worse idea (but which people still do), you could inject the whole container and get Request from there. The reason why you shouldn't do it is you never should have any code that deals with business rules or any system code in your entities.
You can switch your locale directly in your routes by using _locale custom variable (accessible also from the Request). Or you can create a kernel listener, which will do the required functionality for you. This way you keep your code testable and decoupled.

Resources