I've got a problem with the native php SoapServer in symfony2.
The SoapServer uses a "UserService" Service-Class in symfony2, which should be instantiated with the symfony2 EntityManager injected so that I can get access to my "UserRepository".
To clarify:
Soap-Server:
$oSOAPServer = new \SoapServer('/path/to/wsdl');
$oSOAPServer->setClass("my\Namespace\UserService");
$oSOAPServer->handle();
Service:
use \Doctrine\ORM\EntityManager as EntityManager;
class UserService
{
protected $em;
public function __construct(EntityManager $em) {
$this->em = $em;
}
...
Problem is: the SoapServer always returns an Internal Server Error.
The service itself works called in symfony2 directly.
Is it even possible to inject the EntityManager when called/instantiated by the SoapServer?
Thanks in advance!
Martin
Instead of using SoapServer::setClass() you could use SoapServer::setObject() and pass your service in:
$oSOAPServer = new \SoapServer('/path/to/wsdl');
$oSOAPServer->setObject($container->get('my_service'));
$oSOAPServer->handle();
Implementing a soap server is documented in the Symfony documentation: How to Create a SOAP Web Service in a Symfony2 Controller
Also, if you only need a repository, don't inject the whole entity manager. Register your repository as a service and inject it to your service.
Related
I'm trying to access the EasyCorp\Bundle\EasyAdminBundle\Dto\PaginatorDtoin my Crud Controller :
public function __construct(
private EntityManagerInterface $manager,
private EntityRepository $entityRepository,
private PaginatorDto $paginatorDto,
) {
}
But I've got this error => Cannot autowire service "App\Controller\Activity\ActivityCrudController": argument "$paginatorDto" of method "__construct()" references class "EasyCorp\Bundle\EasyAdminBundle\Dto\PaginatorDto" but no such service exists. and I don't understand why and How to fix it :(
Any idea ?
I'm not an expert of that bundle so take my answer with a pinch of salt but looking at bundle's code I've noticed PaginatorDto not to be a service (as the name suggests).
As that DTO is not a service (and it's ok it is not), you can't autowire it nor make it a service "locally" (eg.: in your application).
So, in order to retrieve the DTO object, inject AdminContextProvider (that is a service as you can notice here) instead and use it to get the DTO
$adminContext->getCrud()->getPaginator();
Your crud controller should extend AbstractCrudController which give you access to the current admin context.
So if you want to use it in one of your crud controller method you should be able to access the paginator with:
$paginator = $this->getContext()->getCrud()->getPaginator();
If you want to do the same outside your crud controller, let's say in another service. You need to inject the AdminContextProvider to first get the AdminContext and do it the same way.
private ?AdminContext $siteRepository;
public function __construct(AdminContextProvider $adminContextProvider)
{
$this->adminContext = $adminContextProvider->getContext();
}
I've got class like this,
use Doctrine\ORM\EntityManagerInterface;
class LoginTools {
private $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
and in Controller
$logTool = new LoginTools();
Question
Does autowire should pass EntityManagerInterface to LoginTools automatically?
Because when I call LoginTools class without passing the argument I get error
Too few arguments to function App\Utils\LoginTools::__construct(), 0 passed exactly 1 expected
With Regards,
Wiktor.
As you said, LoginTools is a service. That means, that you mustn't create it in code, like you do, Symfony creates it for you and you have just to inject this service in controller instead of EntityManagerInterface.
The thing is that Symfony has DI container, it's purpose is creating services based on your configuration from config/services.yaml and then injecting them into other services' constructors/functions/properties. There's no magic, all this code, which creates your services and inject them into other services, is generated automatically and is saved into var/cache dir by Symfony, you can check it by yourself.
I want to inject my translations string into a service, so I used this in the service definition:
arguments: [#doctrine.orm.entity_manager, #translator]
I used this in the constructor:
public function __construct(\Doctrine\ORM\EntityManager $entityManager, \Symfony\Component\Translation\Translator $translator)
But I get this error:
.... __construct() must be an instance of Symfony\Component\Translation\Translator, instance of Symfony\Component\Translation\LoggingTranslator given...
What is the difference between the two?
In according with the news announcement, from the version 2.6 the translator component is defined as service like translator.default.
So change your service definition:
arguments: [#doctrine.orm.entity_manager, #translator]
with
arguments: [#doctrine.orm.entity_manager, #translator.default]
Symfony 2.6 introduced missing translations logging and for this the "translator" service alias was replaced by some kind of proxy to the real translator class.
As said in the other (and currently accepted) answer, the real translator class is now on the "translator.default" service. But using this service instead of "translator" will disable this new Symfony feature, so you may want to avoid that.
To fix your issue and still have access to the new features, change the code of your constructor to accept any implementation of TranslatorInterface :
public function __construct(\Doctrine\ORM\EntityManager $entityManager, \Symfony\Component\Translation\TranslatorInterface $translator)
Now, I am writing a php project with doctrine. But at service class, I need inject a EntityManager. How to do it? I have searched some answer, but They use a framework.
If donot use any php framework, How to write a service class and inject EntityManager?
Thanks a lots.
You just need to write a class that obtains an EntityManager object, as per:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/configuration.html#obtaining-an-entitymanager
class EntityManagerService
{
public static function getEntityManager() {
// return EntityManager object as per documentation.
}
}
$em = EntityManagerService::getEntityManager();
I hope this helps!
For example i have algorithmic function, which calculates specific hash-code. Function itself is 300+ lines of code. I need to use that functions many times in many different controllers in my bundle. Where can i store my calculate_hash() to use it in my bundle ? Can i access it from other bundles ?
Can i also write global calculate_hash() which have access to entity manager ?
Didn't find my answer here.
In the Symfony2 world, this is clearly belonging to a service. Services are in fact normal classes that are tied to the dependency injection container. You can inject them the dependencies you need. For example, say your class where the function calculate_hash is located is AlgorithmicHelper. The service holds "global" functions. You define your class something like this:
namespace Acme\AcmeBundle\Helper;
// Correct use statements here ...
class AlgorithmicHelper {
private $entityManager;
public function __construct(EntityManager $entityManager) {
$this->entityManager = $entityManager;
}
public function calculate_hash() {
// Do what you need, $this->entityManager holds a reference to your entity manager
}
}
This class then needs to be made aware to symfony dependecy container. For this, you define you service in the app/config/config.yml files by adding a service section like this:
services:
acme.helper.algorithmic:
class: Acme\AcmeBundle\Helper\AlgorithmicHelper
arguments:
entityManager: "#doctrine.orm.entity_manager"
Just below the service, is the service id. It is used to retrieve your service in the controllers for example. After, you specify the class of the service and then, the arguments to pass to the constructor of the class. The # notation means pass a reference to the service with id doctrine.orm.entity_manager.
Then, in your controller, you do something like this to retrieve the service and used it:
$helper = $this->get('acme.helper.algorithmic');
$helper-> calculate_hash();
Note that the result of the call to $this->get('acme.helper.algorithmic') will always return the same instance of the helper. This means that, by default, service are unique. It is like having a singleton class.
For further details, I invite you to read the Symfony2 book. Check those links also
The service container section from Symfony2 book.
An answer I gave on accesing service outside controllers, here.
Hope it helps.
Regards,
Matt
Braian in comment asked for Symfony 3 answer, so here is one Symfony 3.3 (released May 2017):
1. The original class remains the same
namespace Acme\AcmeBundle\Helper;
use Doctrine\ORM\EntityManager;
final class AlgorithmicHelper
{
/**
* #var EntityManager
*/
private $entityManager;
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
public function calculateHash()
{
// Do what you need, $this->entityManager holds a reference to your entity manager
}
}
2. Service registration is much simpler
# app/config/services.yml
services:
_defaults: autowire # this enabled constructor autowiring for all registered services
Acme\AcmeBundle\Helper\AlgorithmicHelper: ~
3. Use constructor injection to get the service
use Acme\AcmeBundle\Helper\AlgorithmicHelper;
class SomeController
{
/**
* #var AlgorithmicHelper
*/
private $algorithmicHelper;
public function __construct(AlgorithmicHelper $algorithmicHelper)
{
$this->algorithmicHelper = $algorithmicHelper;
}
public function someAction()
{
// some code
$hash = $this->algorithmicHelper->calculateHash();
// some code
}
}
You can read about Symfony 3.3 dependency injection (in this case registering services in config and using it in controller) news in these 2 posts:
https://www.tomasvotruba.cz/blog/2017/05/07/how-to-refactor-to-new-dependency-injection-features-in-symfony-3-3/
https://symfony.com/blog/the-new-symfony-3-3-service-configuration-changes-explained