Makro {link} v emailech od Nette 2.3 (hodně obsáhle)
- David Grudl
- Nette Core | 8215
Od Nette 2.3 je k dispozici nástroj LinkGenerator pro generování odkazů mimo presentery, ale se stejným komfortem.
Jak ho použít?
Mám teda nějakou třídu, která odesílá emaily, předám
ji LinkGenerator do proměnné $this->linkGenerator
a
vytvořím si objekt Latte.
Kód emailu může vypadat nějak takto:
<title>Subject of message</title>
<p>Hello {$name} <a n:href="Homepage:">click here</a></p>
A kód třídy:
class MailSender
{
/** @var Nette\Application\LinkGenerator */
private $linkGenerator;
function construct(Nette\Application\LinkGenerator $lg)
{
$this->linkGenerator = $lg;
}
function sendEmail()
{
$latte = new Latte\Engine;
$latte->setTempDirectory(...);
...
}
Nastavit temp directory je docela fajn, aby se šablona s každým emailem nemusela znovu kompilovat (pokud jich posíláte denně méně než pár set, v samostatných requestech, je to teda upřímně docela fuk), jenže kde vzít cestu k té složce? Můžeme si ji opět předat, ale chytřejší řešení je místo toho si předat objekt, tzv. továrničku, který dovede vyrobit Latte právě už s nastavenou cestou k temp dir:
/** @var Nette\Bridges\ApplicationLatte\ILatteFactory */
private $latteFactory;
// opět předáme přes konstruktor
function sendEmail()
{
$latte = $this->latteFactory->create();
// nainstaluji do $latte makra {link} a n:href
Nette\Bridges\ApplicationLatte\UIMacros::install($latte->getCompiler());
// a vygenerujeme HTML email
$html = $latte->renderToString(__DIR__ . '/email.latte', [
'name' => $order->getName(), // proměnné do šablony
....
]);
...
}
Tady ještě jednou přeruším, protože musím zmínit ještě jednu
alternativu, a to nechat si vygenerovat přímo známý objekt
$template
, už s nakonfigurovaným Latte. Vyměním tedy
latteFactory
za templateFactory
:
/** @var Nette\Application\UI\ITemplateFactory */
private $templateFactory;
// opět předáme přes konstruktor případně anotací @inject
function sendEmail()
{
$template = $this->templateFactory->createTemplate();
$template->name = $order->getName();
$html = (string) $template;
...
}
(Stejně jako templateFactory->createTemplate()
funguje i
$this->createTemplate()
uvnitř presenteru či komponenty, ale
vhodnější je odesílání emailů delegovat do samostatné třídy, protože
to není zodpovědnost presenterů. Vidíte, že to používání šablon nijak
neomezuje.)
Zbytek metody sendEmail
bude vypadat cca takto:
...
$mail = new Nette\Mail\Message;
$mail->addTo($order->email);
$mail->setHtmlBody($html); // nebo setHtmlBody($template)
$mailer->send($mail); // $mailer si opět předáme
}
A teď zbývá poslední krok! Zapojit do toho ten LinkGenerator, ke kterému jsem se dosud nedostal. Je to snadné, ale zatím ne intuitivní (intuitivní API teprve hledám).
Jednoduše generátor vložte do šablony do proměnné
_control
.
Tedy buď:
$params = array(
'name' => $order->getName(),
'_control' => $this->linkGenerator,
...
);
nebo
$template->_control = $this->linkGenerator;
podle toho, kterou cestou na to jdete.
A odkazy se začnou generovat.
- Climber007
- Člen | 105
Při linku obsahujícím cestu s modulem (:Front:Homepage:) LinkGenerator selže, že prý špatný název presenteru. Chyba nebo jsem udělal někde něco špatně?
- Climber007
- Člen | 105
Bez dvojtečky to samozřejmě jde, ale chtěl bych tu šablonu používat jak s LinkGenratorem, tak normálně v Presenteru. Jde o to, že by se to mělo chovat ve všech případech konzistentně.
- David Matějka
- Moderator | 6445
viz issue na gh: https://github.com/…on/issues/72, muzete poslat PR ;)
- Climber007
- Člen | 105
Díky, jsem blbej, tam jsem se zapomněl nepodívat. PR moc rád, nevím jak budu stíhat.
Editoval Climber007 (11. 9. 2015 19:59)