Şablonlar

Nette, Latte şablonlama sistemini kullanır. Bunun nedeni, hem PHP için en güvenli şablonlama sistemi olması hem de en sezgisel sistem olmasıdır. Çok fazla yeni şey öğrenmenize gerek yoktur, PHP bilginiz ve birkaç etiket yeterlidir.

Bir sayfanın bir layout şablonu + ilgili eylemin şablonundan oluşması yaygındır. Örneğin bir layout şablonu şöyle görünebilir, {block} bloklarına ve {include} etiketine dikkat edin:

<!DOCTYPE html>
<html>
<head>
	<title>{block title}Uygulamam{/block}</title>
</head>
<body>
	<header>...</header>
	{include content}
	<footer>...</footer>
</body>
</html>

Ve bu da eylemin şablonu olacaktır:

{block title}Ana Sayfa{/block}

{block content}
<h1>Ana Sayfa</h1>
...
{/block}

Bu, layout'taki {include content} yerine eklenecek olan content bloğunu tanımlar ve ayrıca layout'taki {block title} öğesinin üzerine yazacak olan title bloğunu yeniden tanımlar. Sonucu hayal etmeye çalışın.

Şablonları Bulma

Presenter'larda hangi şablonun oluşturulacağını belirtmeniz gerekmez, framework yolu kendisi türetir ve size yazmaktan tasarruf sağlar.

Her presenter'ın kendi dizinine sahip olduğu bir dizin yapısı kullanıyorsanız, şablonu basitçe bu dizine eylemin (veya view'in) adıyla yerleştirin, yani default eylemi için default.latte şablonunu kullanın:

app/
└── Presentation/
    └── Home/
        ├── HomePresenter.php
        └── default.latte

Presenter'ların birlikte tek bir dizinde ve şablonların templates klasöründe olduğu bir yapı kullanıyorsanız, onu ya <Presenter>.<view>.latte dosyasına ya da <Presenter>/<view>.latte dosyasına kaydedin:

app/
└── Presenters/
    ├── HomePresenter.php
    └── templates/
        ├── Home.default.latte  ← 1. seçenek
        └── Home/
            └── default.latte   ← 2. seçenek

templates dizini bir seviye yukarıda da yer alabilir, yani presenter sınıflarını içeren dizinle aynı seviyede.

Şablon bulunamazsa, presenter 404 – sayfa bulunamadı hatası ile yanıt verir.

View'i $this->setView('jineView') kullanarak değiştirirsiniz. Ayrıca şablon dosyasını doğrudan $this->template->setFile('/path/to/template.latte') kullanarak belirtebilirsiniz.

Şablonların arandığı dosyalar, olası dosya adları dizisini döndüren formatTemplateFiles() metodunu geçersiz kılarak değiştirilebilir.

Layout Şablonunu Bulma

Nette ayrıca layout dosyasını otomatik olarak bulur.

Her presenter'ın kendi dizinine sahip olduğu bir dizin yapısı kullanıyorsanız, layout'u ya yalnızca ona özelse presenter içeren klasöre ya da birden fazla presenter için ortaksa bir seviye yukarıya yerleştirin:

app/
└── Presentation/
    ├── @layout.latte           ← ortak layout
    └── Home/
        ├── @layout.latte       ← yalnızca Home presenter için
        ├── HomePresenter.php
        └── default.latte

Presenter'ların birlikte tek bir dizinde ve şablonların templates klasöründe olduğu bir yapı kullanıyorsanız, layout şu yerlerde beklenecektir:

app/
└── Presenters/
    ├── HomePresenter.php
    └── templates/
        ├── @layout.latte       ← ortak layout
        ├── Home.@layout.latte  ← yalnızca Home için, 1. seçenek
        └── Home/
            └── @layout.latte   ← yalnızca Home için, 2. seçenek

Presenter bir modülde bulunuyorsa, modülün iç içe geçme durumuna göre daha üst dizin seviyelerinde de aranacaktır.

Layout adı $this->setLayout('layoutAdmin') kullanılarak değiştirilebilir ve ardından @layoutAdmin.latte dosyasında beklenecektir. Ayrıca layout şablonu dosyasını doğrudan $this->setLayout('/path/to/template.latte') kullanarak belirtebilirsiniz.

