Avoid defining service multiple times in Symfony 2 Controller - php

I have multiple functions in my controller, and lots of them call $usermgr = $this->get('usermanager'); (where usermanager is a service defined in config.yml).
This means code is repeated multiple times. Is there a way to define $usermgr only once in the controller? Normally I'd consider a __construct but I believe thats not possible with a controller?

There is nothing wrong with getting the same service in multiple methods in a controller.
You can change your controller into a service ( http://symfony.com/doc/current/cookbook/controller/service.html and http://richardmiller.co.uk/2011/04/15/symfony2-controller-as-service/ ) and then inject that service. While that follows the best practises, your current way is not wrong.
You cannot request that service in the constructor, using the Symfony base Controller class, as the service container is set after initialization.

Related

Private functions in Laravel 5 service containers

I'm building an app with Laravel 5.1 using my own service providers to separate some business logic, but I can't seem to find a way to acces other methods of the service provider from within itself.
Using the function name tries to look for something in the namespace App\Providers and there's no $this because it's singleton pattern, so how can I do it? Does it have to "use" itself?
I also don't want an external helper as this function would be specific to this service.
Simply enough it can be done using self::method() or static::method() but your method has to be declared as static.

Symfony, where to put custom methods on entities?

I'm learning Symfony and I'm trying to figure out where to put custom actions over an Entity...
For example, if I have an entity Order, where to put $order->complete()? Or $order->sendToProduction(), $order->queueForDelivery()?
Those are just examples, I have complex entities and I must perform on them many actions.
In the Controller?
No, because the same action may be called from different controllers
In the Entity?
That would be the more appropriate way in a MVC model, but here I can't find an easy way to perform custom mysql query (doctrine/em is not available) from inside the Entity class, which I find strange since db operations should be perfomed at the Entity level, I believe...
In the EntityController?
It doesn't seem appropriate, and it's not easy to call repository methods from a listener, for example, and call them directly on the object...
What else? Do I have to create services? Utility classes?
If the work can be done inside a signle entity (and it's relations of course) then it should be placed there. I mean, if the operation is about changing entity's internal state.
Otherwise, if this job need to use other parts of application like database, or is performed on multiple not related entites, then I would suggest using services.
That's what where are for. Service is basically a class that can do anything. Using Service container, you can pass any dependencies to it so it's very flexible and easy to use.
For example $order->queueForDelivery(). That may mean a few different things:
changing internal state like change status to queued_for_delivery - then it should be in Order entity class
$order should be put in the Queue that is other entity class, then it should be in Queue class like $queue->addOrder($order)
this queue is an external service like RabbitMQ or anything else. Then you should use a service class.

DI Container and controllers

I just followed the http://fabien.potencier.org/article/50/create-your-own-framework-on-top-of-the-symfony2-components-part-1 articles, and have some questions about the DI container.
Let's say I want to fire an event inside my controller, how would i get the dispatcher inside my controller?
I'm starting my test framework through
$c->get('app')->handle($request);
where 'app' is the Symfony\HttpKernel. How can i set the dependencies to the container? Let's say I have a view engine, defined in the container
$c->register('view.engine', 'Core\ViewEngine');
and I want to give that object, or resolve that object, inside my Controller to render some views. It's the same problem with the event fire, I don't have access to those values inside my controller ... How is a DI container supposed to work in situations like this?
Thanks!
There are different approaches. You might want to read through the silex documentation as a next step. In silex, the application itself is a DI container. You might also read through the introduction to Symfony 2 documentation.
The most straight forward approach (and the one used by S2 as a default) is to inject the DI container itself into your controller. The controller can then pull out services such as the dispatcher as needed.
A "better" approach is to inject the dispatcher along with whatever else the controller needs directly into the controller. It's "better" because the controller itself does not need access to the container. But it's more difficult since a controller often needs a number of services just to it's job.
==============================================
How would I inject the container in the controller though?
That is where looking at existing frameworks starts to come in handy. Remember that HTTPKernel is a component and not a framework. How you use it is up to you.
In Symfony 2 the app object is actually derived from Kernel and not HTTPKernel. The Kernel in turn contains an instance of HTTPKernel as well as an instance of the container.
There are several approaches you might take. There is no single "correct" one.
If you look into HTTPKernel::handleRaw you will find:
$controller = $this->resolver->getController($request))
You might make your own controller resolver object which would inject the container after creating the controller. Just one possibility.

How to access services inside non-controller function in Symfony 2

You may access the (let's say) Doctrine service inside the controller, using:
$d = $this->getDoctrine()
now I want my controller to call another function (in another class) and I want that class to have access to all services. Is that possible without passing the services as variable?
You have to inject dependent services to your class or method. If you were thinking about some global object you might access everywhere than it's not the right way to go (and you can't actually access the container this way). You'd miss the whole point of dependency injection.
You can inject the services to your class two ways:
Manually
Let DIC do it
First solution requires you to pass the dependency yourself either way (constructor, setter, method).
The later solution means you define your class as a service and let container construct it and inject the dependencies. It can only be done if you can delegate object creation to DIC. It cannot be done with Entities for example.
Be careful with injecting whole container. It's not the best practice. You'd introduce dependency on a whole container which might have different services depending on the configuration. Dependencies wouldn't be clear.

Passing Entity Manager to Service Layer ZF Doctrine2

I'm trying to pass the entity manager to a service but havent find a correct way yet. I want to complete remove the em from the controller so thats why I'm finding another way.
I was thinking of this options:
1. I could save it in the registry and then try to access it from the service object. can I access the registry from there?
2. Inject the em to a static variable of a base class for the services in the bootstrap.
What is the correct way yo do it?
thanks
I think generally the best way to do it is to pass the entitymanager as an argument to the constructor.
This allows you to easily replace the entitymanager for example when doing unit tests, and unlike your approaches of 1 and 2, it does not depend on behavior in a base class or global data (the registry is a lot like a global variable)
What you could do to avoid touching the EM in your controllers is using a dependency injection container, such as the one in Symfony2 or the one in ZF2 (not sure if that component is very stable yet).
Another perhaps slightly simpler approach would be to have a sort of a "service locator" object, which you would use in the controller to get instances of your services. You could initialize the locator in your bootstrap with the services, or perhaps with a factory class which creates them.
In any case you will probably require at least some kind of an intermediate object in the controller. Personally I don't really see an issue with simply using the EM itself, unless you have some other reasons besides just not wanting to.
There's nothing wrong, IMO, with letting your controllers know about the EM. I typically use a Zend_Application_Resource to bootstrap Doctrine. That resource facilitates a bootstrap resource called "doctrine" which has an EM available. The abstract controller implements and em() method, which returns the EM.
When instantiating service classes, the constructor simply injects the EM via a call to $this->em() at constructor time.
This is nice, as many times, simple controller actions don't need any special service class, but can instead get away with doing $entity = $this->em()->getRepository('Some\Entity')->find(1); In those cases, I don't see any reason for additional redirection via a service class.

Categories