Symfony event subscriber not working even service is defined - php

I have an event subscriber:
namespace App\EventListener;
use App\Entity\Token;
use App\Model\EncryptUtils;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\Common\EventSubscriber;
class DatabaseSubscriber implements EventSubscriber
{
public function getSubscribedEvents()
{
return array(
'prePersist'
);
}
public function prePersist(LifecycleEventArgs $args)
{
$entity = $args->getObject();
if ($entity instanceof Token) {
$enityt->setCreatedAt(new \DateTime());
}
}
}
And I've declared the service in services.yaml:
parameters:
locale: 'en'
services:
App\EventListener\DatabaseSubscriber:
tags:
- { name: doctrine.event_subscriber, connection: default }
_defaults:
autowire: true
autoconfigure: true
public: false
bind:
$appSecret: '%kernel.secret%'
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
But there's no way to get it working. I've also tried with an event listener but nothing happens

You should declare your service after all the default configuration because if not, the default configuration is overriding yours.
So your services.yaml file should be:
services:
_defaults:
autowire: true
autoconfigure: true
public: false
bind:
$appSecret: '%kernel.secret%'
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
App\EventListener\DatabaseSubscriber:
tags:
- { name: doctrine.event_subscriber, connection: default }

Related

Autowiring problem with parameter injection in Symfony 5

I'm having troubles trying to retrieve a manager from a controller in Symfony 5.
I've got this MailerManager in src/Manager/MailerManager.php:
<?php
namespace App\Manager;
use App\Client\MailjetClient;
class MailerManager {
private $mailjetClient;
function __construct(MailjetClient $mailjetClient) {
$this->setMailjetClient($mailjetClient);
}
function send($data) {
}
function getMailjetClient() {
return $this->mailjetClient;
}
private function setMailjetClient($mailjetClient) {
$this->mailjetClient = $mailjetClient;
}
}
This manager needs to inject src/Client/MailjetClient.php in order to work, that has got this code:
<?php
namespace App\Client;
use \Mailjet\Resources;
class MailjetClient {
private $client;
function __construct(string $apikey, string $apisecret) {
$this->setClient($apikey, $apisecret);
}
function getClient() {
return $this->client;
}
function setClient($apikey, $apisecret) {
$this->client = new \Mailjet\Client($apikey, $apisecret);
}
}
This is just a wrapper for the mailjet sdk installed via composer, that needs to be feeded with different $apikey and $apisecret depending on the environment, for what I'm using parameters through services.yaml file, where I also have got autowiring enabled and service definitions for both MailjetClient and MailerManager:
parameters:
rabbitmq:
host: '%env(RABBITMQ_HOST)%'
port: '%env(RABBITMQ_PORT)%'
user: '%env(RABBITMQ_USER)%'
pwd: '%env(RABBITMQ_PWD)%'
mailjet:
apikey: '%env(MAILJET_APIKEY)%'
apisecret: '%env(MAILJET_APISECRET)%'
services:
_defaults:
autowire: true
autoconfigure: true
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
App\Client\MailjetClient\:
resource: '../src/Client/MailjetClient.php'
arguments:
$apikey: '%mailjet.host%'
$apisecret: '%mailjet.port%'
App\Manager\MailerManager\:
resource: '../src/Manager/MailerManager.php'
arguments:
$mailjetClient: '#client.mailjet'
The problem I'm having is that I'm getting this error: Cannot autowire service "App\Client\MailjetClient": argument "$apikey" of method "__construct()" is type-hinted "string", you should configure its value explicitly. when I try to inject the MailManager in the src/Controller/MailerController.php controller:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use App\Manager\MailerManager;
class MailerController extends AbstractController
{
/**
* #Route("/compose", name="compose")
*/
public function compose(MailerManager $mailerManager)
{
dump($mailerManager);die();
}
}
}
What could posibbly be wrong? I'm coming from Symfony 2, and this parameter injection was something standard that used to work like a charm, now I'm totally confused about how to mix the autowiring with the service manual definition.
I had a total disaster on the services.yml side, thanks to u_mulder and Tejas Gosai hints I could finally put this to work. I had a few type errors on the parameters I was injecting, the MailManager.php specific declaration was not needed, and my client namespaces should not end with \ ad u_mulder suggested.
Finally, with this services.yml it works:
parameters:
rabbitmq.host: '%env(RABBITMQ_HOST)%'
rabbitmq.port: '%env(RABBITMQ_PORT)%'
rabbitmq.user: '%env(RABBITMQ_USER)%'
rabbitmq.pwd: '%env(RABBITMQ_PWD)%'
mailjet.apikey: '%env(MAILJET_APIKEY)%'
mailjet.apisecret: '%env(MAILJET_APISECRET)%'
services:
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
App\Client\MailjetClient:
arguments:
$apikey: '%mailjet.apikey%'
$apisecret: '%mailjet.apisecret%'
App\Client\RabbitClient:
arguments: ['%rabbitmq.host%','%rabbitmq.port%','%rabbitmq.user%','%rabbitmq.pwd%']

