Symfony 4 Invalid service "my.myform.service" - php

I am new to Symfony. I try to make a service from one of my classes.
When I run bin/console cache:clear I get this error:
In ResolveNamedArgumentsPass.php line 66:
Invalid service "my.myform.service": did you forget to add the "$" prefix to argument "container"?
Here is my code:
config/services.yaml:
my.myform.service:
class: App\Controller\MyformController
arguments:
container: "#service_container"
src/Controller/MessageController.php:
namespace App\Controller;
use App\Entity\Product;
use Doctrine\ORM\EntityManagerInterface;
use App\Controller\MyformController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class MessageController extends AbstractController
{
/**
* #Route("/message", name="message", methods="GET")
*/
public function index(Request $request): Response
{
//$myform = new MyformController();
//$myform->createMyform();
$this->get("my.myform.service")->createMyform();
...
src/Controller/MyformController.php:
namespace App\Controller;
use App\Entity\Myform;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class MyformController extends AbstractController
{
public function __construct($container )
{
$this->container = $container;
}
/* protected function get($service)
{
return $this->container->get($service);
}
*/
public function createMyform(): Response
{
// you can fetch the EntityManager via $this->getDoctrine()
What's wrong?
PS I commented function get() in MyformController because I had an error:
PHP Fatal error: Declaration of App\Controller\MyformController::get($service) must be compatible with Symfony\Bundle\FrameworkBundle\Controller\AbstractController::get(string $id): object in /home/admin/web/alpin52.ru/public_html/miriada/myform/src/Controller/MyformController.php on line 51
Thanks.

why do you use dedicated method for getting the service? Use the dependency injection, framework let you define the service as argument of your action method
public function index(Request $request, YourServiceClass $serviceClass): Response
{
//$myform = new MyformController();
//$myform->createMyform();
$serviceClass->doSomething();
}

Related

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.

Why is Symfony's autowire giving me the debug-version instance of a class? Can I bypass this to get the regular version in dev mode?

I have a problem with the autowiring of Symfony\Component\Mercure\Publisher. Instead I am being autowired Symfony\Component\Mercure\Debug\TraceablePublisher by error. How do I fix this?
Error message is:
Argument 1 passed to App\Controller\PublisherController::index() must be an instance of Symfony\Component\Mercure\Publisher, instance of Symfony\Component\Mercure\Debug\TraceablePublisher given, called in C:\xampp\htdocs\freely\vendor\symfony\http-kernel\HttpKernel.php on line 145
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Mercure\Publisher;
use Symfony\Component\Mercure\Update;
use Symfony\Component\Routing\Annotation\Route;
/**
* Class PublisherController
* #package App\Controller
*/
class PublisherController extends AbstractController
{
/**
* #Route("/publish/{topic}", name="publisher", methods={"POST"})
*/
public function index(Publisher $publisher, $topic, Request $request)
{
$publisher(new Update($topic, $request->getContent()));
return new Response('success');
}
}

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 ...
}
}

Symfony 4 kernel controller event listener - implement interface

I want to make some operations before controller load and I have problem with include interfaces or classes into function.
My question is how should I do it to start working?
There is a code:
~/src/Controller/ControllerListener.php
<?php
namespace App\EventListener;
use App\Controller\DailyWinController;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
class ControllerListener implements DailyWinController
{
public function onKernelController(FilterControllerEvent $event, LoggerInterface $logger) {
$logger->alert('Working');
}
}
~/src/Controller/DailyWinController.php
<?php
namespace App\Controller;
interface DailyWinController {
// maybe there something?
}
~/src/Controller/UserController.php
<?php
namespace App\Controller;
use App\Entity\User;
use App\Entity\DailyWin;
use Psr\Log\LoggerInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
class UserController extends Controller implements DailyWinController
{
/**
* #Route("/user", name="user")
* #param AuthorizationCheckerInterface $authChecker
* #param UserInterface $user
* #return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
*/
public function user(AuthorizationCheckerInterface $authChecker, UserInterface $user = null, LoggerInterface $logger) {
if ($authChecker->isGranted('ROLE_USER') === false) {
return $this->redirectToRoute('logowanie');
}
$logger->warning('Logger is working');
$em = $this->getDoctrine()->getManager();
$DWrep = $em->getRepository(DailyWin::class);
$userId = $user->getId();
$dailyWin = $DWrep->findOneBy(['userId' => $userId]);
return $this->render('andprize/user/index.html.twig', array(
'dailyWin' => $dailyWin,
'userId' => $userId
));
}
}
I have the following problem:
FatalThrowableError Type error: Argument 2 passed to
App\EventListener\ControllerListener::onKernelController() must
implement interface Psr\Log\LoggerInterface, string given
You have to inject the logger to the listener.
<?php
namespace App\EventListener;
use App\Controller\DailyWinController;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
class ControllerListener implements DailyWinController
{
protected $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger=$logger;
}
public function onKernelController(FilterControllerEvent $event) {
$this->logger->alert('Working');
}
}

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