$this->setLayout(false) veya şablon içindeki {layout none} etiketi kullanılarak layout araması kapatılır.

Layout şablonlarının arandığı dosyalar, olası dosya adları dizisini döndüren formatLayoutTemplateFiles() metodunu geçersiz kılarak değiştirilebilir.

Şablondaki Değişkenler

Değişkenleri şablona $this->template'e yazarak iletiriz ve ardından şablonda yerel değişkenler olarak kullanılabilirler:

$this->template->article = $this->articles->getById($id);

Bu şekilde herhangi bir değişkeni şablonlara kolayca iletebiliriz. Ancak sağlam uygulamalar geliştirirken kendimizi sınırlamak daha yararlı olur. Örneğin, şablonun beklediği değişkenlerin listesini ve türlerini açıkça tanımlayarak. Bu sayede PHP türleri kontrol edebilir, IDE doğru şekilde öneride bulunabilir ve statik analiz hataları ortaya çıkarabilir.

Ve böyle bir listeyi nasıl tanımlarız? Basitçe bir sınıf ve onun özellikleri şeklinde. Onu presenter'a benzer şekilde adlandırırız, ancak sonunda Template ile:

/**
 * @property-read ArticleTemplate $template
 */
class ArticlePresenter extends Nette\Application\UI\Presenter
{
}

class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template
{
	public Model\Article $article;
	public Nette\Security\User $user;

	// ve diğer değişkenler
}

Presenter'daki $this->template nesnesi artık ArticleTemplate sınıfının bir örneği olacaktır. Böylece PHP yazarken bildirilen türleri kontrol edecektir. Ve PHP 8.2 sürümünden itibaren, mevcut olmayan bir değişkene yazma konusunda da uyaracaktır, önceki sürümlerde aynı şeye Nette\SmartObject trait'ini kullanarak ulaşılabilir.

@property-read ek açıklaması IDE ve statik analiz içindir, sayesinde öneri işlevi çalışacaktır, bkz. PhpStorm and code completion for $this⁠-⁠>⁠template.

Öneri lüksünün tadını şablonlarda da çıkarabilirsiniz, sadece PhpStorm'a Latte eklentisini kurmanız ve şablonun başına sınıf adını belirtmeniz yeterlidir, daha fazla bilgi için Latte: tür sistemi nasıl kullanılır makalesine bakın:

{templateType App\Presentation\Article\ArticleTemplate}
...

Bu şekilde bileşenlerdeki şablonlar da çalışır, sadece adlandırma kuralına uymanız ve örneğin FifteenControl bileşeni için FifteenTemplate şablon sınıfını oluşturmanız yeterlidir.

$template'i farklı bir sınıfın örneği olarak oluşturmanız gerekiyorsa, createTemplate() metodunu kullanın:

public function renderDefault(): void
{
	$template = $this->createTemplate(SpecialTemplate::class);
	$template->foo = 123;
	// ...
	$this->sendTemplate($template);
}

Varsayılan Değişkenler

Presenter'lar ve bileşenler, şablonlara otomatik olarak birkaç yararlı değişken iletir:

  • $basePath, kök dizine mutlak URL yoludur (örn. /eshop)
  • $baseUrl, kök dizine mutlak URL'dir (örn. http://localhost/eshop)
  • $user, kullanıcıyı temsil eden nesnedir
  • $presenter, mevcut presenter'dır
  • $control, mevcut bileşen veya presenter'dır
  • $flashes, flashMessage() fonksiyonu tarafından gönderilen mesajlar dizisidir

Kendi şablon sınıfınızı kullanıyorsanız, bu değişkenler için bir özellik oluşturursanız iletilirler.

Bağlantı Oluşturma

Şablonda, diğer presenter'lara ve eylemlere bağlantılar şu şekilde oluşturulur:

<a n:href="Product:show">ürün detayı</a>

n:href niteliği HTML <a> etiketleri için çok kullanışlıdır. Bağlantıyı başka bir yerde, örneğin metinde yazdırmak istiyorsak, {link} kullanırız:

Adres: {link Home:default}

Daha fazla bilgi için URL Bağlantıları Oluşturma bölümünde bulabilirsiniz.

Özel Filtreler, Etiketler vb.