Non-existent service error since symfony 3.3

I had 2 working services at my symfony 3.2.(8?) project and had to up to 3.3 (currently 3.3.2). One of my services is working just fine, and the second one is giving me error:
services.yml
parameters:
#parameter_name: value
services:
_defaults:
autowire: true
autoconfigure: true
public: false
AppBundle\:
resource: '../../src/AppBundle/*'
exclude: '../../src/AppBundle/{Entity,Repository}'
list_brands:
class: AppBundle\Service\ListBrands
arguments: [ '#doctrine.orm.entity_manager' ]
calls:
- method: getBrands
picture_upload:
class: AppBundle\Service\UploadPicture
arguments: ['#kernel']
src\AppBundle\Service\UploadPicture.php
<?php
namespace AppBundle\Service;
use DateTime;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpKernel\Kernel;
class UploadPicture
{
protected $kernel;
public function __construct(Kernel $kernel)
{
$this->kernel = $kernel;
}
public function uploadPicture($object, string $oldPic, string $path)
{
/** #var UploadedFile $image */
$image = $object->getImage();
$time = new DateTime('now');
if ($image) {
$imgPath = '/../web/' . $path;
$filename = $time->format('d-m-Y-s') . md5($time->format('s')) . uniqid();
$image->move($this->kernel->getRootDir() . $imgPath,$filename . '.png');
$object->setImage($path . $filename . '.png');
} else {
$object->setImage($oldPic);
}
}
}
Error: You have requested a non-existent service "picture_upload".
Calling it like this: $uploadService = $this->get('picture_upload');
You have not written how you inject / call your service, but calling $this->get() sounds like a call from within a controller. I guess this is related to the new change in Symfony and your default service config of the public attribute.
Please check the following commented lines in your configuration:
# services.yml
services:
_defaults:
autowire: true
autoconfigure: true
public: false # here you are setting all service per default to be private
AppBundle\:
resource: '../../src/AppBundle/*'
exclude: '../../src/AppBundle/{Entity,Repository}'
list_brands:
class: AppBundle\Service\ListBrands
arguments: [ '#doctrine.orm.entity_manager' ]
calls:
- method: getBrands
picture_upload:
class: AppBundle\Service\UploadPicture
arguments: ['#kernel']
public: true # you need to explicitly set the service to public
You need to mark the service as public, either per default (not recommended) or explicitly in the service definition.

Symfony 2.5 "You have requested a non-existent service "siteTest.b"

