I always use doctrine from controllers or from entity repository classes, now I am trying to use it from a static class but I can't find any example on how to do id.
Basically I'd need (I think) a way to create the entity manager in a static method.
thanks
M
You may call a setter function, injecting entity manager, where you call the static method:
MyController
Class MyController extends Controller
{
public function newAction()
{
$entityManager = $this->getDoctrine()->getManager();
SomeClass::setEntityManager($entityManager);
$result = SomeClass::myStaticMethod();
}
}
SomeClass
Class SomeClass
{
private static $entityManager;
public static function setEntityManager($entityManager)
{
self::$entityManager = $entityManager;
}
public static function myStaticMethod()
{
return $entityManager->getRepository(SomeEntity::class)->findAll();
}
}
I'm not sure from your question what you mean by static class/method, some code example might help. But you could declare this class as a service, which it sounds like it might be meant to be anyway, and then inject the entity manager as a dependency.
services.yml
services:
my_service:
class: Acme\AppBundle\Services\MyService
arguments: ["#doctrine.orm.entity_manager"]
Then in your class you will have the entity manager available like this:
<?php
namespace Acme\AppBundle\Services;
use Doctrine\ORM\EntityManager;
class MyService
{
/**
* Entity Manager
*
* #var Doctrine\ORM\EntityManager
*/
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
...
}
And you can then use this service in your controllers like so:
$this->get('my_service')->doSomething();
Related
How can i get the entityManager in some classes in Symfony ?
Tried to add a service but entityManager is null ...
What is the best way to do this in Symfony 4 ?
It's for call a function in a Repository from another class.
To access the entityManager inside your Service, you have to construct it first.
namespace App\Service;
use Doctrine\ORM\EntityManagerInterface;
class ServiceName
{
private $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
public function myFunction()
{
$classRepo = $this->entityManager->getRepository(ClassName::class);
}
}
I want to create HelperController for my project. I generate a controller with doctrine:generate:controller and I need to use entity manager in it.
I enjected to services.yml but it is giving an error like this:
Argument 1 passed to CampingBundle\Controller\HelperController::__construct() must be an instance of Doctrine\ORM\EntityManager, none given ...
My Controller Code :
namespace CampingBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Doctrine\ORM\EntityManager;
class HelperController extends Controller
{
protected $manager;
public function __construct(EntityManager $manager)
{
$this->manager = $manager;
}
My Services.yml :
services:
camping.helper_controller:
class: CampingBundle\Controller\HelperController
arguments: ["#doctrine.orm.entity_manager"]
Why it doesn't work ? Shoudl I clear cache or something else or is there anything wrong in definition ?
Thanks
Try to use EntityManagerInterface and remove extends Controller.
Check this link if you need CAS (Controllers as Services).
Change protected $manager; to private $manager;
namespace CampingBundle\Controller;
use Doctrine\ORM\EntityManagerInterface;
class HelperController
{
/**
* #var EntityManagerInterface $entityManager
*/
private $entityManager;
/**
* #param $entityManager
*/
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
}
I'll leave my two cents here as I had same issue and fixed it by adding tags to service.
something.validate.some_service:
class: Path\To\Some\Validator
arguments:
- '#doctrine.orm.entity_manager'
tags:
- { name: validator.constraint_validator, alias: some_validator_alias }
How to Work with Service Tags by Symfony
How can call this function
$this->get('translator')->trans()
in my class namespace Di\NotificationBundle\Manager;
class SMSManager
{
private function send(){
// call $this->get('translator')->trans()
}
}
You have to define your service and inject your parameter to that service. Then it's available in your constructor.
https://symfony.com/doc/current/service_container/parameters.html
and pass the translation service to your class as dependency as example:
class SMSManager
{
public function __construct(
TranslatorInterface $translator
) {
$this->translator = $translator;
}
defined as example as:
acme_sms_manager:
class: Di\NotificationBundle\Manager\SMSManager
arguments:
- '#translator'
then simply call as:
private function send(){
this->translator->trans()
}
Hope this help
I have a function that I need a few controllers. Can i call it in some other way than to extend the class in which the function is?
Question:
class CategoryController extends Controller
{
public function getCategoriesAction()
{
$categories = $this->getDoctrine()->getRepository('ModelBundle:Category')->findAll();
return $categories;
}
}
How call this function in PostController?
You can define a service and inject entity manager in it, for retrieving data:
dummy.manager:
class: AppBundle\Model\DummyManager
arguments:
entityManager: "#doctrine.orm.entity_manager"
In your service, call findAll() method:
class DummyManager {
/** #var EntityManager */
protected $entityManager;
public function __construct($entityManager) {
$this->entityManager = $entityManager;
}
public function getCategories(){
return $this->entityManager->getRepository('ModelBundle:Category')->findAll();
}
}
And last step, in your controller:
class CategoryController extends Controller
{
public function getCategoriesAction()
{
$categories = $this->container->get('dummy.manager')->getCategories();
//...
}
}
I hope this helps.
You can also use pure PHP with traits
trait CategoryProvider {
public function getCategoriesAction() {
$categories = $this->container->get('dummy.manager')>getCategories();
//...
}
}
After that you can use this trait in your controllers
class Controller1 {
use CategoryProvider;
public function indexAction(){
//...
$this->getCategoriesAction();
//...
}
}
class Controller2 {
use CategoryProvider;
public function anotherAction(){
//...
$this->getCategoriesAction();
//...
}
}
You should not define model-style getters on a controller. The notion of a "getCategoriesAction" method for a controller should be vacated from your brain.
What you want to do is define this fetching behavior in the model layer. This can be done a bunch of different ways. Cristian just posted one way so I'll offer another.
You can define the Entity Repository itself as a service.
app/config/services.yml
services:
model.repository.category:
class: ModelBundle\Entity\CategoryRepository
factory: ["#doctrine.orm.entity_manager", getRepository]
arguments: ['ModelBundle:Category']
Then in your controller (assuming it's a container-aware controller) you can do this
$categories = $this->get('model.repository.category')->findAll();
Another approach, how #Med mentioned, is to declare your controller as service:
services:
categoryController:
class: AppBundle\Controller\CategoryController
arguments:
entityManager: #entityManager
I followed the tutorial of Fabien Potiencier, about how to create your own Framework on top of the Symfony Components. Now i need a way. And I want to inject the Dependency Container to all my Controllers, without defining every single Controller as a Service.
In the orginal Symfony2 Framework all Controllers extends the Controller Class located in Symfony\Bundle\FrameworkBundle\Controller\Controller.php:
namespace Symfony\Bundle\FrameworkBundle\Controller;
class Controller extends ContainerAware
{
// ...
}
The Controller Class extends the ControllerAware Class, so you can do something like this in your Controller:
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class MyController extends Controller
{
public function someAction()
{
$this->container->get('dependencie_xyz);
}
}
So my question is: How can I accomplish the same in my Framework?
It took me a while, but i finally figured out how the Symfony2 Framework does it.
In the SymfonyFrameworkBundle is a custom ControllerResolver, which call the setContainer Method on the resolved controller. The controller has to be a instance of the ContainerAwareInterface.
Simplified version:
class ContainerAwareControllerResolver extends ControllerResolver
{
private $container;
public __construct(ContainerInterface $container)
{
$this->container = $container;
parent::__construct();
}
public function getController(Request $request)
{
$controller = parent::getController($request);
if($controller instanceof ContainerAware ){
$controller->setContainer($this->container);
}
}
}
Source:
https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php
It is too simply. The next code will help you
namespace Symfony\Bundle\FrameworkBundle\Controller;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;
use Symfony\Component\DependencyInjection\ContainerAware as ContainerAware;
class TestService extends ContainerAware
{
public function __construct(Container $container) {
// in your example from official doc 'dependencie_xyz' is a name of service
$this->setContainer($container); // call parent setContainer() method, for identifying container variable, from now you can access to ServiceContainer using $this->container variable
$test_param = $this->container->getParameter('test_param'); // get test_param from config.yml
}
}
in service.yml
write smthing like this
services:
test_service:
class: Symfony\Bundle\FrameworkBundle\TestService
arguments: ['#service_container']
and post service container as argument
If you are not implementing any interface on controller you can add the this way and it will work. This is a small modification to c4pone implementation.
/**
* Description of ContainerAwareControllerResolver
*
* #author sbc
*/
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Controller\ControllerResolver;
class ContainerAwareControllerResolver extends ControllerResolver {
private $container;
public function __construct(LoggerInterface $logger = null, ContainerInterface $container = null) {
parent::__construct($logger);
$this->container = $container;
}
protected function instantiateController($class) {
$new_class = new $class();
$new_class->setContainer($this->container);
return $new_class;
}
The Controller Class extends the ControllerAware Class, so you can do something like this in your Controller:
Well, this is not true. If we take a look at the signature of the ContainerAware class, we see that this added a setContainer method so we can set the container. Symfony2 has created the Controller::get method to make some live easier.
We can see how they do it in the source code:
/**
* Gets a service by id.
*
* #param string $id The service id
*
* #return object The service
*/
public function get($id)
{
return $this->container->get($id);
}
You can put this in your own Controller class and let all your controllers extend that controller class.