While updating from Symfony 3.4 to 4.1, when I php bin/console, I got the following error.
I want to take parameters in a url reference way.
What is the cause?
https://symfony.com/blog/new-in-symfony-4-1-getting-container-parameters-as-a-service
Error code
Unused binding "$projectDir" in service "common.parameterService".
config/services.yaml
parameters:
parameter_name: XXX
services:
_defaults:
autowire: false
autoconfigure: false
public: false
bind:
$projectDir: '%kernel.project_dir%'
common.parameterService:
class: AppBundle\Model\Service\ParameterService
arguments: [ "#service_container" ]
AppBundle/Model/Service/ParameterService.php
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use AppBundle\Model\Service\BaseService;
/**
*
*/
class ParameterService extends BaseService
{
private $params;
public function __construct(ParameterBagInterface $params)
{
$this->params = $params;
}
/**
*
* #param string
* #return mixed
*/
public function getParameter()
{
return $this->params->get('parameter_name');
}
It means you have declared this:
bind:
$projectDir: '%kernel.project_dir%'
but have not injected the $projectDir in the ParameterService nor in any other services in that file.
You can delete these two lines:
bind:
$projectDir: '%kernel.project_dir%'
Related
I have a few problems loading use_cases in my project using symfony dependency injection.
The following code belongs to RegisterUserController class.
<?php
namespace App\Infrastructure\Controller\User;
use App\Application\UseCase\User\RegisterUserUseCase;
use Symfony\Component\HttpFoundation\Request;
/**
* Class RegisterUserController
*
* #package App\Infrastructure\Controller\User
* #author Ismael Moral <jastertdc#gmail.com>
*/
final class RegisterUserController
{
/**
* #var RegisterUserUseCase
*/
protected $registerUserUseCase;
/**
* RegisterUserController constructor.
*
* #param RegisterUserUseCase $registerUserUseCase
*/
public function __construct(
RegisterUserUseCase $registerUserUseCase
) {
$this->registerUserUseCase = $registerUserUseCase;
}
}
This is my services.yml where I have defined all the services in my project.
parameters:
databaseWriterDsn: '%env(DB_WRITER_DSN)%'
databaseWriterUsername: '%env(DB_WRITER_USERNAME)%'
databaseWriterPassword: '%env(DB_WRITER_PASSWORD)%'
services:
_defaults:
autowire: false # Automatically injects dependencies in your services.
autoconfigure: false # Automatically registers your services as commands, event subscribers, etc.
PdoWriter:
class: PDO
arguments: ['%databaseWriterDsn%', '%databaseWriterUsername%', '%databaseWriterPassword%']
MysqlPdoUserWriterRepository:
class: App\Infrastructure\Repository\User\MysqlPdoUserWriterRepository
arguments: ['#PdoWriter']
PasswordFactory:
class: App\Infrastructure\Factory\User\PasswordFactory
arguments: []
UsernameFactory:
class: App\Infrastructure\Factory\User\UsernameFactory
arguments: []
UuidFactory:
class: App\Shared\Infrastructure\UuidFactory
arguments: []
UserFactory:
class: App\Infrastructure\Factory\User\UserFactory
arguments: ['#UuidFactory', '#UsernameFactory', '#PasswordFactory']
RegisterUserUseCase:
class: App\Application\UseCase\User\RegisterUserUseCase
arguments: ['#MysqlPdoUserWriterRepository', '#UserFactory']
RegisterUserController:
class: App\Infrastructure\Controller\User\RegisterUserController
arguments: ['#RegisterUserUseCase']
tags: ['controller.service_arguments']
This is the error I get when I'm trying to do a curl request to /user/register/.
Controller "App\Infrastructure\Controller\User\RegisterUserController" has required constructor arguments and does not exist in the container. Did you forget to define such a service?
If I changed the controller definition using this, I can get it to work. So I have to specificate fullnamespace for controller definition.
App\Infrastructure\Controller\User\RegisterUserController:
class: App\Infrastructure\Controller\User\RegisterUserController
arguments: ['#RegisterUserUseCase']
tags: ['controller.service_arguments']
I have Symfony 4 project.
And here is the service. It is marked as public and it is in separate cooperation.yml which is connected to project:
services:
App\Matcher\CooperationSiteConfigMatcher:
public: true
Here is class itself
<?php
namespace App\Matcher;
use App\Factory\CooperationOptionsFactory;
use App\Options\Cooperation\CooperationOptions;
use App\Resolver\SiteResolver;
use App\Factory\Exception\MissingCooperationOptionsException;
use Assert\AssertionFailedException;
class CooperationSiteConfigMatcher
{
const TYPE_PARTNERSHIP = 'partnership';
const TYPE_FRANCHISE = 'franchise';
/**
* #var CooperationOptionsFactory
*/
private $optionsFactory;
/**
* #var SiteResolver
*/
private $siteResolver;
/**
* CooperationSiteConfigMatcher constructor.
* #param CooperationOptionsFactory $optionsFactory
* #param SiteResolver $siteResolver
*/
public function __construct(CooperationOptionsFactory $optionsFactory, SiteResolver $siteResolver)
{
$this->optionsFactory = $optionsFactory;
$this->siteResolver = $siteResolver;
}
/**
* #param $group
* #return CooperationOptions
* #throws AssertionFailedException
* #throws MissingCooperationOptionsException
*/
public function matchOptionsByGroupAndSite($group)
{
$domainAliasKey = $this->siteResolver->resolve();
return $this->optionsFactory->createForSite($group, $domainAliasKey);
}
}
Global service.yml base configuration:
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
App\:
resource: '%kernel.root_dir%/*'
exclude: '%kernel.root_dir%/{Entity,Migrations,Tests,Kernel.php,Form/EventListener,Request}'
But I receive an error:
The "App\Matcher\CooperationSiteConfigMatcher" service or alias has
been removed or inlined when the container was compiled. You should
either make it public or stop using the container directly and use
dependency injection instead.
The problem disappears when I move this service to global services.yml.
My custom services.yml is loaded via CooperationExtension class:
class CooperationExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$config = $this->processConfiguration(new CooperationConfiguration(), $configs);
$loader = new YamlFileLoader(
$container,
new FileLocator(__DIR__ . '/../Resources/config/services')
);
$loader->load('cooperation.yaml');
$this->generateCooperationServices($config, $container);
}
public function getAlias()
{
return 'cooperation';
}
public function getXsdValidationBasePath()
{
return false;
}
public function getNamespace()
{
return "cooperation/schema";
}
}
Extension registered in Kernel.php configureContainer method:
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void
{
$cooperationExtension = new CooperationExtension();
$container->registerExtension($cooperationExtension);
$container->loadFromExtension($cooperationExtension->getAlias());
$container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php'));
// Feel free to remove the "container.autowiring.strict_mode" parameter
// if you are using symfony/dependency-injection 4.0+ as it's the default behavior
$container->setParameter('container.autowiring.strict_mode', true);
$container->setParameter('container.dumper.inline_class_loader', true);
$confDir = $this->getProjectDir().'/config';
$loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/{packages}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob');
}
Symfony sees cooperation.yml. I checked it when removed some other services from it and exception appeared.
But somehow it do not merge it correctly with global services.yml and I don't see this service as public when load it from cooperation.yml
I am a beginner on Symfony.
I am trying to create a class to use my database (mysql). But I can not succeed. Can you help me ?
Here is my current class:
<?php
namespace App\Database;
use Doctrine;
use Doctrine\DBAL\Connection;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class DatabaseApi extends AbstractController
{
/**
* #var Connection
*/
protected $database = null;
protected static $instance = null;
/**
* DatabaseApi constructor.
*/
protected function __construct()
{
$database = $this->container->get('database');
$this->database = $database;
}
public static function getInstance()
{
self::$instance = new self();
return self::$instance;
}
private function __clone()
{
}
/**
* #param $authentication_key
* #return mixed
* #throws Doctrine\DBAL\DBALException
*/
public function select_authentication_key($authentication_key)
{
$auth_key_query = $this->database->prepare('CALL Verify_authentication_key(:authentication_key)');
$auth_key_query->bindValue('authentication_key', $authentication_key);
$auth_key_query->execute();
$results = $auth_key_query->fetchAll(\PDO::FETCH_ASSOC);
return $results[0];
}
}
I tried to create it with everything I could find on the Internet. Unfortunately, I get an error "Call to a member function get() on null".
There is my services.yaml file :
parameters:
database_connection: default
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones
database:
alias: doctrine.dbal.%database_connection%_connection
And is is how I try to call the fonction :
$database = DatabaseApi::getInstance();
$result = null;
try{
$result = $database->select_authentication_key("1111-1111-1111-1111");
}catch (Exception $e){
print($e);
}
print_r($result);
I use symfony2 and SonataAdminBundle, SonataMediaBundle and SonataClassificationBundle
Now I want custmize setting for admin panel, but I have this error.
[Symfony\Component\Config\Exception\FileLoaderLoadException]
Catchable Fatal Error: Argument 5 passed to Sonata\MediaBundle\Admin\BaseMe
diaAdmin::__construct() must implement interface Sonata\ClassificationBundl
e\Model\CategoryManagerInterface, none given, called in /Users/whitebear/Codin
gWorks/httproot/myapp/app/cache/de_/appDevDebugProjectContaine_.php on l
ine 9494 and defined in . (which is being imported from "/Users/whitebear/Codi
ngWorks/httproot/myapp/app/config/routing.yml").
What I have done is two things.
made DependencyInjection file
Application/Sonata/MediaBundle/DependencyInjection/ApplicationSonataMediaExtension.php
<?php
namespace Application\Sonata\MediaBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
/**
* This is the class that loads and manages your bundle configuration
*
* To learn more see {#link http://symfony.com/doc/current/cookbook/bundles/extension.html}
*/
class ApplicationSonataMediaExtension extends Extension
{
/**
* {#inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
}
}
then made services.yml for admin
Application/Sonata/MediaBundle/Resources/config/services.yml
#Disable gallery & media menu from admin panel
services:
sonata.media.admin.media:
class: %sonata.media.admin.media.class%
tags:
- { name: sonata.admin, manager_type: orm, show_in_dashboard: false, label_catalogue: %sonata.media.admin.media.translation_domain% , label_translator_strategy: sonata.admin.label.strategy.underscore }
arguments:
- ~
- %sonata.media.admin.media.entity%
- %sonata.media.admin.media.controller%
- "#sonata.media.pool"
- %sonata.classification.manager.category% # add here.
calls:
- [setModelManager, ["#sonata.media.admin.media.manager"]]
- [setTranslationDomain, [%sonata.media.admin.media.translation_domain%]]
- [setTemplates, [{ inner_list_row: SonataMediaBundle:MediaAdmin:inner_row_media.html.twig , base_list_field: SonataAdminBundle:CRUD:base_list_flat_field.html.twig , list: SonataMediaBundle:MediaAdmin:list.html.twig , edit: SonataMediaBundle:MediaAdmin:edit.html.twig }]]
sonata.media.admin.gallery:
class: %sonata.media.admin.gallery.class%
tags:
- { name: sonata.admin, manager_type: orm, show_in_dashboard: false, label_catalogue: %sonata.media.admin.media.translation_domain% , label_translator_strategy: sonata.admin.label.strategy.underscore }
arguments:
- ~
- %sonata.media.admin.gallery.entity%
- %sonata.media.admin.gallery.controller%
- "#sonata.media.pool"
calls:
- [setTranslationDomain, [%sonata.media.admin.media.translation_domain%]]
- [setTemplates, [{ list: SonataMediaBundle:GalleryAdmin:list.html.twig }]]
in Sonata\MediaBundle\Admin\BaseMediaAdmin
abstract class BaseMediaAdmin extends AbstractAdmin
{
/**
* #var Pool
*/
protected $pool;
/**
* #var CategoryManagerInterface
*/
protected $categoryManager;
/**
* #param string $code
* #param string $class
* #param string $baseControllerName
* #param Pool $pool
* #param CategoryManagerInterface $categoryManager
*/
public function __construct($code, $class, $baseControllerName, Pool $pool, CategoryManagerInterface $categoryManager)
{
parent::__construct($code, $class, $baseControllerName);
$this->pool = $pool;
$this->categoryManager = $categoryManager;
}
Thanks to #mdma
I figured out I must path 5th parameters as CategoryManagerInterface to BaseMediaAdmin constructor.
then I updated the service.yml but I have error like this.
[Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException]
The service "sonata.media.admin.media" has a dependency on a non-existent p
arameter "sonata.classification.manager.category". Did you mean one of thes
e: "sonata.classification.manager.category.class", "sonata.classification.m
anager.tag.class", "sonata.classification.manager.context.class", "sonata.c
lassification.manager.tag.entity", "sonata.classification.manager.category.
entity", "sonata.classification.manager.context.entity", "sonata.classifica
tion.admin.category.class"?
It solved.
I changed this sentence inservices.yml
- %sonata.classification.manager.category% to "#sonata.classification.manager.category"
The error say : Argument 5 doesn't exist in Sonata\MediaBundle\Admin\BaseMediaAdmin::__construct()
So, look at arguments in you sonata.media.admin.media service configuration. There are only 4 arguments. You need to add the 5th.
In bundle config (https://github.com/sonata-project/SonataMediaBundle/blob/master/Resources/config/doctrine_orm_admin.xml), there are 5 arguments :
<argument/>
<argument>%sonata.media.admin.media.entity%</argument>
<argument>%sonata.media.admin.media.controller%</argument>
<argument type="service" id="sonata.media.pool"/>
<argument type="service" id="sonata.media.manager.category" on-invalid="null"/>
So, I think you can add #sonata.media.manager.category as 5th argument.
I need inject parameter in repository, I try add calls to service repo but my call function not call when I call some function from my repo
app.repository.file:
class: "%app.repository.file.class%"
factory_service: doctrine.orm.default_entity_manager
factory_method: getRepository
arguments:
- "%app.entity.file.class%"
calls:
- [setParam,['%md5_suffix%']]
setParam not call
private $param;
public function setParam($param)
{
$this->param = $param;
}
param have null
and I try use JMSDiExtraBundle
/**
* #DI\InjectParams({
* "param" = #DI\Inject("%md5_suffix%"),
* })
*/
public function setParam($param)
{
$this->param = $param;
}
but have in property %md5_suffix% like string, not property from parameters.yml :)
how to inject parameter from parameters yml in repo ?
Factory_service is deprecated in 2.8. Instead, try using something like:
app.repository.file:
class: Doctrine\ORM\EntityRepository
factory: ['#doctrine.orm.entity_manager', getRepository]
arguments:
- "%app.entity.file.class%"
calls:
- [setParam,['%md5_suffix%']]
I create another service
economy.param_helper:
class: "%economy.param_helper.class%"
arguments:
- "%md5_suffix%"
and inject this service in repo like this
/**
* #var ParamHelper
*/
private $param;
/**
* #DI\InjectParams({
* "param" = #DI\Inject("economy.param_helper"),
* })
*/
public function setParam(ParamHelper $param)
{
$this->param = $param;
}
and call $md5Suffix = $this->param->getMd5Suffix();
But I'am not sure this is right way