V Nette je k dispozici nástroj LinkGenerator pro vytváření odkazů bez nutnosti použití presenterů a přitom stejně pohodlně. Jak ho použít?
Ukážeme si to na příkladu třídy, která odesílá emaily. Kód emailu může vypadat nějak takto: (všechny příklady jsou pro Nette 2.4 nebo vyšší)
<title>Subject of message</title>
<p>Hello {$name} <a n:href="Homepage:">click here</a></p>
Třídě předám
LinkGenerator a ta si jej uloží do proměnné
$this->linkGenerator
.
class MailSender
{
/** @var Nette\Application\LinkGenerator */
private $linkGenerator;
function __construct(Nette\Application\LinkGenerator $generator)
{
$this->linkGenerator = $generator;
}
Samotné odesílání emailů bude provádět metoda sendEmail
,
která si vytvoří objekt Latte:
function sendEmail()
{
$latte = new Latte\Engine;
$latte->setTempDirectory(...);
...
}
U Latte je vhodné nastavit temp directory , aby se šablona s každým
emailem nemusela znovu kompilovat, nicméně pokud jich posíláte jen několik
denně, nebo třeba hodně, ale v jednom requestu (tj. pomocí jednoho objektu
$latte
), není to nutné, kompilace je blesková. Kde cestu k temp
složce vzít? 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
nakonfigurované Latte vyrobit:
/** @var Nette\Bridges\ApplicationLatte\ILatteFactory */
private $latteFactory;
// $latteFactory opět předáme přes konstruktor
function sendEmail()
{
$latte = $this->latteFactory->create();
// nainstalujeme do $latte makra {link} a n:href
Nette\Bridges\ApplicationLatte\UIMacros::install($latte->getCompiler());
$params = [ // proměnné do šablony
'name' => $order->getName(),
...
];
// a vygenerujeme HTML email
$html = $latte->renderToString(__DIR__ . '/email.latte', $params);
// a odešleme jej, viz dále
}
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
, který bude obsahovat například proměnné
$basePath
apod, už s nakonfigurovaným Latte. Vyměním tedy
latteFactory
za templateFactory
:
/** @var Nette\Application\UI\ITemplateFactory */
private $templateFactory;
// $templateFactory si opět předáme přes konstruktor
function sendEmail()
{
$template = $this->templateFactory->createTemplate();
$template->name = $order->getName();
$template->setFile(__DIR__ . '/email.latte');
}
Jde o obdobu použití $this->createTemplate()
uvnitř
presenteru či komponenty.
Zbytek metody sendEmail
bude vypadat takto:
...
$mail = new Nette\Mail\Message;
$mail->addTo($order->email);
$mail->setHtmlBody($html); // nebo setHtmlBody($template)
$this->mailer->send($mail); // $mailer si opět předáme konstruktorem
}
A teď zbývá poslední krok! Zapojit do toho LinkGenerator, ke kterému se konečně dostávám. Je to snadné:
Tedy buď (pokud si předáváme latteFactory
):
$latte->addProvider('uiControl', $this->linkGenerator);
nebo (pokud jdeme cestou templateFactory
):
$template->getLatte()->addProvider('uiControl', $this->linkGenerator);
O té chvíle můžete používat makro {link}
nebo
n:href
.
LinkGenerator generuje všechny URL absolutní, tedy včetně
http://example.com
. Taktéž na moduly pohlíží absolutně,
tudíž v odkazech neuvádějte na začátku dvojtečku ani //
,
není to potřeba a vlastně tomu ani nebude rozumět.
Pokud v routeru používáte relativní cesty, což je velmi časné, generátor bere doménu z aktuálního HTTP requestu. Ale v CLI žádný HTTP request pochopitelně neexistuje. Lze jej však podstrčit třeba v config.neon:
services:
application.linkGenerator:
arguments:
refUrl: Nette\Http\UrlScript('http://example.com')
Celý kód by vypadal tedy nějak takto:
<?php
use Nette\Application\LinkGenerator;
use Nette\Bridges\ApplicationLatte\ILatteFactory;
use Nette\Mail\IMailer;
class MailSender
{
/** @var LinkGenerator */
private $linkGenerator;
/** @var ILatteFactory */
private $latteFactory;
/** @var IMailer */
private $mailer;
function __construct(LinkGenerator $generator, ILatteFactory $latteFactory, IMailer $mailer)
{
$this->linkGenerator = $generator;
$this->latteFactory = $latteFactory;
$this->mailer = $mailer;
}
function sendEmail()
{
$latte = $this->latteFactory->create();
// nainstalujeme do $latte makra {link} a n:href
Nette\Bridges\ApplicationLatte\UIMacros::install($latte->getCompiler());
$latte->addProvider('uiControl', $this->linkGenerator);
//$order = ...;
$params = [
'name' => $order->getName(),
// ...
];
$html = $latte->renderToString(__DIR__ . '/email.latte', $params);
$mail = new Nette\Mail\Message;
$mail->addTo($order->email);
$mail->setHtmlBody($html);
$this->mailer->send($mail);
}
}
Komentáře
zolo14 #1
a čo v prípade ak generujem odkazy mimo http, teda v cli, ako do odkazov dostanem doménu? lebo takto mi to vygeneruje odkaz http://presenter/action
petr #2
tak skoro čtyři stránky textu o tom, jak vložit odkaz do emailu, přečteny. A jsem žhavý na další díl. Ale Nette asi budu raději používat na něco jiného:)
David Grudl #3
#1 zolo14, jo, tohle je trošku tricky, doplnil jsem to do článku
Bohouš #4
Jak do templateFactory předám info, jakou šablonu má použít?
Honza #5
#4 Bohouši, řekl bych, že nějak takhle:
Tento článek byl uzavřen. Už není možné k němu přidávat komentáře.