Can't load class by dependency injection in Symfony2 - php

I'm trying to use dependenc injection in Symfony, but it doesnt work for mee :-(
I have this controller:
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
/**
* Class UsersController
*/
class UsersController extends Controller
{
....
public function indexAction(){
....
$userManager = $this->get('user_manager');
$userManager->createUser();
...
}
....
}
This want this class to inject:
<?php
namespace AppBundle\DI;
use AppBundle\Entity\User;
use Doctrine\ORM\EntityManager;
class UserManager
{
protected $em;
public function __construct(EntityManager $entityManager){
$this->em = $entityManager;
}
public function createUser(){
$user = new User();
....
$this->em->persist($user);
$this->em->flush();
}
}
My services.yml
services:
user_manager:
class: AppBundle\DI\UserManager
arguments: ["#doctrine.orm.entity_manager"]
But i still have this error:
Attempted to load class "UserManager" from namespace "AppBundle\DI".
Did you forget a "use" statement for another namespace?
Could someone advise me, where is a mistake? I'm starting with symfony...
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;
}

Symfony doesn't load my custom validator defined as service

I'm trying to inject EntityManagerInterface in my custom validator, but I have this error:
Attempted to load class "validator_check_client_id" from the global namespace.
Did you forget a "use" statement?
My code is:
CheckClientId.php
namespace App\Validator;
use Symfony\Component\Validator\Constraint;
/**
* #Annotation
*/
class CheckClientId extends Constraint{
public $message = 'Test';
public function validatedBy(){
return 'validator_check_client_id';
}
}
CheckClientIdValidator.php
namespace App\Validator;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class CheckClientIdValidator extends ConstraintValidator{
private $entityManager;
public function __construct(EntityManagerInterface $entityManager) {
$this->entityManager = $entityManager;
}
public function validate($value, Constraint $constraint){
//Todo
return;
}
}
services.yaml
validator.check_client_id:
class: App\Validator\CheckClientIdValidator
autowire: false
arguments:
$entityManager: '#doctrine.orm.entity_manager'
tags:
- {
name: validator.constraint_validator,
alias: validator_check_client_id,
}
Should I do an extra step to register my service? I think that symfony cannot find it because it is not properly registered.
I also tried to do what this answer says symfony validator as service not working, but I get a similar error:
Attempted to load class "app.validator.blog.slug_unique" from the global namespace.
Did you forget a "use" statement?
Do you have any idea what is happening?
Thank you for your help!
Thanks to autowire and autoconfig, all you really have to do is to get your class names right. No changes to services.yaml. Here is a working example using a fresh 5.2 project.
# src/Validator/CheckClientId.php
namespace App\Validator;
use Symfony\Component\Validator\Constraint;
/** #Annotation */
class CheckClientId extends Constraint
{
public $message = 'CheckClientId';
}
# =============================
# src/Validator/CheckClientIdValidator
namespace App\Validator;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedValueException;
class CheckClientIdValidator extends ConstraintValidator
{
public function __construct(private EntityManagerInterface $entityManager)
{
}
public function validate($value, Constraint $constraint)
{
dump('validate ' . $value);
throw new UnexpectedValueException($value, 'string');
}
}
# ===============================
# Test Entity
# src/Entity/Client.php
namespace App\Entity;
use App\Validator as AcmeAssert;
class Client
{
/** #AcmeAssert\CheckClientId */
public $id = 42;
}
# ====================================
# Test Command
# src/Command/ValidateCommand
namespace App\Command;
use App\Entity\Client;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
class ValidateCommand extends Command
{
protected static $defaultName = 'test:validator';
public function __construct(private ValidatorInterface $validator)
{
parent::__construct();
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$client = new Client();
$errors = $this->validator->validate($client);
echo $errors;
return Command::SUCCESS;
}
}
Get the test command working and move on from there.

Injecting Services into a Service

