Na navigaci | Klávesové zkratky

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

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

  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 9 lety | 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 9 lety
  3. David Grudl #3

    avatar

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

    před 9 lety
  4. Bohouš #4

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

    před 9 lety | reagoval [5] Honza
  5. Honza #5

    avatar

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

    $template->setFile(__DIR__ . '/template.latte');
    před 9 lety

Tento článek byl uzavřen. Už není možné k němu přidávat komentáře.


phpFashion © 2004, 2024 David Grudl | o blogu

Ukázky zdrojových kódů smíte používat s uvedením autora a URL tohoto webu bez dalších omezení.