Symfony2 - Inject a service into SonataAdmin
-
27-06-2021 - |
Pregunta
I'd like to get a db connection from within a SonataAdmin class' configureFormFields()
For sure this doesn't work
protected function configureFormFields(FormMapper $formMapper)
{
$mycnx = $this->get('doctrine.dbal.mycnx_connection');
//...
I need it for my extension of Sonata/UserBundle/Admin/Entity/UserAdmin
How can I call a service from this class ?
The context:
I need to have a choice field (company) whose choices come from an other connection (from a stored procedure).
Solución
What you have to do is:
- create a service getting the connection injected to get companies from
- create a custom field
- register it as a service and inject the first service in constructor
supply the choices to the field
public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( #...
Then you'll be able to simply use it from configureFormFields()
with:
->add('company', 'company')
Otros consejos
How to use a second dbal connection to supply choices for a form field
You can actually have this a little easier and with less code involved...
Configuration
Your configuration looks somewhat like this if you already have setup a second connection doctrine.dbal.mycnx_connection
.
app/config/config.yml
doctrine:
dbal:
connections:
default:
driver: "%database_driver%"
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
mycnx_connection: # credentials for 2nd connection
driver: "pdo_mysql"
host: "%database_host_2%"
port: "%database_port_2%"
dbname: "%database_name_2%"
user: "%database_user_2%"
password: "%database_password_2%"
charset: UTF8
default_connection: default
Now if you haven't already ... configure a second entity/document manager that is using this connection:
app/config/config.yml
doctrine:
# dbal, ...
orm:
entity_managers:
default:
connection: default
mappings:
AcmeDemoBundle: ~
AcmeStoreBundle: ~
company: # <- setup a second em using the customer connection
connection: customer
mappings:
AcmeCompanyBundle: ~
default_entity_manager: default
... this may look like much to this point but it really isn't ... as everything described above should already be present in your application if you have a second dbal connection.
I just wanted to make it really obvious for others.
You now have two services available that reflect your two entity-managers:
@doctrine.orm.entity_manager.default
( ... which is aliased to@doctrine.orm.entity_manager
)@doctrine.orm.entity_manager.company
The Entity Field-Type
Now all that's left for you to do is use the entity field-type and configure it to use the entity-manager using the company
connection.
Acme/YourBundle/Form/Type/YourType.php
use Doctrine\ORM\EntityRepository;
// ...
$builder->add('users', 'entity', array(
'class' => 'AcmeCompanyBundle:Company',
'em' => 'doctrine.orm.entity_manager.company', // <- non-default em here
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('company')
->orderBy('company.name', 'ASC');
},
));
That's it ... while you may still want to make your form a service ... you don't have to inject anything.
You don't need to use the EntityRepository $er
part in 'query_builder'
... you can just return a QueryBuilder instance if you don't want to create the repository for your companies.