Latte şablonlama sistemi özel filtreler, fonksiyonlar, etiketler vb. ile genişletilebilir. Bu, doğrudan render<View> veya beforeRender() metodunda yapılabilir:

public function beforeRender(): void
{
	// filtre ekleme
	$this->template->addFilter('foo', /* ... */);

	// veya doğrudan Latte\Engine nesnesini yapılandırırız
	$latte = $this->template->getLatte();
	$latte->addFilterLoader(/* ... */);
}

Latte sürüm 3, her web projesi için bir extension oluşturarak daha gelişmiş bir yol sunar. Böyle bir sınıfın kaba bir örneği:

namespace App\Presentation\Accessory;

final class LatteExtension extends Latte\Extension
{
	public function __construct(
		private App\Model\Facade $facade,
		private Nette\Security\User $user,
		// ...
	) {
	}

	public function getFilters(): array
	{
		return [
			'timeAgoInWords' => $this->filterTimeAgoInWords(...),
			'money' => $this->filterMoney(...),
			// ...
		];
	}

	public function getFunctions(): array
	{
		return [
			'canEditArticle' =>
				fn($article) => $this->facade->canEditArticle($article, $this->user->getId()),
			// ...
		];
	}

	// ...
}

Onu yapılandırma kullanarak kaydederiz:

latte:
	extensions:
		- App\Presentation\Accessory\LatteExtension

Çeviri

Çok dilli bir uygulama programlıyorsanız, muhtemelen şablondaki bazı metinleri farklı dillerde yazdırmanız gerekecektir. Nette Framework bu amaçla tek bir metodu translate() olan Nette\Localization\Translator çeviri arayüzünü tanımlar. Bu metot, genellikle bir dize olan $message mesajını ve isteğe bağlı diğer parametreleri alır. Görevi, çevrilmiş dizeyi döndürmektir. Nette'de varsayılan bir uygulama yoktur, ihtiyaçlarınıza göre Componette adresinde bulabileceğiniz birkaç hazır çözüm arasından seçim yapabilirsiniz. Belgelerinde çevirmeni nasıl yapılandıracağınızı öğreneceksiniz.

Şablonlara, setTranslator() metoduyla bize iletilmesini istediğimiz bir çevirmen ayarlanabilir:

protected function beforeRender(): void
{
	// ...
	$this->template->setTranslator($translator);
}

Çevirmen alternatif olarak yapılandırma kullanılarak ayarlanabilir:

latte:
	extensions:
		- Latte\Essential\TranslatorExtension(@Nette\Localization\Translator)

Ardından çevirmen örneğin |translate filtresi olarak kullanılabilir ve translate() metoduna iletilen ek parametreler dahil (bkz. foo, bar):

<a href="basket">{='Sepet'|translate}</a>
<span>{$item|translate}</span>
<span>{$item|translate, foo, bar}</span>

Veya alt çizgi etiketi olarak:

<a href="basket">{_'Sepet'}</a>
<span>{_$item}</span>
<span>{_$item, foo, bar}</span>

Şablonun bir bölümünü çevirmek için eşli {translate} etiketi vardır (Latte 2.11'den itibaren, daha önce {_} etiketi kullanılırdı):

<a href="order">{translate}Sipariş{/translate}</a>
<a href="order">{translate foo, bar}Sipariş{/translate}</a>

Çevirmen standart olarak şablon oluşturulurken çalışma zamanında çağrılır. Ancak Latte sürüm 3, tüm statik metinleri şablon derlemesi sırasında çevirebilir. Bu, her dize yalnızca bir kez çevrildiği ve sonuçtaki çeviri derlenmiş forma yazıldığı için performanstan tasarruf sağlar. Önbellek dizininde, her dil için bir tane olmak üzere şablonun birden fazla derlenmiş sürümü oluşturulur. Bunun için dili ikinci parametre olarak belirtmek yeterlidir:

protected function beforeRender(): void
{
	// ...
	$this->template->setTranslator($translator, $lang);
}

Statik metin derken örneğin {_'merhaba'} veya {translate}merhaba{/translate} kastedilir. {_$foo} gibi statik olmayan metinler çalışma zamanında çevrilmeye devam edecektir.

versiyon: 4.0