I got a strange problem using the logger service in symfony 2:
When injecting the logger to a service, I get a type error because LoggerInterface expected but Symfony\Bridge\Monolog\Logger given.
Also if I try to inject a custom logger, I get error because of undefined service.
Here is my code:
confiy.yml
monolog:
channels: ['payment']
handlers:
paymentlog:
type: stream
path: "%kernel.logs_dir%/payment.log"
level: debug
channels: [payment]
service.yml
#payment_services
payment.gateway_payments:
class: AppBundle\Service\paymentService
arguments: ["#service_container", "#doctrine.orm.entity_manager", "#logger"]
Service:
<?php
namespace AppBundle\Service;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Doctrine\ORM\EntityManager;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
class paymentService {
private $container;
private $em;
private $logger;
public function __construct(ContainerInterface $container, EntityManager $em, LoggerInterface $logger){
$this->container = $container;
$this->em = $em;
$this->logger = $logger;
}
Also injecting the logger with #monolog.logger.paymentlog is giving me an error "undefinded service"
Can someone please tell me where I am wrong?
THX a lot.
try this:
use Monolog\Logger;
instead of this:
use Symfony\Component\HttpKernel\Log\LoggerInterface;
And after this;
public function __construct(ContainerInterface $container, EntityManager $em, Logger $logger){
insetad of this:
public function __construct(ContainerInterface $container, EntityManager $em, LoggerInterface $logger){
Related
In my Symfony project I have manager, in which I injected two interfaces.
class ActionLogsManager
{
private $entityManager;
private $container;
private $token;
public function __construct(EntityManager $manager, ContainerInterface
$container, TokenInterface $token)
{
$this->entityManager = $manager;
$this->container = $container;
$this->token = $token;
}
}
I want to register this manager in services.yml, but i dont know how to pass these interfaces as parameters (dont know the correct syntax for this)
services:
managers.action_log_manager:
class: MyBundle\Managers\ActionLogsManager
arguments: ['#doctrine.orm.entity_manager', ?, ?]
Use TokenStorageInterface instead of TokenInterface. Aliases for those services are #service_container and #security.token_storage.
Your services.yml will look as follows:
services:
managers.action_log_manager:
class: MyBundle\Managers\ActionLogsManager
arguments: ['#doctrine.orm.entity_manager', '#service_container', '#security.token_storage']
It is very simple. You can use the console command to find it.
bin/console debug:container
On the left column - Service ID, on the right - Class name.
As example look at the screenshot
I'm trying to override the LastLoginListener to add functionality to it.
I;m trying to do it as described here
It seems
In AppBundle\DependencyInjection\OverrideServiceCompilerPass.php
<?php
namespace AppBundle\DependencyInjection\Compiler;
use AppBundle\EventListener\LastLoginListener;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class OverrideServiceCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition('"fos_user.security.interactive_login_listener');
$definition->setClass(LastLoginListener::class);
}
services.yml
services:
app.login_listener:
class: AppBundle\EventListener\LastLoginListener
arguments: []
tags:
- { name: kernel.event_subscriber }
The listener itself is copied from the bundle.
The autoloader expected class "AppBundle\DependencyInjection\OverrideServiceCompilerPass" to be defined in file "/vendor/composer/../../src/AppBundle/DependencyInjection/OverrideServiceCompilerPass.php". The file was found but the class was not in it, the class name or namespace probably has a typo.
in DebugClassLoader.php (line 261)
My goal is to add the ip address of the last login with the listener, but I'll need to create another to add a role and a registration date
I'm trying to do it "the right way" instead of doing something hackish
Its much better to use success_handler and failure_handler services.
# app/config/security.yml
firewalls:
main:
...
form_login:
...
success_handler: authentication_success_handler
failure_handler: authentication_failure_handler
Next you need to register your services and add arguments that fit your needs (probably #router and #doctrine.orm.entity_manager)
# app/config/services.yml
authentication_success_handler:
class: AppBundle\Handler\AuthenticationSuccessHandler
arguments: ['#router', '#doctrine.orm.entity_manager']
authentication_failure_handler:
class: AppBundle\Handler\AuthenticationFailureHandler
arguments: ['#router', '#doctrine.orm.entity_manager']
Then you need to create your services
// src/AppBundle/Handler/AuthenticationSuccessHandler.php
<?php
namespace AppBundle\Handler;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Router;
use Doctrine\Common\Persistence\ObjectManager;
class AuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface {
protected $router;
private $em;
public function __construct(Router $router, ObjectManager $em) {
$this->router = $router;
$this->em = $om;
}
public function onAuthenticationSuccess(Request $request, AuthenticationException $exception) {
// your code here - creating new object. redirects etc.
}
}
and
// src/AppBundle/Handler/AuthenticationFailureHandler.php
<?php
namespace AppBundle\Handler;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Router;
use Doctrine\Common\Persistence\ObjectManager;
class AuthenticationFailureHandler implements AuthenticationFailureHandlerInterface {
protected $router;
private $em;
public function __construct(Router $router, ObjectManager $em) {
$this->router = $router;
$this->em = $om;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception) {
// your code here - creating new object. redirects etc.
}
}
If you want to hook into another FOSUserBundle Controller use this
I wish to inject the services security.context & service_container in a controller. It is possible ?
here my controller :
<?php
...
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
...
class ApiProtectedController extends Controller {
protected $container;
protected $securityContext;
function __construct(ContainerInterface $container, SecurityContextInterface $securityContext) {
$this->container = $container;
$this->securityContext = $securityContext;
}
...
}
And my services declaration
api_protected_controller:
class: MyProject\ApiBundle\Controller\ApiProtectedController
arguments: [#service_container, #security.context]
//here an example of something working fine
wsse.api.security.authentication.provider:
class: MyProject\ApiBundle\Security\Authentication\Provider\WsseProvider
arguments: ['', %kernel.cache_dir%/security/nonces, #service_container]
the error returned :
Catchable Fatal Error: Argument 1 passed to MyProject\ApiBundle\Controller\ApiProtectedController::__construct() must implement interface Symfony\Component\DependencyInjection\ContainerInterface, none given,
my goal is to get in my controller the token injected in securityContext by wsseprovider, do you think it's possible ?
I have a public area of my app accesible with no login or authentication, and when I run this code in a controller if ($securityContext->isGranted('IS_AUTHENTICATED_ANONYMOUSLY')) I get a true as expected.
Then I have a service defined like this:
main.services:
class: App\MainBundle\Services\MainServices
arguments: [ #doctrine.orm.entity_manager, #security.context, #service_container ]
But when I run this code:
public function __construct(EntityManager $em, SecurityContext $securityContext, Container $container) {
$this->em = $em;
$this->container = $container;
$this->securityContext = $securityContext;
error_log("MAIN");
if ($securityContext->isGranted('IS_AUTHENTICATED_ANONYMOUSLY'))
error_log("MAIN Anon");
else
error_log("MAIN no anon");
}
I get an exception:
Uncaught exception 'Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException' with message 'The security context contains no authentication token. One possible reason may be that there is no firewall configured for this URL.'
The service is invoked right after the first command in controller.
Thank you
This error could occur when service initializes before security token created. Try not to check access in constructor, move this check to method, called from your controller.
Use it only if a token is defined and #Ziumin is wright.
public function __construct(EntityManager $em, SecurityContext $securityContext, Container $container) {
$this->em = $em;
$this->container = $container;
$this->securityContext = $securityContext;
error_log("MAIN");
$token = $this->securityContext->getToken();
if (is_object($token)) {
if ($securityContext->isGranted('IS_AUTHENTICATED_ANONYMOUSLY'))
error_log("MAIN Anon");
else
error_log("MAIN no anon");
}
}
I needed to move my model from the controller method, so I got help to change it to a service. The service by itself works, but I need to be able to connect to doctrine and the kernel from inside of this service. At first I tried to enable doctrine, but that created problems. How can I make this work? I've followed docs and got this code. I have no idea why I got the error below. Thank you for your help in advance.
My config is:
CSVImport.php
namespace Tools\TFIBundle\Model;
use Doctrine\ORM\EntityManager;
class CSVImport {
protected $em;
public function __construct( EntityManager $em ) {
$this->em = $em;
}
app/config/config.yml
services:
csvimport:
class: Tools\TFIBundle\Model\CSVImport
arguments: [ #doctrine.orm.entity_manager ]
action in controller
$cvsimport = $this->get('csvimport');
MY ERROR
Catchable Fatal Error: Argument 1 passed to
Tools\TFIBundle\Model\CSVImport::__construct() must be an instance of
Doctrine\ORM\EntityManager, none given, called in
.../Tools/TFIBundle/Controller/DefaultController.php on line 58 and defined in
.../Tools/TFIBundle/Model/CSVImport.php line 12
EDIT, my working code:
service class code with Kernel attached to it
namespace Tools\TFIBundle\Model;
use Doctrine\ORM\EntityManager,
AppKernel;
class CSVImport {
protected $em;
protected $kernel;
protected $cacheDir;
public function __construct( EntityManager $em, AppKernel $k ) {
$this->em = $em;
$this->kernel = $k;
}
Try injecting #doctrine.orm.default_entity_manager.
On web I've found how to connect to Doctrine DBAL to be able to make queries on my own. But when i changed my configuration to this one:
app/config.yml
services:
csvimport:
class: Tools\TFIBundle\Model\CSVImport
arguments: [ #doctrine.dbal.connection, #doctrine.orm.entity_manager, #kernel ]
class definition
namespace Tools\TFIBundle\Model;
use Doctrine\ORM\EntityManager,
Doctrine\DBAL\Connection,
AppKernel;
class CSVImport {
protected $c;
protected $em;
protected $kernel;
public function __construct(Connection $c, EntityManager $em, AppKernel $k ) {
$this->c = $c;
$this->em = $em;
$this->kernel = $k;
}
i got error:
RuntimeException: The definition "csvimport" has a reference to an abstract definition "doctrine.dbal.connection". Abstract definitions cannot be the target of references.
Any ideas?