Na navigaci | Klávesové zkratky

Translate to English… Ins Deutsche übersetzen…

Generování odkazů kupříkladu v emailech a Nette

Od Nette 2.3 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:

<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();

    // nainstalujme 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
        ....
    ]);

    // 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)

    $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é, nicméně liší se to v Latte 2.3 a 2.4:

Tedy buď:

$params = array(
    'name' => $order->getName(),
    '_control' => $this->linkGenerator, // pro Latte 2.3
    ...
);
$latte->addProvider('uiControl', $this->linkGenerator); // pro Latte 2.4
$html = $latte->renderToString(__DIR__ . '/email.latte', $params);

nebo

$template->_control = $this->linkGenerator; // pro Latte 2.3
$template->getLatte()->addProvider('uiControl', $this->linkGenerator); // pro Latte 2.4

podle toho, zda používáte latteFactory nebo templateFactory.

O té chvíle můžete používat makro {link} nebo n:href.

Všechny odkazy se budou generovat absolutní, tedy včetně http://example.com. Pokud router používá 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 bootstrapu:

$configurator->addServices([
    'http.request' => new Nette\Http\Request(new Nette\Http\UrlScript('http://example.com')),
]);

Komentáře

  1. zolo14 #1

    avatar

    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

    před rokem | odpovědět | reagoval [3] David Grudl
  2. petr #2

    avatar

    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:)

    před rokem | odpovědět
  3. David Grudl http://davidgrudl.com #3

    avatar

    #1 zolo14, jo, tohle je trošku tricky, doplnil jsem to do článku

    před rokem | odpovědět
  4. Bohouš #4

    Jak do templateFactory předám info, jakou šablonu má použít?

    před rokem | odpovědět | reagoval [5] Honza
  5. Honza #5

    avatar

    #4 Bohouši, řekl bych, že nějak takhle:

    $template->setFile(__DIR__ . '/template.latte');
    před rokem | odpovědět

Zanechat komentář

Text komentáře
Kontakt

(kvůli gravataru)



*kurzíva* **tučné** "odkaz":http://example.com /--php phpkod(); \--