Factory – problém s __construct()

Newer
Člen | 47
+
0
-

Hoj, rozhodl jsem se udělat si továrnu na zasílání mailů s latte šablonou, ale tracy hlásí:

Service of type Nette\Bridges\ApplicationLatte\TemplateFactory needed by $templateFactory in __construct() not found. Did you add it to configuration file?

někdo nějaký tip co jsem opoměl?

<?php
declare(strict_types=1);

namespace App\CoreModule\Factory;

use Nette\Application\LinkGenerator;
use Nette\Application\UI\Template;
use Nette\Bridges\ApplicationLatte\TemplateFactory;
use Nette\Mail\Message;

class LatteMailFactory
{
    /** @var LinkGenerator */
    private $linkGenerator;

    /** @var TemplateFactory */
    private $templateFactory;

    public function __construct(LinkGenerator $linkGenerator, TemplateFactory $templateFactory)
    {
        $this->linkGenerator = $linkGenerator;
        $this->templateFactory = $templateFactory;
    }
atd
}

services:
	- App\CoreModule\Factory\LatteMailFactory

Edit 1) Tohle funguje, proč nefunguje verze s konstruktorem?

class LatteMailFactory
{
    /** @var LinkGenerator */
    private $linkGenerator;

    /** @var Nette\Bridges\ApplicationLatte\TemplateFactory @inject*/
    private $templateFactory;

    public function __construct(LinkGenerator $linkGenerator )
    {
        $this->linkGenerator = $linkGenerator;
    }
}

Edit 2) Nefunguje, jen tracy nedetekovala chybu. Chyba: call member function on null při volání na templateFactory, takze neni injected..

Editoval Newer (14. 2. 2021 20:10)

galab
Backer | 74
+
+1
-

V mailech používám Nette\Application\UI\ITemplateFactory

Newer
Člen | 47
+
0
-

To šlape, díky, ačkoli mi phpstorm hlasí že je to deprecated. Já jsem ten Nette\Bridges\ApplicationLatte\TemplateFactory našel přímo v dokumentaci pro nette 3.0 …

galab
Backer | 74
+
0
-

Jo, to je pro 3.0. Tys asi jel podle docky pro 3.1

Newer
Člen | 47
+
0
-

jel jsem podle https://doc.nette.org/cs/mail

a verzi mam 3.0.4

galab
Backer | 74
+
+1
-

Hmm, 3.07 nabízí Nette\Bridges\ApplicationLatte\TemplateFactory, nevím. Někdo zkušenější se musí vyjádřit.
3.04 určitě nepoužívej, je tam chybka… Minimálně 3.06

Elvis77
Člen | 4
+
0
-

Potvrzuji podivné chování třídy Nette\Bridges\ApplicationLatte\TemplateFactory.
Používám PHP 7.4 a Nette 3.1.

Příklad funkčního řešení:

Továrnička
Zde deklaruji že TemplateFactory je třída Nette\Application\UI\TemplateFactory.
Pokud v továrničce použiji třídu Nette\Bridges\ApplicationLatte\TemplateFactory tak to nefunguje a dostanu:

Nette\DI\ServiceCreationException
Service of type App\FrontModule\Factories\FormFactory: Service of type Nette\Bridges\ApplicationLatte\TemplateFactory needed by $templateFactory in __construct() not found. Did you add it to configuration file?
<?php

declare(strict_types = 1);

namespace App\FrontModule\Factories;

use App\Model\UserRepository;
use App\Model\FormRepository;
use App\Services\LocaleService;
use App\Services\ParamService;
use App\Services\RecaptchaService;
use Nette\Application\UI\TemplateFactory;
// use Nette\Bridges\ApplicationLatte\TemplateFactory;


class FormFactory
{
	private FormRepository $formRepository;
	private ParamService $paramService;
	private LocaleService $localeService;
	private RecaptchaService $recaptchaService;
  	private TemplateFactory $templateFactory;

	public function __construct(
		FormRepository $formRepository,
		ParamService $paramService,
		LocaleService $localeService,
		RecaptchaService $recaptchaService,
    	TemplateFactory $templateFactory
	)
	{
		$this->formRepository = $formRepository;
		$this->paramService = $paramService;
		$this->localeService = $localeService;
		$this->recaptchaService = $recaptchaService;
    	$this->templateFactory = $templateFactory;
	}

	public function createContactForm(): \ContactForm
	{
		return new \ContactForm(
			$this->formRepository,
			$this->paramService,
			$this->localeService,
			$this->recaptchaService,
      		$this->templateFactory
		);
	}
}

Control komponenty
V komponentě oproti tomu deklaruji že TemplateFactory z konstruktoru je třída Nette\Bridges\ApplicationLatte\TemplateFactory. To funguje.

<?php

