How to use multiple arguments in symfony2 service - php

This is my service file code
adminusercheck.commonFunc:
class: adminBundle\Helpers\CommonFunctions
#arguments: ["#session"]
arguments:
- #doctrine.orm.entity_manager
- #session
This is my Service class code
use Doctrine\ORM\EntityManager;
class CommonFunctions{
private $session;
protected $em;
public function __construct(Session $session, EntityManager $em)
{
$this->session = $session;
$this->em = $em;
}

Your argument order in the constructor is not matching with what's inside the services file.
The following,
public function __construct(Session $session, EntityManager $em)
Needs to be,
public function __construct(EntityManager $em, Session $session)
It is essential to note that argument order is important.
https://symfony.com/doc/2.8/components/dependency_injection.html
On a separate note, try to keep DI's to the minimum as possible. This will have an impact on performance.
Hope this helps. Thanks.

Related

getDoctrine() null on Symfony 3.4

I have an error on a symfony 3.4 project.
I'm trying to manage the display of a notification in the menu of my application.
So I created a CustomController which extends Controller.
Then I made all my other controllers inherit from CustomController.
But when I make a call to getDoctrine() to reach a repository I get the following error:
"Call to a member function has() on null"
Here is my CustomController:
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class CustomController extends Controller
{
public $data = [];
protected $em;
public function __construct()
{
$this->em = $this->getDoctrine()->getManager();
$countAttente = $this->em->getRepository('AppBundle:Commandes')->tailleEnAttente("En attente");
$this->data['countAttente'] = $countAttente;
}
}
I tried to pass the controller as a service in service.yml but it did not change anything
AppBundle\Controller\CustomController:
class: AppBundle\Controller\CustomController
arguments: ["#doctrine.orm.entity_manager"]
calls:
- [setContainer, ["#service_container"]]
I found many similar topics on this type of error but none of them allowed me to skip this error
Any help is welcome
Autowire your EntityManager directly inside your constructor:
use Doctrine\ORM\EntityManagerInterface;
private $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
Or if you need a specific repository, and autowired is set up with the default configuration you can do the same as well with the repository:
private $repository;
public function __construct(CommandesRepository $repository)
{
$this->repository = $repository;
}

Use entity manager in service

Is there a way to access an entity manager in a service ?
Although I think I have to use a dependency injection, I can't find anything in the symfony documentation.
I'm using symfony 4.
Just inject it into the constructor:
use Doctrine\ORM\EntityManagerInterface
class YourService
{
private $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
// ...
}
Thanks to autowiring no extra configuration is required.
Here is example of simple class with entity manager injected, that you can register as service:
namespace My\AppBundle;
use Doctrine\ORM\EntityManagerInterface;
class YourServiceName
{
/**
* #var EntityManagetInterface
*/
private $em;
public function __construct(EntityManagerInterface $em) : void
{
$this->em = $em;
}
}
And in services.yml:
services:
your.service.name:
class: My\AppBundle\YourServiceName
arguments: [ #doctrine.orm.default_entity_manager]
Yes you can,
use Doctrine\Common\Persistence\ObjectManager;
public function __construct(ObjectManager $manager)
{
$this->manager = manager;
}
Use the EntityManagerInterface to your service and check the autoWiring or you will need to inject it

Symfony 2.7 - Unable to use render() - onAuthenticationFailure()

I have a file "AuthenticationHandler.php" which is using "onAuthenticationFailure()" function to be able to lock an account after 5 failed attempts. If an account is locked, an email is sent to this user with an unlock link to his account... Everything is working fine here.
The problem is when I try to use "render()" instead of simply adding a sentence in "setBody("something", 'text/html')"
I have tried injecting #twig/#templating/#service_container in my AuthenticationHandler but none of them worked. When I fail on purpose to log in, I'm not receiving any error nor any flashbag saying "Bad Credential". It simply does nothing. It goes back to the login page without any message or mail.
I know my imports(use) are good because if I ommit them, I receive some common error where it says that I forgot a use statement.
I have tried putting a try/catch around "render()", but it simply ignores the rest of my code the moment I reach "$this->template->render('email:myTestPage.html.twig')
Again, every other service I inject works fine, If I simply don't use the "render()" function, an email is sent correctly. Is there any other way to capture an error message? Or at least something to put me on the right track!
service.yml:
authentication_handler:
class: Dbm\UserBundle\Handler\AuthenticationHandler
arguments: ["#session", "#router", "#security.context", "#doctrine.orm.entity_manager", "#mailer", "#twig"]
AuthenticationHandler.php
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Routing\Router;
use Doctrine\ORM\EntityManager;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
class AuthenticationHandler implements AuthenticationSuccessHandlerInterface, AuthenticationFailureHandlerInterface
{
private $session;
private $security;
private $router;
private $em;
private $mailer;
private $twig;
public function __construct(Session $session, Router $router, SecurityContext $security, EntityManager $em, \Swift_Mailer $mailer, \Twig_Environment $twig)
{
$this->session = $session;
$this->security = $security;
$this->router = $router;
$this->em = $em;
$this->mailer = $mailer;
$this->twig = $twig;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
...
$message = (new \Swift_Message())
->setSubject('Unlock Account')
->setFrom('foobar#foobar.com')
->setTo($mail)
->setBody($this->twig->render('Email:new-unexpire-account.html.twig', array('hash' => $hash)), 'text/html');
$this->mailer->send($message);
}
}
I have also tried with $foo = $this->twig->render('Email:new-unexpire-account.html.twig', array('hash' => $hash)), 'text/html') alone and I'm not getting anything either. It stops there.

symfony An error has occurred: Notice: Undefined property: ::$container

I working on a web socket app using ratchet and symfony 2.8 to connect to database and changing value in a certain column if someone connect to the server but I get error in this line
$sql = $this->container->get('database_connection');
the full error message
An error has occurred: Notice: Undefined property: check\roomsBundle\Sockets\Chat::$container
my injection in the services.yml code
services:
database_connection:
class: check\roomsBundle\Sockets\Chat
arguments: ["#service_container"]
my Chat.php code
<?php
namespace check\roomsBundle\Sockets;
use tuto\testBundle\Entity\Users;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class Chat implements MessageComponentInterface {
protected $clients;
//protected $db;
public function __construct() {
$this->clients = new \SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn) {
$this->clients->attach($conn);
echo "New connection! ({$conn->resourceId})\n";
$sql = $this->container->get('database_connection');
$users = $sql->query("UPDATE user SET ONoff= '1' WHERE UserId='2'");
}
}
Ok so there's a few things that you'll need to fix in order to solve your problem.
services:
database_connection:
class: check\roomsBundle\Sockets\Chat
arguments: ["#service_container"]
What this is doing is when it calls the constructor it's going to pass in the service container, however using the constructor to pass in your container isn't favorable, but rather instead you should implement the Symfony\Component\DependencyInjection\ContainerAwareInterface interface and then implement the method setContainer and optional a getContainer method.
/**
* #param ContainerInterface|NULL $container
*/
public function setContainer(
ContainerInterface $container = NULL
)
{
$this->container = $container;
return $this;
}
/**
* #return ContainerInterface
*/
protected function getContainer()
{
return $this->container;
}
And then after that update your service to call this method when initializing it.
services:
chat_service: # renamed because this is your chat service, not your database connection
class: check\roomsBundle\Sockets\Chat
calls:
- [setContainer, ["#service_container"]]
Your service is fine you just need little changes in your chat.php class
use Symfony\Component\DependencyInjection\ContainerInterface as Container;
class Chat implements MessageComponentInterface {
protected $clients;
private $container;
//protected $db;
public function __construct(Container $container) {
$this->clients = new \SplObjectStorage;
$this->container = $container;
}
Now u can use $this->container
Updated
Try to inject entity manager
services:
database_connection:
class: check\roomsBundle\Sockets\Chat
arguments:
- #doctrine.orm.default_entity_manager
in chat.php do like this
use Doctrine\ORM\EntityManager;
class Chat implements MessageComponentInterface {
protected $clients;
protected $em;
public function __construct(EntityManager $em) {
$this->clients = new \SplObjectStorage;
$this->em = $em;
}
$this->em->getRepository('yorrepo')->updateFuntion();
Now try to call from some repo to update
Injecting the service container is generally considered as a bad idea.
you should consider to inject database_connection service .
There are few ways to do that. Have a look at Types of Injection.
services:
chat_service:
class: check\roomsBundle\Sockets\Chat
arguments: ["#database_connection"]
your class
protected $connection;
public function __construct($connection) {
$this->connection = $connection;
}
Even if you want to go ahead with injecting the service container, the above link has relavent documentation that will help you to solve the issue you are facing.

Symfony 2 EntityManager injection in service

I've created my own service and I need to inject doctrine EntityManager, but I don't see that __construct() is called on my service, and injection doesn't work.
Here is the code and configs:
<?php
namespace Test\CommonBundle\Services;
use Doctrine\ORM\EntityManager;
class UserService {
/**
*
* #var EntityManager
*/
protected $em;
public function __constructor(EntityManager $entityManager)
{
var_dump($entityManager);
exit(); // I've never saw it happen, looks like constructor never called
$this->em = $entityManager;
}
public function getUser($userId){
var_dump($this->em ); // outputs null
}
}
Here is services.yml in my bundle
services:
test.common.userservice:
class: Test\CommonBundle\Services\UserService
arguments:
entityManager: "#doctrine.orm.entity_manager"
I've imported that .yml in config.yml in my app like that
imports:
# a few lines skipped, not relevant here, i think
- { resource: "#TestCommonBundle/Resources/config/services.yml" }
And when I call service in controller
$userservice = $this->get('test.common.userservice');
$userservice->getUser(123);
I get an object (not null), but $this->em in UserService is null, and as I already mentioned, constructor on UserService has never been called
One more thing, Controller and UserService are in different bundles (I really need that to keep project organized), but still: everyting else works fine, I can even call
$this->get('doctrine.orm.entity_manager')
in same controller that I use to get UserService and get valid (not null) EntityManager object.
Look like that I'm missing piece of configuration or some link between UserService and Doctrine config.
Your class's constructor method should be called __construct(), not __constructor():
public function __construct(EntityManager $entityManager)
{
$this->em = $entityManager;
}
For modern reference, in Symfony 2.4+, you cannot name the arguments for the Constructor Injection method anymore. According to the documentation You would pass in:
services:
test.common.userservice:
class: Test\CommonBundle\Services\UserService
arguments: [ "#doctrine.orm.entity_manager" ]
And then they would be available in the order they were listed via the arguments (if there are more than 1).
public function __construct(EntityManager $entityManager) {
$this->em = $entityManager;
}
Note as of Symfony 3.3 EntityManager is depreciated. Use EntityManagerInterface instead.
namespace AppBundle\Service;
use Doctrine\ORM\EntityManagerInterface;
class Someclass {
protected $em;
public function __construct(EntityManagerInterface $entityManager)
{
$this->em = $entityManager;
}
public function somefunction() {
$em = $this->em;
...
}
}
Since 2017 and Symfony 3.3 you can register Repository as service, with all its advantages it has.
Check my post How to use Repository with Doctrine as Service in Symfony for more general description.
To your specific case, original code with tuning would look like this:
1. Use in your services or Controller
<?php
namespace Test\CommonBundle\Services;
use Doctrine\ORM\EntityManagerInterface;
class UserService
{
private $userRepository;
// use custom repository over direct use of EntityManager
// see step 2
public function __constructor(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function getUser($userId)
{
return $this->userRepository->find($userId);
}
}
2. Create new custom repository
<?php
namespace Test\CommonBundle\Repository;
use Doctrine\ORM\EntityManagerInterface;
class UserRepository
{
private $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository(UserEntity::class);
}
public function find($userId)
{
return $this->repository->find($userId);
}
}
3. Register services
# app/config/services.yml
services:
_defaults:
autowire: true
Test\CommonBundle\:
resource: ../../Test/CommonBundle

Categories