I have a method in 'DynamicList' service that should return a select filled with dynamic data, but i'm getting "circular reference":
YML:
parameters:
my.dynamic_list.class: My\DynamicListBundle\Service\DynamicList
services:
my.dynamic_list:
class: %my.dynamic_list.class%
arguments: ['#doctrine.orm.default_entity_manager','#templating']
Class:
<?php
namespace My\DynamicListBundle\Service;
use Doctrine\ORM\EntityManager;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
class DynamicList
{
private $em;
private $templating;
public function __construct(
EntityManager $em,
EngineInterface $templating
) {
$this->em = $em;
$this->templating = $templating;
}
public function getSelect($slug)
{
$dynamic_list = $this->em
->getRepository('MyDynamicListBundle:DynamicList')
->findOneBy(array(
"slug" => $slug
));
return $this->templating->render('MyComponentsCoreBundle::Templates/DynamicList/combo.html.twig', array(
'dl' => $dynamic_list
));
}
}
I guess i don't need to put here the twig content: the problema occurs before.
Last, the error i'm getting:
Circular reference detected for service "my.dynamic_list", path: "my.dynamic_list -> templating -> twig". (500 Internal Server Error - ServiceCircularReferenceException)
What's the proper way to get templating component working in my service?
Well, I found a workaround but I don't if is the best way:
<?php
namespace My\DynamicListBundle\Service;
use Doctrine\ORM\EntityManager;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
class DynamicList
{
private $em;
private $templating;
public function __construct(
EntityManager $em
) {
$this->em = $em;
}
public function init(
EngineInterface $templating
) {
$this->templating = $templating;
}
public function getSelect($slug)
{
$dynamic_list = $this->em
->getRepository('MyDynamicListBundle:DynamicList')
->findOneBy(array(
"slug" => $slug
));
return $this->templating->render('MyComponentsCoreBundle::Templates/DynamicList/combo.html.twig', array(
'dl' => $dynamic_list
));
}
}
So, in controller, I call 'init()' to pass 'templating':
$dl_service = $this->get('my.dynamic_list');
$dl_service->init($this->container->get('templating'));
Related
I use HWIOAuthBundle for Symfony.
HWI\Bundle\OAuthBundle\Security\Core\Authentication\Provider\OAuthProvider.php has function "authenticate" where create and return OAuthToken.
public function authenticate(TokenInterface $token){
...
$token = new OAuthToken($oldToken->getRawToken(), $user->getRoles());
$token->setResourceOwnerName($resourceOwner->getName());
$token->setUser($user);
$token->setAuthenticated(true);
$token->setRefreshToken($oldToken->getRefreshToken());
$token->setCreatedAt($oldToken->getCreatedAt());
return $token;
}
I need set some attribute to this OAuthToken like :
$token->setAttribute('name' => 'value');
How can i do this ?
I use service with only one function "loadUserByOAuthUserResponse" which return user object :
class PartnerEntityUserProvider implements OAuthAwareUserProviderInterface{
...
public function loadUserByOAuthUserResponse(UserResponseInterface $response){
...
return $user;
}
...
}
Edited
I found solution with using service on security.interactive_login event :
config/services.yaml
services:
App\EventListener\InteractiveLoginListener:
tags:
- { name: kernel.event_listener, event: security.interactive_login }
src/EventListener/InteractiveLoginListener.php
<?php
namespace App\EventListener;
use App\Entity\Perimetre;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
class InteractiveLoginListener
{
private $security;
private $entityManager;
public function __construct(Security $security, EntityManagerInterface $entityManager)
{
$this->security = $security;
$this->entityManager = $entityManager;
}
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
{
$this->security->getToken()->setAttribute('perimetre', $this->entityManager->getRepository(Perimetre::class)->findOneBy(['id' => $this->security->getToken()->getUser()->getFiliale()->getPerimetre()->getId()]));
}
}
i'm working on Symfony 4.
I have a service:
App\EventListener\EbayExceptionListener:
tags:
- { name: kernel.event_listener, event: kernel.controller }
arguments: [ "#doctrine.orm.entity_manager" , "#router" , "#session" ]
And here is my listener :
<?php
namespace App\EventListener;
use App\Entity\Ebay;
use Doctrine\ORM\EntityManager;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\Routing\Router;
class EbayExceptionListener
{
private $repository;
private $router;
private $session;
private $redirectName = 'home';
public function __construct(EntityManager $entityManager, Router $router, Session $session)
{
$this->repository = $entityManager->getRepository(Ebay::class);
$this->router = $router;
$this->session = $session;
}
//Check if an eBay entity exist in the database, if not redirect to the form to create the eBay entity
public function onKernelController(FilterControllerEvent $event)
{
$ebay = $this->repository->findOneBy(['name' => 'Ebay']);
$request = $event->getRequest();
$routeName = $request->get('_route');
dump($routeName);
if ($routeName != "home" AND $ebay == null) {
$this->session->getFlashBag()->add('error', 'Please provide information for Ebay form');
return new RedirectResponse($this->router->generate($this->redirectName));
}
}
}
My Controller:
<?php
namespace App\Controller;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class HomeController extends Controller
{
/**
* #Route("/", name="home")
*/
public function index()
{
return $this->render('home/index.html.twig', [
'controller_name' => 'HomeController',
]);
}
}
I have a problem with the var $routeName inside my Listener, in fact the value of this variable should be the name of the current route. But when I use the dump($routeName)
I have 2 results : "_wdt" and "home"
I don't know why the $request parameters are not the same when my listener is executed and after the page has been generated.
Because I have no page call "_wdt" it supposed to be "home".
Did I do something wrong ?
Thank you for your help.
I am trying to access to doctrine within an EventListener which tests a database table, if it is invalid then the user will be redirected to a config page where he will fix the issues!
The test will be executed before every call to a controller, so I will use the Event kernel.controller:
[EDITED: SOLVED, TESTING AND REDIRECTING VERY FINE]
<?php
namespace AdminBundle\EventListener;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Doctrine\ORM\EntityManager;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\Session;
class BuildReferencesEventListener
{
/**
* #var EntityManager
*/
protected $em;
/**
* #var Router
*/
protected $router;
protected $references = [
1 => 'oxygen',
2 => 'pH',
3 => 'pCO2'
];
protected $redirect_route = 'references';
protected $requestStack;
protected $session;
public function __construct(EntityManager $entityManager, Router $router, RequestStack $requestStack, Session $session)
{
$this->em = $entityManager;
$this->router = $router;
$this->requestStack = $requestStack;
$this->session = $session;
}
public function onKernelController()
{
$em = $this->em;
$savedReferences = $em->getRepository('AdminBundle:ParamReference')->findAll();
$references = $this->references;
if (count($savedReferences) <= 0){
$this->redirect();
}
for ($i =0; $i<count($savedReferences); $i++){
if ($savedReferences[$i] !== $references[$i]) {
$this->redirect();
}
}
}
public function redirect()
{
$request = $this->requestStack->getCurrentRequest();
$route = $request->get('_route');
$this->session->getFlashBag()->add('warning', 'You need to setup the references for the parameters before starting the work');
if ($route != 'references'){
$url = $this->router->generate('references');
$redirect = new RedirectResponse($url);
$redirect->send();
}
}
}
Here is services.yml
build.references:
class: AdminBundle\EventListener\BuildReferencesEventListener
arguments: ['#doctrine.orm.entity_manager', '#router', '#request_stack', '#session']
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
Add argument inside your service.yml event listner service section
Your.service:
Class: AdminBundle\EventListener\BuildReferencesEventListener
arguments: ['#doctrine.orm.entity_manager']
tags:
- { name: kernel.event_listener, event: kernel.controller }
And add this __cunstruct code inside your listner:
namespace AdminBundle\EventListener;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Doctrine\ORM\EntityManager;
class BuildReferencesEventListener
{
protected $em;
function __construct(EntityManager $em)
{
$this->em = $em;
}
public function onKernelController(FilterControllerEvent $event)
{
//TO DO call doctrine
// $em = Enity Manager...
// $em->getRepository...
// I hope its clear enough what im trying to do
}
In Symfony 3.4 and above, autowiring is enabled by default, so you just have to add a type-hinted argument to your service's constructor method and a private property to assign the argument's value to.
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
class BuildReferencesEventListener
{
private $em;
public __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
public function onKernelController(FilterControllerEvent $event)
{
$em = this->em;
// [...]
}
}
If you need to
declare arguments explicitly, you could do this in your service configuration:
# config/services.yaml
services:
# ... same code as before
# explicitly configure the service
AdminBundle\EventListener\BuildReferencesEventListener:
arguments:
$em: '#doctrine.orm.entity_manager_interface'
This could be useful to pass parameters that the service container doesn't know.
To learn more about the service container, https://symfony.com/doc/3.4/service_container.html#injecting-services-config-into-a-service.
How do I use Doctrine in a class outside from the controller?
$event = $this->getDoctrine()
->getRepository('AtotrukisMainBundle:Event')
->findByCreatedBy($userId);
if (!$event) {
throw $this->createNotFoundException(
'You have no events'
);
}
The code above works perfectly in a controller, but in a service I get error: Attempted to call method "getDoctrine" on class "Atotrukis\MainBundle\Service\EventService" in /var/www/src/Atotrukis/MainBundle/Service/EventService.php line 15.
How do I make it work?
services.yml:
services:
eventService:
class: Atotrukis\MainBundle\Service\EventService
Part from the EventController:
public function readMyEventsAction()
{
$user = $this->getDoctrine()->getRepository('AtotrukisMainBundle:User')
->findOneById($this->get('security.context')->getToken()->getUser()->getId());
$userEvents = $this->get('eventService')->readUserEvents($user);
return $this->render('AtotrukisMainBundle:Event:myEvents.html.twig', array('events' => $userEvents));
}
EventService.php:
<?php
namespace Atotrukis\MainBundle\Service;
class EventService{
public function create(){
}
public function readUserEvents($userId){
$event = $this->getDoctrine()
->getRepository('AtotrukisMainBundle:Event')
->findByCreatedBy($userId);
if (!$event) {
throw $this->createNotFoundException(
'You have no events'
);
}
return $userId;
}
}
You can pass it as an argument in your service declaration:
services:
eventService:
class: Atotrukis\MainBundle\Service\EventService
arguments: ["#doctrine.orm.entity_manager"]
Then just add a constructor to your class:
protected $em;
public function __construct($em)
{
$this->em = $em
}
Hello i have an error on EventSubscriber for form in sonata admin
namespace OneA\AdvertBundle\Form\EventListener;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\DependencyInjection\ContainerAware;
class CategoryFieldsSubscriber extends ContainerAware implements EventSubscriberInterface
{
private $factory;
public function __construct(FormFactoryInterface $factory)
{
$this->factory = $factory;
}
public static function getSubscribedEvents()
{
return array(FormEvents::PRE_SET_DATA => 'preSetData');
}
public function preSetData(FormEvent $event)
{
$data = $event->getData();
$form = $event->getForm();
//$form->add('advert_fields', 'text');
$advert_type = $form->get('advert_type')->getData();
$this->getFields($form, $advert_type);
}
public function getFields($form, $advert_type)
{
$form->add('advert_fields', 'text', array(
'label' => 'dfjg',
));
$this->container->get('one_a_advert.admin_motors_field')->getFieldsForm($form);
}
}
When i call the container i have this error
FatalErrorException: Error: Call to a member function get() on a non-object in
To the container->get(
You need to send in your constructor required container like this:
services:
kernel.listener.your_listener:
class: OneA\AdvertBundle\Form\EventListener\CategoryFieldsSubscriber
arguments: [#factory, #service_container]
and use this like
private $container;
private $factory;
public function __construct(FormFactoryInterface $factory, $container)
{
$this->container = $container;
$this->factory = $factory;
}