Factory – problém s __construct()
- Newer
- Člen | 47
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)
- Elvis77
- Člen | 4
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
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
- d@rkWolf
- Člen | 167
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í.