I am trying to inject public services like entityManager in the constructor of a service I created but I keep having this error :
Too few arguments to function App\Services\BillingInterface::__construct(), 0 passed in /var/www/.../src/Controller/TestController.php on line 144 and exactly 1 expected.
In my controllers, services are correctly injected in different methods but in the service I created it's not injected in the constructor.
I didn't change anything in the services.yaml as the documentation says autowire is automatic in Symfony 4.2
PS : I recently updated from Symfony 4.1 to 4.2 and I'm not sure but I think it worked before.
Maybe a library didn't updated correctly but I don't find any errors.
Here are the informations for the service
Service code :
#/src/Services/BillingInterface
namespace App\Services;
use Doctrine\ORM\EntityManagerInterface;
class BillingInterface {
private $em;
public function __construct(EntityManagerInterface $entityManager)
{
$this->em = $entityManager;
}
}
Controller code :
namespace App\Controller;
use App\Services\BillingInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class TestController extends AbstractController {
public function teest(EntityManagerInterface $entityManager)
{
$billing = new BillingInterface();
}
}
And If I instantiate BillingInterface with $entityManager parameter of Controller, it works but I would like it injected directly in the BillingInterface class constructor.
And finally, here is what is written in Symfony's documentation :
// src/Service/MessageGenerator.php
// ...
use Psr\Log\LoggerInterface;
class MessageGenerator
{
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
public function getHappyMessage()
{
$this->logger->info('About to find a happy message!');
// ...
}
}
Link : https://symfony.com/doc/current/service_container.html
Chapter : Injecting Services/Config into a Service
So, I don't know what's wrong with my Service.
Thank you for your answers.
Since your BillingInterface is a service - you need to use its instance that is provided by Symfony container instead of attempting to instantiate it by yourself. Your controller needs to inject this service in order to be able to use it:
namespace App\Controller;
use App\Services\BillingInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class TestController extends AbstractController
{
/**
* #var BillingInterface
*/
private $billing;
/**
* #param BillingInterface $billing
*/
public function __construct(BillingInterface $billing)
{
$this->billing = $billing;
}
public function teest(EntityManagerInterface $entityManager)
{
// Use $this->billing ...
}
}

How to autowire Common Controller Dependencies in Symfony using an Abstract class

I have created an abstract BaseController class that extends AbstractController.
This is so that all the Common Dependencies don't have to be injected in each Controller class that I have (e.g. EntityManager and RequestStack).
However, I have some Controller classes where I would like to inject additional services in the constructor, but this is causing problems.
// src/Controller/BaseController.php
namespace App\Controller;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RequestStack;
abstract class BaseController extends AbstractController
{
protected $em;
protected $request;
public function __construct(EntityManagerInterface $em, RequestStack $request)
{
$this->em = $em;
$this->request = $request->getCurrentRequest();
}
}
I can then just extend my Controller classes and call for example $this->em in any of the methods.
However, let's say that I wanted to do the following:
// src/Controller/DashboardController.php
namespace App\Controller;
use Symfony\Component\Translation\TranslatorInterface;
class DashboardController extends BaseController
{
public function __construct(TranslatorInterface $translator)
{
parent::__construct();
$this->translator = $translator;
}
public function index()
{
// use $this->translator()
}
}
This would cause an error as the constructor of the BaseController is expecting two arguments to be passed.
I've tried adding the following to my services.yaml but to no avail:
App\Controller\BaseController:
arguments: ['#doctrine.orm.entity_manager', '#request_stack']
What would be the best way to autowire these arguments, and would this be a good practice?

Symfony 3.1 / Doctrine, Repository or include path wrong

I got this error:
Warning: Missing argument 1 for Doctrine\ORM\EntityRepository::__construct()
I used phpstorm for coding and the line in TestController.php
new ProductRepository();
is underlined with a message:
Required parameter $em missing less.
Invocation parameter types are not compatible with declared.
But I don't use the $em parameter yet.
I use 3 files:
AppBundle
|__Controller
| |__ TestController.php
|__Entity
|_______ Product.php
|_______ ProductRepository.php
TestController.php:
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Doctrine\ORM\EntityRepository;
use AppBundle\Entity\ProductRepository;
use Symfony\Component\HttpFoundation\Response;
class TestController extends Controller
{
/**
* #Route("/test", name="test")
*/
public function indexAction()
{
$pr = new ProductRepository();
return new Response('OK '.$pr->test());
}
}
Product.php:
<?php
// src/AppBundle/Entity/Product.php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="product")
* #ORM\Entity(repositoryClass="AppBundle\Entity\ProductRepository")
*/
class Product
{ /* ......CODE ...*/}
ProductRepository.php:
namespace AppBundle\Entity;
use Doctrine\ORM\EntityRepository;
class ProductRepository extends EntityRepository
{
public function test()
{
return 'hello';
}
}
Get repository through doctrine service, controller returns doctrine service by getDoctrine method
public function indexAction()
{
$pr = $this->getDoctrine()->getRepository('AppBundle:Product');
return new Response('OK '.$pr->test());
}
You shouldn't create repositories directly. Use EntityManager for this purpose. You can try the following code:
class TestController extends Controller
{
private $entityManager;
public function __construct(\Doctrine\ORM\EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
/**
* #Route("/test", name="test")
*/
public function indexAction()
{
$pr = $this->entityManager->getRepository('AppBundle\Entity\ProductRepository');
return new Response('OK '.$pr->test());
}
}

Categories