Odeslání emailu z Modelu, zpřístupnění presenter z Modelu pro LiveTranslator
- kralik
- Člen | 230
Ahoj,
prosím o radu jak mohu správně udělat následující chování.
Nějak se s tím peru a nedaří se mi.
Používám Model (nejen) pro přístup k datům z databáze. Rád bych aby aplikace posílala emaily právě z Modelu, což mi přijde dobré umístění pro odesílání emailů.
V aplikaci ještě používám LiveTranslator.
Takto se obdobně snažím o emaily:
<?php
$latte = new Latte\Engine;
$params = array(
'orderId' => 123,
);
$mail = new Message;
$mail->setFrom('Franta <franta@example.com>')
->addTo('petr@example.com')
->setHtmlBody($latte->renderToString('email.latte', $params));`
?>
Nette mi napíše že „Filter ‚translate‘ is not
defined.“
Nevím jak si do Modelu mohu přidat Presenter abych mohl použít
něco jako
<?php
$template->setTranslator($this->getPresenter->translator);
?>
Moc díky
- ViPEr*CZ*
- Člen | 817
Pár postřehů… Už bych tomu neříkal model, ale nějaká business třída. Používáš MVC architektůru… ? Tak co je modelu po Presenteru? Model si nechte prostě modelem. Translátor je jen nějaká services, tak proč cpát business třídě celej Presenter? Přes DI si předejte do business třídy objekt translatoru.
- kralik
- Člen | 230
Díky,
ale prosím ještě jednou pro ty vzadu.
Ano používám MVC architekturu.
Mužete někdo poskytnou přímo kód jak vytvořit samostatnou třídu a
předat si do ni translator?
S OOP ještě nejsem uplně kamarád.
Také nepotřebuji celý presenter, ale líbí se mi toto „Přes DI si
předejte do business třídy objekt translatoru.“
Ale nevím jak s tím.
Moc díky
- ViPEr*CZ*
- Člen | 817
Zkuste: https://doc.nette.org/…dependencies
Jednoduše vytvoříte-li třídu a v jejím konstruktoru uvedente nějakou
závislost (musíte uvést type hint závislosti), pak pokud takovou třídu
zaregistrujete v konfiguraci, tak Nette se Vám postará o vytvoření objektu
a v systémovém kontejneru vyhledá právě podle type hintu onu závislost a
použije ji.
Nadmíru je jasné, že ona závislost musí také existovat v systémovém
kontejneru. Buď si jí tedy musíte také registrovat v konfiguraci a nebo to
je nějaká služba, kterou interně vytváří automaticky samo Nette.
Váš translátor by měl mít type hint nějaký interface ITranslator.
Tuto koncovou službu (business třídu) už si injectnete do Presenteru a
použijete v příslušném obslužném kódu.
- David Matějka
- Moderator | 6445
Template, ktery znas z presenteru, je jednoduchy wapper kolem Latte\Engine. Pokud chces pouzivat primo Latte\Engine, tak tam translator dostanes pridanim filteru, viz implementace v Template
Ale Latte\Engine nevytvarej rucne, pouzij ILatteFactory, pripadne muzes rovnou pouzit ITemplateFactory, ktery ti prave vytvori onu znamou template z presenteru. Precti si https://phpfashion.com/…-a-nette-2-3, sice je to o odkazech, ale velmi se to prave dotyka pouziti sablon v emailech.
- kralik
- Člen | 230
Ahoj,
tak jsem se pokoušel z „Generování odkazů v emailech“, ale moc jsem to
nepochopil.
Zkouším to takto:
<?php
<?php
class MailSender
{
/** @var Nette\Application\LinkGenerator */
private $linkGenerator;
/** @var Nette\Application\UI\ITemplateFactory */
private $templateFactory;
function construct(Nette\Application\LinkGenerator $generator)
{
$this->linkGenerator = $generator;
}
function sendEmail()
{
$template = $this->templateFactory->createTemplate();
$template->name = 'Test';
$template->setFile(WWW_DIR.'/../app/templates/Home/notif.latte');
Tracy\Debugger::barDump($template,'sablonaEmailu');
$template->_control = $this->linkGenerator;
$mail = new Nette\Mail\Message;
$mail->addTo('test@test.com');
$mail->setHtmlBody($template); // nebo setHtmlBody($template)
//$mailer->send($mail);
}
}
?>
A samotný email poslat takto:
<?php
\MailSender::sendEmail();
?>
Zatím jsem to zkoušel s tím LinkGenerátor.
Nette mi
hlásí Non-static method MailSender::sendEmail() should not be called statically, assuming $this from incompatible context
Místo toho
function construct(Nette\Application\LinkGenerator $generator)
si
předám
function construct(\LiveTranslator\Translator $translator)
?
Dostanu se nějak ke svému modelu abych dotáhl data z DB?
$dM = $this->mainModel->getMailData()
Kdybyste mi prosím poradili na zcela konkrétní třídě viz. výše.
Moc díky
- David Matějka
- Moderator | 6445
Registrujes to jako sluzbu, kterou si vyzadas, viz treba: https://doc.nette.org/…dependencies
a jeste treba video z posoboty
- ViPEr*CZ*
- Člen | 817
Bude nutné se naučit nějaké základy. Btw funkci sendMail() ani staticky zavolat nemůže jak jste to naznačil.
<?php
\MailSender::sendEmail();
?>
Toto je špatně!!!! A proč???
Protože $template->_control = $this->linkGenerator;
$this->linkGenerator bude null a to jste zajisté nezamýšlel :-)
Jak píše David. Musíte to registrovat jako službu. Tím zajistíte v případě potřeby zavolání konstruktoru a díky DI splnění závislostí.
- kralik
- Člen | 230
Ahoj,
tak jsem zhlédl nějaká videa o DI a přečetl odkazované články a
bohužel je to nad mé síly.
Dostal jsem se do bodu, kdy mám následující.
Samostatnou třídu:
<?php
use Nette\Mail\SendmailMailer;
class PosliMailFactory
{
protected $defaultFrom;
/** @var Nette\Application\UI\ITemplateFactory */
protected $templateFactory;
protected $translator;
public function __construct($defaultFrom, Nette\Application\UI\ITemplateFactory $templateFactory, \LiveTranslator\Translator $translator) {
$this->defaultFrom = $defaultFrom;
$this->templateFactory = $templateFactory;
$this->translator = $translator;
}
public function sendEmail()
{
$template = $this->templateFactory->createTemplate();
$template->name = 'Test';
$template->setFile(WWW_DIR.'/../app/templates/Home/notif.latte');
//
Tracy\Debugger::barDump($template,'sablonaEmailu');
//
// //$template->_control = $this->translator;
//
// $mail = new Nette\Mail\Message;
// $mail->addTo('test@test.com');
// $mail->setHtmlBody($template); // nebo setHtmlBody($template)
//
// $mailer = new SendmailMailer;
// $mailer->send($mail);
}
}
?>
V config.neon
<?php
parameters:
mailFrom: "test@test.cz"
...
services:
- PosliMailFactory(%mailFrom%)
...
?>
V BasePresenteru:
<?php
/** @var \PosliMailFactory */
protected $posliMail;
...
public function injectPosliMail(\PosliMailFactory $posliMail) {
$this->posliMail = $posliMail;
}
?>
A nakonec v Presenteru
<?php
...
$this->posliMail->sendEmail();
...
?>
Nette mi vyhazuje chybu:
Argument 1 passed to Nette\Bridges\ApplicationLatte\TemplateFactory::createTemplate() must be an instance of Nette\Application\UI\Control, none given, called in D:\wamp5416\www\gap\app\model\PosliMail.php on line 32 and defined
je to u
$template = $this->templateFactory->createTemplate();
Vůbec netuším zda jdu správnou cestou a je tam jen něco málo špatně,
nebo je to úplně z cesty?
Prosím poraďte.
Díky
- ViPEr*CZ*
- Člen | 817
Chyba vychází z dokumentace:
https://api.nette.org/…Factory.html#…
Ta metoda chce 1 parametr. Vy jste ji nepředal nic. Navíc to má být
Control.
Ku příkladu presenter vytváří template takto:
/**
* @return ITemplate
*/
protected function createTemplate()
{
return $this->getTemplateFactory()->createTemplate($this);
}
Takže třeba přes Vaší sendEmail udělejte také nutnost 1× parametru typu Control a ten pak předejte createTemplate(…). Jinak takhle asi ok.
- kralik
- Člen | 230
ViPErCZ napsal(a):
Chyba vychází z dokumentace:
https://api.nette.org/…Factory.html#…Ta metoda chce 1 parametr. Vy jste ji nepředal nic. Navíc to má být Control.
Ku příkladu presenter vytváří template takto:/** * @return ITemplate */ protected function createTemplate() { return $this->getTemplateFactory()->createTemplate($this); }
Takže třeba přes Vaší sendEmail udělejte také nutnost 1× parametru typu Control a ten pak předejte createTemplate(…). Jinak takhle asi ok.
Používám Nette 2.2.10
Můžete prosím uvést jak konkrétně udělat to předávání Control
přes sendEmail().
Resp. Jaký přesně Control předávat?
Mám vytvořit nějaký vymyšlený Control?
Vím, že jsou to blbé otázky, ale tohle zatím netuším jak provedu.
Potřebuji, a poprosím, zcela o konkrétní příklad.
Moc díky
- ViPEr*CZ*
- Člen | 817
sendMail(Nette\Application\UI\Control $control) {
$template = $this->templateFactory->createTemplate($control);
...
}
v presenteru pak
$this->posliMail->sendEmail($this);
jak prosté. Kdyby jste si to přečetl co jsem psal. Presenter vytváří
šablonu tak, že factory latte předá sám sebe. Presenter je taky Control :-)
No a přes parametr sendMail ho předáte do objektu a dál také té samé
factory.
Pokud aktualizujete na 2.3.x tak už nic předávat nebudete nejspíše muset
(viz. co psal David).
- kralik
- Člen | 230
Super, jste skvělí.
Mooc děkuji.
Doufám, že jednout také budu na vaší nynější Nette úrovni.
Pro lidi jako jsem já, přikládám kompletní plně funkční třídu:
<?php
use Nette\Mail\SendmailMailer;
class PosliMailFactory extends Nette\Object
{
protected $defaultFrom;
/** @var Nette\Application\UI\ITemplateFactory */
protected $templateFactory;
/** @var App\Model\Main */
protected $mainModel;
protected $translator;
public function __construct($defaultFrom, Nette\Application\UI\ITemplateFactory $templateFactory, \LiveTranslator\Translator $translator,App\Model\Main $mainModel) {
$this->defaultFrom = $defaultFrom;
$this->templateFactory = $templateFactory;
$this->translator = $translator;
$this->mainModel = $mainModel;
}
public function sendEmail($co,$aid,$RecipEmail,Nette\Application\UI\Control $control)
{
if($RecipEmail){
$ukol = $this->mainModel->getActionNotif($aid);
$params = array(
'co' => $co,
'maction' => $ukol['Action'],
'msubject' => $ukol['Subject']
);
$template = $this->templateFactory->createTemplate($control);
$template->params = $params;
$template->setTranslator($this->translator);
if($control->lang == 'cs'){
$template->setFile(WWW_DIR.'/../app/templates/Home/notifCS.latte');
}elseif($control->lang == 'en'){
$template->setFile(WWW_DIR.'/../app/templates/Home/notifEN.latte');
}else{
$template->setFile(WWW_DIR.'/../app/templates/Home/notifEN.latte');
}
$template->setTranslator($this->translator);
$mailer = new Nette\Mail\SendmailMailer(array(
'host' => 'mujserver.domena.cz'
));
$mail = new Nette\Mail\Message;
$mail->setHtmlBody($template);
if(is_array($RecipEmail)){
foreach ($RecipEmail as $k => $re) {
$mail->addTo($re);
}
}else{
$mail->addTo($RecipEmail);
}
$mail->setFrom($this->defaultFrom)
->setSubject('Předmět');
$mailer->send($mail);
return $res;
}
}
}
?>
V Presenteru:
<?php
$this->posliMail->sendEmail('new',$aid,$RecipEmail,$this);
?>
Ještě jednou díky