declare(strict_types=1);

use Latte\Engine;
use Nette\Application\UI\Control;
use Nette\Application\UI\Form;
use Nette\Mail\Message;
use Nette\Mail\SendmailMailer;
use Nette\Utils\ArrayHash;
use App\Model\FormRepository;
use App\Services\LocaleService;
use App\Services\ParamService;
use App\Services\RecaptchaService;
use Tracy\Debugger;
use Nette\Bridges\ApplicationLatte\TemplateFactory;
use Nette\Bridges\ApplicationLatte\Template;

class ContactForm extends Control {

    public $onSuccess;
    public $onError;
    private FormRepository $formRepository;
    private ParamService $paramService;
    private LocaleService $localeService;
    private RecaptchaService $recaptchaService;
	private TemplateFactory $templateFactory;

    public function __construct(
        FormRepository $formRepository,
        ParamService $paramService,
        LocaleService $localeService,
        RecaptchaService $recaptchaService,
        TemplateFactory $templateFactory
    )
    {
        $this->formRepository = $formRepository;
        $this->paramService = $paramService;
        $this->localeService = $localeService;
        $this->recaptchaService = $recaptchaService;
        $this->templateFactory = $templateFactory;
    }

    public function render(): void
    {
        $this->template->setFile(__DIR__ . '/ContactForm.latte');
        $this->template->render();
    }

    public function createComponentForm(): Form
    {
        // not important
    }

    public function processForm(Form $form, ArrayHash $values): void
    {
        $paramContact = $this->paramService->getContact();
        $recaptcha = $this->recaptchaService->verifyRecaptcha($values->recaptcha_token);

        if ($recaptcha->success && $recaptcha->score > 0.49) {
            $mailer = new SendmailMailer;

            // Prepare Template object
            $template = $this->templateFactory->createTemplate();
			// Enable translations in emailTemplate.latte
            $template->getLatte()->addFilter('translate', [$this->localeService, 'translate']);

            // Mail to user
            $mailUser = new Message;
            $mailUser->setFrom($paramContact->email);
            $mailUser->addReplyTo($paramContact->email);
            $mailUser->setSubject($this->localeService->translate('ContactForm.userMailSubject'));
            $mailUser->setHtmlBody($template->renderToString(__DIR__ . '/ContactFormUserMail.latte', ['values' => $values]));
            $mailUser->addTo($values->email);

            // Send emails
            try {
                $mailer->send($mailUser);
                $this->presenter->flashMessage($this->localeService->translate('form.commonMessage.sendSuccess'), 'success');
            } catch (\Exception $e) {
                $this->presenter->flashMessage($this->localeService->translate('form.commonMessage.sendFailed'), 'error');
                Debugger::log(new \Exception($e->getMessage()));
            }
        } else {
            $this->presenter->flashMessage($this->localeService->translate('form.commonMessage.errorYouAreRobot'), 'error');
        }
        $this->redirect('this');
    }
}

Tudíž děje se nějaká podivnost pokud objekt třídy Nette\Bridges\ApplicationLatte\TemplateFactory předávám přes továrnu do konstruktoru komponenty.

Marek Bartoš
Nette Blogger | 1274
+
+1
-

Třídy se autowirují podle klíče type, nikoli factory, takže když je třída zaregistrována takto, tak jen ten type bude fungovat:

services:
	latte.templateFactory:
		create: Nette\Bridges\ApplicationLatte\TemplateFactory
		type: Nette\Application\UI\TemplateFactory

Ale pokud ji zaregistruje takto, tak se type vytvoří podle factory, a tedy je identický

services:
	latte.templateFactory:
		create: Nette\Bridges\ApplicationLatte\TemplateFactory
	# nebo zkráceně
	latte.templateFactory: Nette\Bridges\ApplicationLatte\TemplateFactory

https://github.com/…ion/pull/283

d@rkWolf
Člen | 167
+
0
-

Zrovna sem narazil na to samé, projel sem composer update a editor na mě začal řvát, že ITemplateFactory a ITemplate je deprecated…

Tak jsem to změnil na Nette\Bridges\ApplicationLatte\TemplateFactory a createTemplate(): Nette\Application\UI\Template a výsledek je:

Service of type App\Model\MailService: Service of type Nette\Bridges\ApplicationLatte\TemplateFactory needed by $templateFactory in __construct() not found. Did you add it to configuration file?

Samozřejmě v 3.1 verzi Mailing dokumentace u „Použití v Nette Application“ nic o tom, že aby to fungovalo, je nutné takto: latte.templateFactory: Nette\Bridges\ApplicationLatte\TemplateFactory registrovat tu template factory v neonu není.

David Grudl
Nette Core | 8227
+
+4
-

Ano, je to opravené v nette/application 3.1-dev.