Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [SF] Translatable i ustawienie locale na podstawie sesji (services)
Forum PHP.pl > Forum > PHP > Frameworki
blackroger
Prośba o pomoc.

mam zdefiniowany dodatek w services:

  1. services:
  2. # Doctrine Extension listeners to handle behaviors
  3.  
  4. gedmo.listener.translatable:
  5. class: Gedmo\Translatable\TranslatableListener
  6. tags:
  7. - { name: doctrine.event_subscriber, connection: default }
  8. calls:
  9. - [ setAnnotationReader, [ @annotation_reader ] ]
  10. - [ setTranslatableLocale, [ %locale% ] ]
  11. - [ setTranslationFallback, [ true ] ]
  12.  


Jak zrobić aby metoda setTranslatableLocale dostawała parametr z sesyjnego getLocale? Teraz parametr jest pobierany bezpośrednio z parametrs.ini, a ja chcę aby tam trafiała wartość z sesji...

Przy wielojęzyczności zmiany krajów powinny być transparentne dla systemu i wiem, że można sobie uruchamiać setTranslatableLocale w kontrolerze, ale mi chodzi o automat i service container.
blackroger
Przy przekazaniu:
  1. gedmo.listener.translatable:
  2. class: Gedmo\Translatable\TranslatableListener
  3. tags:
  4. - { name: doctrine.event_subscriber, connection: default }
  5. calls:
  6. - [ setAnnotationReader, [ @annotation_reader ] ]
  7. - [ setTranslatableLocale, [ @request ] ]
  8. - [ setTranslationFallback, [ true ] ]
  9.  


Wyrzuca błąd:

ScopeWideningInjectionException: Scope Widening Injection detected: The definition "gedmo.listener.translatable" references the service "request" which belongs to a narrower scope. Generally, it is safer to either move "gedmo.listener.translatable" to scope "request" or alternatively rely on the provider pattern by injecting the container itself, and requesting the service "request" each time it is needed. In rare, special cases however that might not be necessary, then you can set the reference to strict=false to get rid of this error.
Crozin
Treść błędu zawiera klarowne wyjaśnienie i możliwe rozwiązania. Nie mniej jednak przeczytaj sobie poniższy artykuł: http://symfony.com/doc/master/cookbook/ser...ner/scopes.html
blackroger
Hmmm... czytałem już ten artykuł ale do mojego przypadku nie za bardzo mogę dostosować którąś z opcji.

Class Gedmo\Translatable\TranslatableListener nie mogę w żaden sposób zmieniać, ani dodać settera (setter injection), ani grzebać w konstruktorze. Czytając po forach niektórzy sugerują uzycie dodatkowej klasy np. RequestInjector, która tworzyłaby funkcję serwisu proxy dla request:

  1. namespace Lib;
  2.  
  3. use Symfony\Component\DependencyInjection\ContainerInterface as Container;
  4.  
  5. class RequestInjector
  6. {
  7.  
  8. protected $container;
  9.  
  10. public function __construct(Container $container)
  11. {
  12. $this->container = $container;
  13. }
  14.  
  15. public function getRequest()
  16. {
  17. return $this->container->get('request');
  18. }
  19.  
  20. public function getLocale()
  21. {
  22. $this->container->get('request')->getLocale();
  23. }
  24. }
  25.  


Mam pytanie. Czy istnieje możliwość wywołania metody bezpośrednio na service?

  1. request_injector
  2. class: Lib\RequestInjector
  3. public: false
  4. arguments: ['@service_container']
  5.  
  6.  
  7.  
  8. gedmo.listener.translatable:
  9. class: Gedmo\Translatable\TranslatableListener
  10. tags:
  11. - { name: doctrine.event_subscriber, connection: default }
  12. calls:
  13. - [ setAnnotationReader, [ @annotation_reader ] ]
  14. - [ setTranslatableLocale, [ @request_injector ] ] # jak tu zwrócić samo getLocale?questionmark.gifquestionmark.gif?
  15. - [ setTranslationFallback, [ true ] ]
  16.  
  17.  


Czy da się tak zrobić, aby zwrócić do metody setTranslatableLocale sama wartość, poprzez wywołanie metody na RequestInjector? I czy to nie kłóci się z logiką services?
Crozin
Musiałbyś tutaj skorzystać z service-factory i factory-method. Zawsze jednak możesz utworzyć swoją własną klasę, dziedziczącą po Gedmo\Translatable\TranslatableListener dodać jej settera, który przyjmuje RequestInjectora i wywołuje dziedziczoną setTranslatableLocale().
blackroger
Heh ...właśnie tak to załatwiam...TranslatableListenerService dziedziczący po TranslatableListener rozszerzający o setRequest....

Dobra nadal nie działa jak powinno....ehhh....

TranslatableListenerService:

  1.  
  2. namespace Lib\Service;
  3.  
  4. use Gedmo\Translatable\TranslatableListener;
  5. use Lib\RequestInjector;
  6.  
  7. class TranslatableListenerService extends TranslatableListener
  8. {
  9. public function setTranslatableLocale($locale)
  10. {
  11. if($locale instanceof RequestInjector)
  12. {
  13. $locale = $locale->getRequest()->getLocale();
  14. }
  15. echo $locale;exit;
  16. parent::setTranslatableLocale($locale);
  17. }
  18. }
  19.  


RequestInjector:

  1. namespace Lib;
  2.  
  3. use Symfony\Component\DependencyInjection\ContainerInterface as Container;
  4.  
  5. class RequestInjector
  6. {
  7.  
  8. protected $container;
  9.  
  10. public function __construct(Container $container)
  11. {
  12. $this->container = $container;
  13. }
  14.  
  15. public function getRequest()
  16. {
  17. return $this->container->get('request');
  18. }
  19.  
  20. public function getLocale()
  21. {
  22. return $this->getRequest()->getLocale();
  23. }
  24. }
  25.  


services.yml:

  1. gedmo.listener.translatable:
  2. class: Lib\Service\TranslatableListenerService
  3. tags:
  4. - { name: doctrine.event_subscriber, connection: default }
  5. calls:
  6. - [ setAnnotationReader, [ @annotation_reader ] ]
  7. - [ setTranslatableLocale, [ @request_injector ] ]
  8. - [ setTranslationFallback, [ true ] ]
  9.  



Nadal nie jest tak jak powinno. Przy clear cache:
[Symfony\Component\DependencyInjection\Exception\InactiveScopeException]
You cannot create a service ("request") of an inactive scope ("request").


Pomocy...

Crozin
Ponieważ próbujesz odwołać się do usługi request w momencie gdy nie jest ona dostępna. Wywołanie akcji z poziomu konsoli nie tworzy usługi request, nie tworzy w ogóle całego zasięgu request. Co musisz zrobić? Przed zwróceniem usługi request z poziomu RequestInjectora, sprawdź czy zasięg (scope) request jest w ogóle dostępny i aktywny przy pomocy ContainerInterface::isScopeActive().

Co zrobić w przypadku gdy nie jest? Metoda getLocale() może z powodzeniem zwrócić parametr default_locale, zaś metoda getRequest() powinna zwrócić NULL. Tutaj trzeba od razu zwrócić uwagę, że w przypadku gdy istnieje możliwość, że zamiast jakiejś usługi zostanie zwrócony NULL w definicji usługi korzystającej z owej niepewnej zależości powinno dodać się onInvalidReference=ignore.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.