I have a Symfony project where I want to inject an entity repository into a service. The service definition is in XML format.
<service id="vendorname_shop.checkout_data_manager" class="Vendorname\ShopBundle\Checkout\CheckoutDataManager">
<argument type="service" id="security.token_storage" />
<argument type="service" id="session" />
<argument type="service" id="vendorname_shop.repository.pickup_point" />
<argument type="service" id="vendorname_shop.repository.order_payment_method" />
<argument type="service" id="vendorname_shop.repository.billing_address" />
</service>
I'd like to make vendorname_shop.repository.billing_address service to be a simple entity repository (not a custom class that I wrote, but the result of
EntityManager->getRepository(Vendorname\ShopBundle\Entity\BillingAddress::class)
method call), so I used the factory syntax in the xml, but I keep recieving error messages when Symfony tries to evaluate the argument:
<service id="vendorname_shop.repository.billing_address" class="Doctrine\ORM\EntityRepository">
<factory service="doctrine.orm.entity_manager" method="getRepository" />
<argument type="expression">Vendorname\ShopBundle\Entity\BillingAddress::class</argument>
</service>
The code above gives me Unexpected character "\" around position 11.
You can try something like this:
services:
my_service_name:
class: AppBundle\Controller\MyServiceName
arguments: ["#=service('doctrine.orm.entity_manager').getRepository('AppBundle:MyEntity')"]
Then you have build a service for your repository.
public function __construct(MyEntityRepository $repository) {
$this->repository = $repository;
}
But i think there are a lot more possibilities.
http://www.zuellich.de/blog/2016/03/symfony-3-inject-entity-repository-into-service-controller.html
here is another solution. I've replaced my answer with some of that solution it is a bit better.
As Cerad said, if I use a fully qualified name, the ::class is totally useless!
In addition changing the argument type to string solved the problem!
<argument type="string">Vendorname\ShopBundle\Entity\BillingAddresss</argument>
Related
In Terminal when I try to run my created command I get the following error:
[Symfony\Component\DependencyInjection\Exception\InvalidArgumentException]]
You cannot dump a container with parameters that contain references to other services (reference to service "old_sound_rabbit_mq.split_file_producer" found in "/rabbit").
This is what happens when I run my newly created console command:
$this->getContainer()->get('split_file')->process();
I don't know why it says that You cannot dump! I don't dump anything in the project.
Is there something I'm unaware of?
EDIT
A part of my services.yml:
<parameters>
<parameter key="file_path">/var/www/path/file.xml</parameter>
<parameter key="rabbit" type="service" id="old_sound_rabbit_mq.split_file_producer" />
</parameters>
<service id="split_file" class="Acme\DemoBundle\SplitFile">
<argument>%file_path%</argument>
<argument>%rabbit%</argument>
</service>
And this is my console command class:
namespace Acme\DemoBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class ReadFileCommand extends ContainerAwareCommand
{
protected function configure()
{
$this->setName('reader:read-file');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->getContainer()->get('split_file')->process();
}
}
Parameters only have a key value. You can't add service etc to a parameter.
<service id="split_file" class="Acme\DemoBundle\SplitFile">
<argument>%file_path%</argument>
<argument type="service" id="old_sound_rabbit_mq.split_file_producer"/>
</service>
http://symfony.com/doc/current/book/service_container.html
I'd suggest switching to yml as it's less verbose
You could create an alias for old rabbit if you wanted.
After composer update, i started getting error message:
The service "swiftmailer.mailer.default.transport.real" has a dependency on a non-existent service "swiftmailer.transport.buffer"
After bit of research i found solutions:
http://error.bengtuo.com/page/13489.html
Symfony2 Monolog to Email Errors why swiftmailer.transport.real is non-existent service
Basically what they offer is to set swiftmail parameter spool: {type: memory} or create service description manually
I've added sppol to all configs: config.yml, config_test.yml, config_dev.yml but that did not helped. Then i've added entries in one of my bundles services.yml
swiftmailer.transport.simplemailinvoker:
class: Swift_Transport_SimpleMailInvoker
swiftmailer.transport.eventdispatcher:
class: Swift_Events_SimpleEventDispatcher
swiftmailer.transport.real:
class: Swift_Transport_MailTransport
arguments: [#swiftmailer.transport.simplemailinvoker, #swiftmailer.transport.eventdispatcher]
but that did not solved my problem ether.
My composer file looks like this:
http://pastebin.com/Wsfx22Lg
Any advice how to fix this?
Try my variant, it works for me:
swiftmailer.transport.simplemailinvoker:
class: Swift_Transport_SimpleMailInvoker
swiftmailer.transport.eventdispatcher:
class: Swift_Events_SimpleEventDispatcher
swiftmailer.replacementfactory:
class: Swift_StreamFilters_StringReplacementFilterFactory
swiftmailer.transport.buffer:
class: Swift_Transport_StreamBuffer
arguments: [#swiftmailer.replacementfactory]
swiftmailer.transport.real:
class: Swift_Transport_MailTransport
arguments: [#swiftmailer.transport.simplemailinvoker, #swiftmailer.transport.eventdispatcher]
Try adding this in your service.yml: worked for me
swiftmailer.transport.simplemailinvoker:
class: Swift_Transport_SimpleMailInvoker
swiftmailer.transport.eventdispatcher:
class: Swift_Events_SimpleEventDispatcher
swiftmailer.transport.buffer:
class: Swift_Transport_StreamBuffer
swiftmailer.transport.real:
class: Swift_Transport_MailTransport
arguments: [#swiftmailer.transport.simplemailinvoker, #swiftmailer.transport.eventdispatcher]
I used part of the previous answer and worked it. Hope this will work for you
The xml version of #Yury Pliashkou's answer:
<?xml version="1.0" encoding="UTF-8"?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="swiftmailer.transport.simplemailinvoker" class="Swift_Transport_SimpleMailInvoker" />
<service id="swiftmailer.transport.eventdispatcher" class="Swift_Events_SimpleEventDispatcher" />
<service id="swiftmailer.replacementfactory" class="Swift_StreamFilters_StringReplacementFilterFactory" />
<service id="swiftmailer.transport.buffer" class="Swift_Transport_StreamBuffer">
<argument type="service" id="swiftmailer.replacementfactory"></argument>
</service>
<service id="swiftmailer.transport.real" class="Swift_Transport_MailTransport">
<argument type="service" id="swiftmailer.transport.simplemailinvoker"></argument>
<argument type="service" id="swiftmailer.transport.eventdispatcher"></argument>
</service>
</services>
</container>
From monolog.xml:
<service id="monolog.logger" parent="monolog.logger_prototype" public="false">
<argument index="0">app</argument>
</service>
<service id="logger" alias="monolog.logger" />
<service id="monolog.logger_prototype" class="%monolog.logger.class%" abstract="true">
<argument /><!-- Channel -->
</service>
How do I accomplish the same overriding of the 0th argument in Yaml?
My colleague created a bundle that allows you to easily convert from XML to YML and it came up with:
services:
monolog.logger:
public: false
arguments: { index_0: app }
monolog.logger_prototype:
class: %monolog.logger.class%
arguments: ['']
logger: #monolog.logger
Never would have guessed that.
One of defining logger with custom channel as service way:
# app/config/config.yml
monolog:
channels: [custom_channel]
When in a controller:
$logger = $this->get('monolog.logger.custom_channel');
or when defining a service:
services:
app.logger.custom_channel:
parent: monolog.logger.custom_channel
Does anyone know how you can extend the Mailer class in the FOSUserBundle?
I am implementing a very basic parental email check (all the validation is done on the form to force a parent's email to be entered), if the parent email field is populated on the user entity then it shoudl send the email to that address not the user's email.
I have tried the following so far:
namespace SSERugby\UserBundle\Mailer;
use FOS\UserBundle\Mailer\Mailer as BaseMailer;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Component\Routing\RouterInterface;
class Mailer extends BaseMailer
{
public function sendConfirmationEmailMessage(UserInterface $user)
{
$email = $user->getEmail();
$parentEmail = $user->getParentEmail();
if(isset($parentEmail)&&(trim($parentEmail)!='')){
$email = $parentEmail;
}
$template = $this->parameters['confirmation.template'];
$url = $this->router->generate('fos_user_registration_confirm', array('token' => $user->getConfirmationToken()), true);
$rendered = $this->templating->render($template, array(
'user' => $user,
'confirmationUrl' => $url
));
$this->sendEmailMessage($rendered, $this->parameters['from_email']['confirmation'], $email);
}
}
It seems to just ignore the overridden class though and use the default, i have cleared the cache before testing.
Thanks
You should create new service with extended mail class (in src\SSERugby\UserBundle\Resources\config\services.xml) like:
<service id="my_mailer" class="SSERugby\UserBundle\Mailer\Mailer" public="true">
<argument type="service" id="mailer" />
<argument type="service" id="router" />
<argument type="service" id="templating" />
<argument type="collection">
<argument key="confirmation.template">%fos_user.registration.confirmation.template%</argument>
<argument key="resetting.template">%fos_user.resetting.email.template%</argument>
<argument key="from_email" type="collection">
<argument key="confirmation">%fos_user.registration.confirmation.from_email%</argument>
<argument key="resetting">%fos_user.resetting.email.from_email%</argument>
</argument>
</argument>
</service>
and then in app/config/config.yml use this service as default:
fos_user:
# ...
service:
mailer: my_mailer
FYI: I copied all service's arguments from FOSUserBundle default mailer config. You can add your own params to it. Also you can read about custom mailers at https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/emails.md
1. Passing parameters into the service?
If not already defined in the services.xml (or yaml), is the only way to pass parameter(s) into service is:
$container->setParameter('loader', $loader);
$container->get('myservice');
I suppose this way loader will be available to ALL services, not just "myservice"?
2. Passing an array of objects into the service?
The Template/DelegatingEngine class takes an array of engine object into the constructor, and I dont know how should I define that in the xml file:
public function __construct(array $engines = array())
{
$this->engines = array();
foreach ($engines as $engine) {
$this->addEngine($engine);
}
}
What should I put into the
<service id="myCustomeFramework.TemplateEngine" class="path\to\DelegateEngine" scope="prototype">
<argument>how can i pass an array of engines here?</argument>
</service>
Answer 1
Yes, it will be available for all services that uses that parameter and that are called after setting the parameter.
Answer 2
For passing an array as an argument to a service using xml you have to do it in this way:
<service id="myCustomeFramework.TemplateEngine" class="path\to\DelegateEngine" scope="prototype">
<argument type="collection">
<argument key="key">value</argument>
<argument key="key">value</argument>
<argument key="key">value</argument>
</argument>
</service>