When run workspace/app_dev.php, no problem. But when I try to run workspace/app.php I get:
"You have requested a non-existent service "siteTest.b"
I dont have the first clue what am I doing wrong.
app/config/config.yml :
imports:
- { resource: parameters.yml }
- { resource: security.yml }
framework:
secret: "%secret%"
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: ~
form: ~
csrf_protection: ~
validation: { enable_annotations: true }
templating:
engines: ['twig']
default_locale: "%locale%"
trusted_hosts: ~
trusted_proxies: ~
session:
handler_id: ~
fragments: ~
http_method_override: true
src/Site/TestBundle/Resources/config/services.yml:
parameters:
siteTest.aa: Site\TestBundle\Controller\a
services:
siteTest.b:
class: %siteTest.aa%
src/Site/TestBundle/DependencyInjection/SiteTestExtension.php :
namespace Site\TestBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
class SiteTestExtension extends Extension
{
/**
* {#inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
}
}
src/Site/TestBundle/Controller/a.php :
namespace Site\TestBundle\Controller;
class a {
public function printTest() {
var_dump('Test');
exit;
}
}
src/Site/TestBundle/Controller/DefaultController.php:
namespace Site\TestBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Response;
class DefaultController extends Controller
{
public function indexAction()
{
$aaa = $this->get('siteTest.b');
exit();
}
}
you might also need to add the code below inside
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: '#TestBundle/Resources/config/services.yml' }
alternatively you can use the cookbook configurations http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class
run command php app/console cache:clear --env=prod to clear your prod cache

Symfony2 components, class instances

Question is why
$config = array(__DIR__ . '/app/config');
$locator = new Symfony\Component\Config\FileLocator($config);
$loader = new Symfony\Component\Routing\Loader\YamlFileLoader($locator);
$routes_collection = $loader->load('routes.yml');
Here $routes_collection is an instance of Symfony\Component\Routing\RouteCollection, and this code works fine.
And here
# config.yml
file_locator:
class: Symfony\Component\Config\FileLocator
arguments: ['%app_root%/app/config']
route_collection:
class: Symfony\Component\Routing\Loader\YamlFileLoader
arguments: ["#file_locator"]
calls:
- [load, ['routes.yml']]
#app.php
$routes_collection = $container->get('route_collection')
$routes_collection is an instance of Symfony\Component\Routing\Loader\YamlFileLoader and if i use it with Symfony\Component\Routing\Matcher\UrlMatcher am getting:
Argument 1 passed to Symfony\Component\Routing\Matcher\UrlMatcher::__construct() must be an instance of Symfony\Component\Routing\RouteCollection, instance of Symfony\Component\Routing\Loader\YamlFileLoader given.
Update
#Pazi ツ, but how to be if i want to use route_collection in matcher
matcher:
class: Symfony\Component\Routing\Matcher\UrlMatcher
arguments: ["#route_collection", "#context"]
If you want to take route_collection via config you need to define route_collection yaml_file_loader as the factory service of route_collection:
# config.yml
file_locator:
class: Symfony\Component\Config\FileLocator
arguments: ['%app_root%/app/config']
yaml_file_loader:
class: Symfony\Copmonent\Routing\Loader\YamlFileLoader
arguments: [ "#file_locator" ]
route_collection:
class: Symfony\Component\Routing\RouteCollection
factory_service: yaml_file_loader
factory_method: load
arguments: [ 'routes.yml' ]
This way you can do
$routes_collection = $container->get('route_collection');
Of course your service is an instance of YamlFileLoader because you configured this in the class attribute. The return value of the methods calls doesn't influence the instance type. You have to call the method in php, if you want to get the return value.
# config.yml
file_locator:
class: Symfony\Component\Config\FileLocator
arguments: ['%app_root%/app/config']
yaml_file_loader:
class: Symfony\Component\Routing\Loader\YamlFileLoader
arguments: ["#file_locator"]
#app.php
$routes_collection = $container->get('yaml_file_loader')->load('routes.yml');

SonataAdminBundle cannot import resource

I have follow error when try to enter in admin dashboard:
Cannot import resource "/var/www/autoportal/app/config/." from
"/var/www/autoportal/app/config/routing.yml". (The autoloader expected
class "App\AdminBundle\Admin\AutoAdmin" to be defined in file
"/var/www/autoportal/src/App/AdminBundle/Admin/AutoAdmin.php". The
file was found but the class was not in it, the class name or
namespace probably has a typo.)
My admin class:
namespace App\AdminBundle\Admin;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
class AutoAdmin extends Admin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('name')
->add('enabled', null, array('required' => false))
;
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('name')
->add('posts')
;
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('name')
->add('slug')
->add('enabled')
;
}
}
Service configure:
services:
app_admin.auto:
class: App\AdminBundle\Admin\AutoAdmin
tags:
- { name: sonata.admin, manager_type: orm, group: posts, label: "Auto" }
arguments:
- ~
- 'App\AutoPortalBundle\Entity\Auto'
- 'SonataAdminBundle:CRUD'
calls:
- [ setTranslationDomain, [AppAdminBundle]]
routing file:
app_auto_portal_controller:
resource: "#AppAutoPortalBundle/Controller"
type: annotation
app_auto_portal:
resource: "#AppAutoPortalBundle/Resources/config/routing.yml"
prefix: /
login:
pattern: /login
defaults: { _controller: AppAutoPortalBundle:Security:login }
login_check:
pattern: /login_check
admin:
resource: '#SonataAdminBundle/Resources/config/routing/sonata_admin.xml'
prefix: /admin
_sonata_admin:
resource: .
type: sonata_admin
prefix: /admin

Categories