Symfony 4 не может ввести скалярное значение в службу

У меня класс ff:

namespace App\Component\Notification\RealTimeNotification;

use App\Component\Notification\NotificationInterface;

class EmailNotification implements NotificationInterface
{   
    private $logNotification;
    private $mailer;
    private $engine;

    // This will appear on From field on Email.
    private $mailerFrom;

    public function __construct(LogNotification $logNotification, \Swift_Mailer $mailer, \Twig_Environment $twig, string $from)
    {
        $this->logNotification = $logNotification;
        $this->mailer = $mailer;
        $this->twig = $twig;

        $this->mailerFrom = $mailerFrom;
    }

    public function send(array $options): void
    {   
        // Resolve options
        $this->resolveOptions($options);

        $sendTo = $options['sendTo'];
        $subject = $options['subject'];

        $template = $options['template'];
        $data = $options['data'];
        $body = $this->createTemplate($template, $data);

        $this->sendEmail($sendTo, $subject, $body);
    }

    protected function sendEmail($sendTo, $subject, $body): void
    {
        dump($this->mailerFrom);
        $message = (new \Swift_Message())
            ->setSubject($subject)
            ->setFrom($this->mailerFrom)
            ->setTo($sendTo)
            ->setBody($body, 'text/html')
        ;

        $this->mailer->send($message);
    }

    protected function createTemplate($template, $data): string
    {
        return $this->twig->render($template, $data);
    }

    protected function resolveOptions(array $options): void
    {

    }

    protected function createLog(array $email): void
    {
        $message = 'Email has been sent to: ' . $email;

        $this->logNotification->send([
            'message' => $message,
        ]);
    }
}

Я попытался вручную связать все аргументы следующим образом:

# Notification
app.log_notification:
    class: App\Component\Notification\RealTimeNotification\LogNotification

app.email_notification:
    class: App\Component\Notification\RealTimeNotification\EmailNotification
    decorates: app.log_notification
    decoration_inner_name: app.log_notification.inner
    arguments:
        $logNotification: '@app.log_notification.inner'
        $mailer: '@mailer'
        $twig: '@twig'
        $from: '%mailer_from%'

Однако когда я запускаю приложение, оно выдает исключение:

Cannot autowire service "App\Component\Notification\RealTimeNotification\EmailNotification": argument "$from" of method "__construct()" must have a type-hint or be given a value explicitly

Почему происходит это событие?

Спасибо!

Это потому, что вы пытаетесь внедрить свое EmailNotification в еще одну службу, используя подсказку типа EmailNotification. Таким образом, autowire ищет в контейнере идентификатор службы, соответствующий имени класса. Он не будет автоматически использовать app.email_notification. Таким образом, он пытается создать новую службу и терпит неудачу на скаляре. Если вы используете autowire, вам больше не нужны идентификаторы служб, такие как app.email_notification. Просто используйте имя класса. И если вы действительно хотите сохранить свой идентификатор, добавьте псевдоним. Все это задокументировано. Также куча вопросов на ту же тему.

Cerad 18.03.2018 13:18

@Cerad, ты прав. Вот как я это сделал. Спасибо!

iamjc015 19.03.2018 13:21
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
3
2
1 033
2

Ответы 2

Автосоединение работает только тогда, когда ваш аргумент является объектом. Но если у вас есть скалярный аргумент (например, строка), его нельзя автоматически подключить: Symfony выдаст явное исключение.

Вы должны Аргументы подключения вручную и явно настроить службу, например:

# config/services.yaml
services:
    # ...

    # same as before
    App\:
        resource: '../src/*'
        exclude: '../src/{Entity,Migrations,Tests}'

    # explicitly configure the service
    App\Updates\SiteUpdateManager:
        arguments:
            $adminEmail: '[email protected]'

Thanks to this, the container will pass [email protected] to the $adminEmail argument of __construct when creating the SiteUpdateManager service. The other arguments will still be autowired.

Надеюсь на эту помощь

Ответ @Matteo великолепен! Вы даже можете отбросить определение службы и делегировать привязка параметровначиная с Smyfony 3.4 + / 2018 +:

 # config/services.yaml
 services:
     _defaults:
         bind:
             $adminEmail: '[email protected]'

     # same as before
     App\:
         resource: '../src/*'

Хотите больше примеров и логики? Найдите здесь: https://www.tomasvotruba.cz/blog/2018/01/22/how-to-get-parameter-in-symfony-controller-the-clean-way/#change-the-config

Мне не нужно использовать app.email_notification, вместо этого я использую полное имя класса.

iamjc015 19.03.2018 13:29

Нет, здесь нет аргументов. Это просто способ еще больше сократить объем написания. Да, вы можете использовать подсказку напрямую. Именованный сервис не нужен, начиная с Symfony 2.8 и autowiring.

Tomas Votruba 19.03.2018 14:17

Другие вопросы по теме