Jak dostat komponentu do Fasady
- libik
- Člen | 96
Ahoj,
morim se s injektaci komponenty do fasady. Co resim: mam komponentu mailer, ktera odesle mail s vyuzitim definovane sablony.
Komponenta:
<?php
namespace App\Controls\Mailer;
class MailerControl extends Control
{
}
interface IMailerFactory
{
/**
* @return MailerControl
*/
public function create();
}
?>
Base fasada:
<?php
namespace App\Model\Facades;
use Kdyby\Doctrine\EntityManager;
use App\Controls\Mailer\MailerControl;
class BaseFacade extends \Nette\Object
{
/** @var EntityManager */
protected $em;
/** @var MailerControl */
protected $mailer;
public function __construct(EntityManager $em, MailerControl $mailer)
{
$this->em = $em;
$this->mailer = $mailer;
}
}
?>
config.neon
services:
- App\Controls\Mailer\MailerControl
- App\Controls\Mailer\IMailerFactory
- App\Model\Facades\UserFacade
router: App\RouterFactory::createRouter
# Factories
- App\Forms\SignFormFactory
basepresenter
<?php
abstract class BasePresenter extends Presenter
{
/** @var IMailerFactory @inject */
public $mailerFactory;
/**
*
* @return MailerControl
*/
protected function createComponentMailer()
{
$control = $this->mailerFactory->create();
return $control;
}
}
?>
A ted si v SingInFactory po odeslani formulare chci zavolat metodu sendPasswordRecoveryInstructions(), ktera by odeslala email.
<?php
class SignFormFactory extends Object
{
/** @var EntityManager */
private $em;
/** @var UserFacade */
private $userFacade;
/** @var Translator */
private $translator;
/** @var User */
private $user;
/**
*
* @param UserFacade $userFacade
* @param Translator $translator
* @param User $user
* @param EntityManager $em
*/
public function __construct(UserFacade $userFacade, Translator $translator, User $user, EntityManager $em)
{
$this->userFacade = $userFacade;
$this->translator = $translator;
$this->user = $user;
$this->em = $em;
}
/**
*
* @param Form $form
* @param ArrayHash $values
*/
public function recoverSubmitted($form, $values)
{
try
{
$this->userFacade->sendPasswordRecoveryInstructions($values->email);
....
} catch (Exception $e)
{
}
}
}
?>
Proto chci do BaseFasade dostat komponentu MailerControl. No a nejak jsem se v tom ted ztratil :)
Kdyz si Mailer predam konstruktorem, Nette na me krici Component '' is not attached to ‚Nette\Application\UI\Presenter‘ kvuli
<?php
$template = $this->createTemplate();
?>
v komponente mailera.
- Navic nevim, jestli nemicham dve veci (zbytecne) v configu pri registraci komponenty a interface jako sluzby
- App\Controls\Mailer\MailerControl
- App\Controls\Mailer\IMailerFactory
A v Base presenteru mam
<?php
createComponentMailer()
?>
Tak jsem z toho jelen :)
- David Matějka
- Moderator | 6445
Nepouzivej na to komponentu, vytvor si sluzbu a sablonu vytvor dle treba https://phpfashion.com/…-a-nette-2-3
- libik
- Člen | 96
Jeste se k tomu vracim. Kdyz dle odkazu pouziju templateFactory, ladenka na me krici Circular reference detected for services: application.12, security.user, 103_App_Model_Facades_UserFacade, 104_App_Controls_Mailer_MailSender, latte.templateFactory.
S pouzitim latteFactory to ale funguje. Bojim se, aby ta kruhovita hlaska neznamenala nejakou zasadni chybu v navrhu.
Dle prvniho mailu jsem upravil
<?php
namespace App\Controls\Mailer;
use Nette\Mail\SendmailMailer;
use Nette\Mail\Message;
use Nette\Diagnostics\Debugger;
use Nette\Application\LinkGenerator;
use Kdyby\Translation\Translator;
use Nette\Bridges\ApplicationLatte\ILatteFactory;
use Nette\Bridges\ApplicationLatte\UIMacros;
class MailSender
{
/** @var Translator */
private $translator;
/** @var LinkGenerator */
private $linkGenerator;
/** @var ILatteFactory */
private $latteFactory;
/** @var UserEntity */
private $userEntity;
/** @var \Nette\Application\UI\ITemplateFactory */
private $templateFactory;
/**
* @param string $from
* @param Translator $translator
* @param LinkGenerator $linkGenerator
* @param \Nette\Application\UI\ITemplateFactory $templateFactory
*/
public function __construct($from, Translator $translator, LinkGenerator $linkGenerator, \Nette\Application\UI\ITemplateFactory $templateFactory)
{
$this->from = $from;
$this->translator = $translator;
$this->linkGenerator = $linkGenerator;
$this->templateFactory = $templateFactory;
}
...
?>
v configu jsem zaregistroval sluzbu
services:
- App\Controls\Mailer\MailSender(%email.defaultFrom%)
- App\Model\Facades\UserFacade
a v BaseEntity pripojuju v konstruktoru
<?php
<?php
namespace App\Model\Facades;
use Kdyby\Doctrine\EntityManager;
use App\Controls\Mailer\MailSender;
/**
* @package App\Model\Facades
*/
class BaseFacade extends \Nette\Object
{
/** @var EntityManager */
protected $em;
/** @var MailSender */
protected $mailSender;
/**
*
* @param EntityManager $em
* @param MailSender $mailSender
*/
public function __construct(EntityManager $em, MailSender $mailSender)
{
$this->em = $em;
$this->mailSender = $mailSender;
}
}
V BasePresenteru injectuju UserFacade (dedi od BaseFacade)
<?php
abstract class BasePresenter extends Presenter
{
/** @persistent null|string */
public $locale;
/**
* @var \Kdyby\Translation\Translator
* @inject
*/
public $translator;
/**
*
* @var UserFacade
* @inject
*/
public $userFacade;
?>
- David Matějka
- Moderator | 6445
Circular reference casto opravdu znaci nejakou chybu navrhu, ale vetsinou je resitelna. V tvem pripade to vypada, ze UserFacade implementuje IAuthenticator, ze? Resenim je proste pro authenticator udelat samostatnou tridu (a tu registrovat jako sluzbu). A delat co nejmensi tridy je obvykle best practise.
A mimochodem, to vyzadovani MailSender v BaseFacade neni prilis idealni. A Base* tridam je take obvykle se lepsi vyhnout :)
A posledni poznamka, na posilani mailu apod. jsou skvele eventy, konkretne treba kdyby/events