I have the class, it declare as service. When I get() my service I run some method and this method require two params what I want to let user configure in config.yml. How I can get these parameters in this class? Maybe exist some way to do this in my service definition? Or I need extend my class from ContainerAware (if I am right its bad practice)? Thanks!
You can inject parameters into your service using %param_name% syntax
services.yml
services:
your_service:
class: Acme\DemoBundle\YourClass
arguments: [#some.other.service, %my_parameter%]
parameters.yml
parameters:
my_parameter: my_value
You can use call them using the constructor
acme.your_service:
class: Acme\DemoBundle\YourService
arguments: [%param1%]
in the class
class YourService {
protected $param1;
public function __construct($param1) {
$this->param1 = $param1;
}
}
Related
Since Sonata\PageBundle\Admin\BlockAdmin is #final i should not extend from it. In UPGRADE-3x.md i can see that i should use decoration.
I am trying to this by decorating this final class with App\Sonata\PageBundle\Admin\PageAdmin.
services.yaml configuration:
parameters:
sonata.page.admin.page.class: App\Sonata\PageBundle\Admin\PageAdmin
services:
Sonata\PageBundle\Admin\PageAdmin:
alias: sonata.page.admin.page
App\Sonata\PageBundle\Admin\PageAdmin:
decorates: Sonata\PageBundle\Admin\PageAdmin
Decorator App\Sonata\PageBundle\Admin\PageAdmin body looks like this (i just invoke all the methods from final class in my decorator): https://gist.github.com/AVAW/910604534684eedb228f71df1d7deb40
But i get error:
Is there any possible way to decorate this final service or I am doing something wrong?
I am using:
sonata-project/admin-bundle: 3.107.3
sonata-project/page-bundle: 3.26.0
symfony: 4.4.41
Did you try to remove the alias and directly use the sonata service name in the "decorate" ? like this :
services:
App\Sonata\PageBundle\Admin\PageAdmin:
decorates: 'sonata.page.admin.page'
I want to une the class Doctrine\ORM\Tools\Pagination\Paginator in a service in symfony, so the service return an instance for this class does not exist. with best practice shoud i pass the class directly or create a service who return an instance of this class.
I suggest to create a service using Factory Method pattern to instantiate the Paginator class with required params (Query/QueryBuilder and fetchJoinCollection) and inject it into your class. Using this approach will help you to mock the Paginator object while unit testing your service.
Create a private Service as parametre
services:
your.service.name:
class: AppBundle\Services\YourClassName
arguments: ['#doctrine.services.paginator']
doctrine.services.paginator:
class: Doctrine\ORM\Tools\Pagination\Paginator
public: false
I have service PgHistService in subdirectory Service in DbExtensionBundle:
namespace Iba\DbExtensionBundle\Service;
class PgHistService { ...}
This service is defined in bundles's services.yml and can be sucessfully included in a controller via $this->get('pghist.service'):
parameters:
pghist.service.class: Iba\DbExtensionBundle\Service\PgHistService
services:
pghist.service:
class: %pghist.service.class%
arguments:
entityManager: "#doctrine.orm.entity_manager"
Now I want to inject it with JMS\DIExtraBundle in doctrine entity listener:
namespace Iba\DbExtensionBundle\Entity;
use JMS\DiExtraBundle\Annotation as DI;
class BaseEntityListener {
/** #DI\Inject("pghist.service") */
public $pgHist;
}
Variable pgHist is always null. What am I doing wrong, please? I tried to set this in config.yml but it doesn't work either:
jms_di_extra:
locations:
all_bundles: false
bundles: [DbExtensionBundle]
directories: ["%kernel.root_dir%/../vendor/iba/db-extension-bundle/Iba/DbExtensionBundle/Service"]
Jason Roman is right, thank you.
If you want to use JMS\DiExtraBunde together with entity listener, you have to use DIExtraBundle own system of invoking listener via annotation #DoctrineListener in listener instead of Doctrine standard one #EntityListeners in the entity.
I am trying to implement a custom repository class in symfony2, and I want it to extend EntityRepository class. I am having trouble with passing the getting arguments to the parent (i.e. EntityRepository) constructor. This is the signiture of parent constructor:
public function __construct($em, Mapping\ClassMetadata $class)
So I had to add this to my services.yml file, in order to get the arguments:
parameters:
user_provider.class: Untitled\F5Bundle\Security\UserRepository
services:
user_meta_data:
class: Doctrine\ORM\Mapping\ClassMetaData
arguments:
name: "Untitled\F5Bundle\Entity\User"
user_provider:
class: "%user_provider.class%"
arguments:
entityManager: "#doctrine.orm.entity_manager"
meta_data: "#user_meta_data"
And I also added the annotation tag to my User class (which I'm not sure if it was neccessary)
Now when I run it, it raises an error. the message says:
FatalErrorException: Error: Class 'Doctrine\ORM\Mapping\ClassMetaData' not found
in /mnt/data/Projects/F5/app/cache/dev/appDevDebugProjectContainer.php line 2749
(/mnt/data/Projects/F5/ is where I keep the code)
I don't get it. What's wrong here? What am I doing wrong?
Metadata is obtained with the MetadataFactory. As an example you can see how it works in EntityManager.
public function getClassMetadata($className)
{
return $this->metadataFactory->getMetadataFor($className);
}
You can retrieve you repository as service as well. Look at this question.
You don't need to inject these constructor arguments yourself, just specify which repository class you want to use:
/**
* #Entity(repositoryClass="MyProject\UserRepository")
*/
class User
{
...
}
See also http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/annotations-reference.html#entity
You miss typed classname "ClassMetaData" should be ClassMetadata
class: Doctrine\ORM\Mapping\ClassMetadata
In my Symfony2 controller, this works fine:
$uploadManager = $this->get('upload.upload_manager');
but when I move it to a custom Listener:
use Doctrine\ORM\Event\LifecycleEventArgs;
use Acme\UploadBundle\Upload\UploadManager;
class PersonChange
{
public function postRemove(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
$entityManager = $args->getEntityManager();
$uploadManager = $this->get('ep_upload.upload_manager');
echo "the upload dir is " . $uploadManager->getUploadDir();
}
}
I get an error:
Fatal error: Call to undefined method Acme\MainBundle\Listener\PersonChange::get() in /home/frank/...
I know I must need a use statement but don't know what to use.
Update: Defining controllers as services is no longer officially recommended in Symfony.
The get() method in the Controller class is just a helper method to get services from the container, and it was meant to get new Symfony2 developers up to speed faster. Once people get comfortable with the framework and dependency injection, it's recommended to define controllers as services and inject each required service explicitly.
Since your PersonChange class is not a controller and doesn't extend the Controller class, you don't have that get() helper method. Instead, you need to define your class as a service and inject needed services explicitly. Read the Service Container chapter for details.
As I ran into the exact same problem maybe I can help
What Elnur said is perfectly fine and I'll just try to pop up a real life example.
In my case I wanted to access
$lucenemanager = $this->get('ivory.lucene.manager')
Even by extending the controller I couldn't get it to work while the controller does access the container (I still did not understand why)
In config.yml my listener (searchindexer.listener) is declared as follow :
services:
searchindexer.listener:
class: ripr\WfBundle\Listener\SearchIndexer
arguments:
luceneSearch: "#ivory_lucene_search"
tags:
- { name: doctrine.event_listener, event: postPersist }
A service (ivory.lucene.search) is passed as argument in my service/listener.
Then in my class
protected $lucenemanager;
public function __construct($luceneSearch)
{
$this->lucenemanager = $luceneSearch;
}
Then you can use the get method against $this
An approach that always works, despite not being the best practice in OO
global $kernel;
$assetsManager = $kernel->getContainer()->get('acme_assets.assets_manager');
If you need to access a Service, define it in the class constructor:
class PersonChange{
protected $uploadManager;
public function __construct(UploadManager $uploadManager){
$this->uploadManager = $uploadManager;
}
// Now you can use $this->uploadManager.
}
Now you can pass the Service as argument when calling the class (example 1) or define the clas itself as a Service (recommended, example 2)
Example 1:
use Acme\PersonChange;
class appController{
function buzzAction(){
$uploadManager = $this->get('upload.upload_manager');
$personChange = new PersonChange($uploadManager);
Example 2 (better):
Define PersonChange as a Service itself, and define the other Service as an argument in services.yml file:
# app/config/services.yml
services:
upload.upload_manager:
class: AppBundle\uploadManager
PersonChange:
class: AppBundle\PersonChange
arguments: ['#upload.upload_manager']
In this way, you don't have to bother with the upload_manager service in the Controller, since it's implicitely passed as an argument for the constructor, so your Controller can be:
class appController{
function buzzAction(){
$personChange = $this->get('PersonChange');